summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt15
-rw-r--r--CONTRIBUTORS1
-rw-r--r--Install/SQLiteCpp-LICENSE.txt20
-rw-r--r--Install/Zip2008.list1
-rw-r--r--MCServer/Plugins/APIDump/APIDesc.lua49
-rw-r--r--MCServer/Plugins/APIDump/Classes/BlockEntities.lua26
-rw-r--r--MCServer/Plugins/APIDump/Hooks/OnEntityAddEffect.lua33
-rw-r--r--MCServer/Plugins/APIDump/Hooks/OnPlayerMoving.lua4
-rw-r--r--MCServer/Plugins/APIDump/Hooks/OnPlayerUsedBlock.lua2
m---------MCServer/Plugins/Core0
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua121
-rw-r--r--MCServer/Plugins/DiamondMover/DiamondMover.lua8
m---------MCServer/Plugins/ProtectionAreas0
-rw-r--r--MCServer/furnace.txt1
-rw-r--r--MCServer/monsters.ini8
-rw-r--r--README.md2
-rw-r--r--SetFlags.cmake18
-rw-r--r--Tools/MCADefrag/CMakeLists.txt6
-rw-r--r--Tools/MCADefrag/Globals.h2
-rw-r--r--Tools/MCADefrag/MCADefrag.cpp16
-rw-r--r--Tools/ProtoProxy/CMakeLists.txt6
m---------lib/SQLiteCpp0
-rw-r--r--lib/inifile/iniFile.cpp27
-rw-r--r--lib/inifile/iniFile.h2
-rw-r--r--lib/tolua++/src/bin/lua/_driver.lua33
-rw-r--r--src/AllocationPool.h8
-rw-r--r--src/Bindings/AllToLua.pkg4
-rw-r--r--src/Bindings/AllToLua_lua.bat (renamed from src/Bindings/AllToLua_lua.bat.bat)0
-rw-r--r--src/Bindings/CMakeLists.txt136
-rw-r--r--src/Bindings/DeprecatedBindings.cpp77
-rw-r--r--src/Bindings/DeprecatedBindings.h2
-rw-r--r--src/Bindings/LuaChunkStay.cpp2
-rw-r--r--src/Bindings/LuaFunctions.h4
-rw-r--r--src/Bindings/LuaState.cpp7
-rw-r--r--src/Bindings/LuaState.h2
-rw-r--r--src/Bindings/LuaWindow.cpp4
-rw-r--r--src/Bindings/ManualBindings.cpp399
-rw-r--r--src/Bindings/ManualBindings.h2
-rw-r--r--src/Bindings/Plugin.h20
-rw-r--r--src/Bindings/PluginLua.cpp49
-rw-r--r--src/Bindings/PluginLua.h9
-rw-r--r--src/Bindings/PluginManager.cpp83
-rw-r--r--src/Bindings/PluginManager.h32
-rw-r--r--src/Bindings/WebPlugin.cpp34
-rw-r--r--src/Bindings/WebPlugin.h8
-rw-r--r--src/Bindings/gen_LuaState_Call.lua4
-rw-r--r--src/BiomeDef.cpp5
-rw-r--r--src/BlockArea.cpp16
-rw-r--r--src/BlockArea.h4
-rw-r--r--src/BlockEntities/BeaconEntity.cpp301
-rw-r--r--src/BlockEntities/BeaconEntity.h79
-rw-r--r--src/BlockEntities/BlockEntity.cpp10
-rw-r--r--src/BlockEntities/BlockEntity.h6
-rw-r--r--src/BlockEntities/BlockEntityWithItems.h2
-rw-r--r--src/BlockEntities/CMakeLists.txt42
-rw-r--r--src/BlockEntities/ChestEntity.cpp13
-rw-r--r--src/BlockEntities/ChestEntity.h21
-rw-r--r--src/BlockEntities/CommandBlockEntity.cpp2
-rw-r--r--src/BlockEntities/CommandBlockEntity.h6
-rw-r--r--src/BlockEntities/DropSpenserEntity.cpp10
-rw-r--r--src/BlockEntities/DropSpenserEntity.h14
-rw-r--r--src/BlockEntities/EnderChestEntity.h4
-rw-r--r--src/BlockEntities/FlowerPotEntity.cpp2
-rw-r--r--src/BlockEntities/FlowerPotEntity.h8
-rw-r--r--src/BlockEntities/FurnaceEntity.cpp2
-rw-r--r--src/BlockEntities/HopperEntity.cpp61
-rw-r--r--src/BlockEntities/HopperEntity.h3
-rw-r--r--src/BlockEntities/JukeboxEntity.h4
-rw-r--r--src/BlockEntities/MobHeadEntity.h6
-rw-r--r--src/BlockEntities/NoteEntity.cpp2
-rw-r--r--src/BlockEntities/NoteEntity.h17
-rw-r--r--src/BlockEntities/RedstonePoweredEntity.h13
-rw-r--r--src/BlockEntities/SignEntity.h6
-rw-r--r--src/BlockID.cpp41
-rw-r--r--src/BlockID.h22
-rw-r--r--src/BlockInfo.cpp334
-rw-r--r--src/BlockInfo.h10
-rw-r--r--src/BlockTracer.h16
-rw-r--r--src/Blocks/BlockAnvil.h2
-rw-r--r--src/Blocks/BlockBed.cpp22
-rw-r--r--src/Blocks/BlockBed.h2
-rw-r--r--src/Blocks/BlockBigFlower.h16
-rw-r--r--src/Blocks/BlockButton.h6
-rw-r--r--src/Blocks/BlockCake.h2
-rw-r--r--src/Blocks/BlockCarpet.h2
-rw-r--r--src/Blocks/BlockCauldron.h18
-rw-r--r--src/Blocks/BlockChest.h48
-rw-r--r--src/Blocks/BlockCloth.h7
-rw-r--r--src/Blocks/BlockComparator.h2
-rw-r--r--src/Blocks/BlockCrops.h2
-rw-r--r--src/Blocks/BlockDirt.h2
-rw-r--r--src/Blocks/BlockDoor.cpp4
-rw-r--r--src/Blocks/BlockDoor.h2
-rw-r--r--src/Blocks/BlockDropSpenser.h6
-rw-r--r--src/Blocks/BlockEnderchest.h2
-rw-r--r--src/Blocks/BlockFarmland.h16
-rw-r--r--src/Blocks/BlockFenceGate.h3
-rw-r--r--src/Blocks/BlockFire.h53
-rw-r--r--src/Blocks/BlockFlower.h2
-rw-r--r--src/Blocks/BlockFluid.h2
-rw-r--r--src/Blocks/BlockFurnace.h4
-rw-r--r--src/Blocks/BlockGlowstone.h6
-rw-r--r--src/Blocks/BlockHandler.cpp74
-rw-r--r--src/Blocks/BlockHandler.h40
-rw-r--r--src/Blocks/BlockHayBale.h1
-rw-r--r--src/Blocks/BlockHopper.h2
-rw-r--r--src/Blocks/BlockIce.h16
-rw-r--r--src/Blocks/BlockLadder.h34
-rw-r--r--src/Blocks/BlockLeaves.h40
-rw-r--r--src/Blocks/BlockLever.h4
-rw-r--r--src/Blocks/BlockLilypad.h14
-rw-r--r--src/Blocks/BlockMelon.h4
-rw-r--r--src/Blocks/BlockMobHead.h4
-rw-r--r--src/Blocks/BlockNewLeaves.h42
-rw-r--r--src/Blocks/BlockNote.h13
-rw-r--r--src/Blocks/BlockOre.h40
-rw-r--r--src/Blocks/BlockPiston.cpp12
-rw-r--r--src/Blocks/BlockPiston.h26
-rw-r--r--src/Blocks/BlockPlanks.h5
-rw-r--r--src/Blocks/BlockPortal.h16
-rw-r--r--src/Blocks/BlockPressurePlate.h4
-rw-r--r--src/Blocks/BlockPumpkin.h13
-rw-r--r--src/Blocks/BlockQuartz.h13
-rw-r--r--src/Blocks/BlockRail.h24
-rw-r--r--src/Blocks/BlockRedstone.h4
-rw-r--r--src/Blocks/BlockRedstoneRepeater.h8
-rw-r--r--src/Blocks/BlockSapling.h4
-rw-r--r--src/Blocks/BlockSideways.h14
-rw-r--r--src/Blocks/BlockSignPost.h (renamed from src/Blocks/BlockSign.h)54
-rw-r--r--src/Blocks/BlockSlab.h14
-rw-r--r--src/Blocks/BlockSnow.h10
-rw-r--r--src/Blocks/BlockStairs.h24
-rw-r--r--src/Blocks/BlockSugarcane.h1
-rw-r--r--src/Blocks/BlockTallGrass.h3
-rw-r--r--src/Blocks/BlockTorch.h23
-rw-r--r--src/Blocks/BlockTrapdoor.h9
-rw-r--r--src/Blocks/BlockTripwireHook.h10
-rw-r--r--src/Blocks/BlockVine.h15
-rw-r--r--src/Blocks/BlockWallSign.h90
-rw-r--r--src/Blocks/BroadcastInterface.h6
-rw-r--r--src/Blocks/CMakeLists.txt98
-rw-r--r--src/Blocks/ChunkInterface.h8
-rw-r--r--src/Blocks/ClearMetaOnDrop.h24
-rw-r--r--src/Blocks/MetaRotator.h8
-rw-r--r--src/Blocks/WorldInterface.h8
-rw-r--r--src/BoundingBox.cpp2
-rw-r--r--src/BoundingBox.h2
-rw-r--r--src/ByteBuffer.cpp2
-rw-r--r--src/CMakeLists.txt332
-rw-r--r--src/ChatColor.cpp48
-rw-r--r--src/ChatColor.h58
-rw-r--r--src/CheckBasicStyle.lua243
-rw-r--r--src/Chunk.cpp472
-rw-r--r--src/Chunk.h50
-rw-r--r--src/ChunkDataCallback.h18
-rw-r--r--src/ChunkDef.h38
-rw-r--r--src/ChunkMap.cpp195
-rw-r--r--src/ChunkMap.h48
-rw-r--r--src/ChunkSender.cpp4
-rw-r--r--src/ChunkSender.h10
-rw-r--r--src/ClientHandle.cpp228
-rw-r--r--src/ClientHandle.h73
-rw-r--r--src/CommandOutput.cpp4
-rw-r--r--src/CommandOutput.h6
-rw-r--r--src/CompositeChat.cpp42
-rw-r--r--src/CompositeChat.h2
-rw-r--r--src/CraftingRecipes.cpp18
-rw-r--r--src/CraftingRecipes.h2
-rw-r--r--src/Cuboid.cpp13
-rw-r--r--src/Cuboid.h14
-rw-r--r--src/Defines.h45
-rw-r--r--src/Enchantments.h4
-rw-r--r--src/Endianness.h11
-rw-r--r--src/Entities/ArrowEntity.cpp24
-rw-r--r--src/Entities/ArrowEntity.h4
-rw-r--r--src/Entities/Boat.cpp4
-rw-r--r--src/Entities/Boat.h2
-rw-r--r--src/Entities/CMakeLists.txt65
-rw-r--r--src/Entities/Effects.h30
-rw-r--r--src/Entities/EnderCrystal.cpp10
-rw-r--r--src/Entities/EnderCrystal.h4
-rw-r--r--src/Entities/Entity.cpp376
-rw-r--r--src/Entities/Entity.h88
-rw-r--r--src/Entities/EntityEffect.cpp411
-rw-r--r--src/Entities/EntityEffect.h494
-rw-r--r--src/Entities/ExpBottleEntity.h4
-rw-r--r--src/Entities/ExpOrb.cpp12
-rw-r--r--src/Entities/ExpOrb.h4
-rw-r--r--src/Entities/FallingBlock.h2
-rw-r--r--src/Entities/FireChargeEntity.h4
-rw-r--r--src/Entities/FireworkEntity.h4
-rw-r--r--src/Entities/Floater.cpp20
-rw-r--r--src/Entities/Floater.h6
-rw-r--r--src/Entities/GhastFireballEntity.h4
-rw-r--r--src/Entities/HangingEntity.cpp8
-rw-r--r--src/Entities/HangingEntity.h4
-rw-r--r--src/Entities/ItemFrame.cpp10
-rw-r--r--src/Entities/ItemFrame.h6
-rw-r--r--src/Entities/Minecart.cpp114
-rw-r--r--src/Entities/Minecart.h25
-rw-r--r--src/Entities/Painting.h10
-rw-r--r--src/Entities/Pawn.cpp100
-rw-r--r--src/Entities/Pawn.h30
-rw-r--r--src/Entities/Pickup.cpp18
-rw-r--r--src/Entities/Pickup.h8
-rw-r--r--src/Entities/Player.cpp657
-rw-r--r--src/Entities/Player.h151
-rw-r--r--src/Entities/ProjectileEntity.cpp27
-rw-r--r--src/Entities/ProjectileEntity.h10
-rw-r--r--src/Entities/SplashPotionEntity.cpp134
-rw-r--r--src/Entities/SplashPotionEntity.h79
-rw-r--r--src/Entities/TNTEntity.cpp2
-rw-r--r--src/Entities/TNTEntity.h4
-rw-r--r--src/Entities/ThrownEggEntity.h4
-rw-r--r--src/Entities/ThrownEnderPearlEntity.h4
-rw-r--r--src/Entities/ThrownSnowballEntity.h4
-rw-r--r--src/Entities/WitherSkullEntity.cpp49
-rw-r--r--src/Entities/WitherSkullEntity.h35
-rw-r--r--src/FastRandom.h3
-rw-r--r--src/FurnaceRecipe.cpp10
-rw-r--r--src/Generating/BioGen.cpp20
-rw-r--r--src/Generating/CMakeLists.txt65
-rw-r--r--src/Generating/Caves.cpp54
-rw-r--r--src/Generating/ChunkDesc.cpp27
-rw-r--r--src/Generating/ChunkDesc.h5
-rw-r--r--src/Generating/ChunkGenerator.cpp14
-rw-r--r--src/Generating/ChunkGenerator.h2
-rw-r--r--src/Generating/CompoGen.cpp33
-rw-r--r--src/Generating/ComposableGenerator.cpp194
-rw-r--r--src/Generating/DistortedHeightmap.cpp28
-rw-r--r--src/Generating/EndGen.cpp4
-rw-r--r--src/Generating/EndGen.h3
-rw-r--r--src/Generating/FinishGen.cpp248
-rw-r--r--src/Generating/FinishGen.h116
-rw-r--r--src/Generating/GridStructGen.cpp13
-rw-r--r--src/Generating/HeiGen.cpp24
-rw-r--r--src/Generating/MineShafts.cpp15
-rw-r--r--src/Generating/NetherFortGen.cpp6
-rw-r--r--src/Generating/Noise3DGenerator.cpp9
-rw-r--r--src/Generating/POCPieceGenerator.cpp2
-rw-r--r--src/Generating/PieceGenerator.cpp18
-rw-r--r--src/Generating/PieceGenerator.h4
-rw-r--r--src/Generating/Prefab.cpp2
-rw-r--r--src/Generating/Prefab.h2
-rw-r--r--src/Generating/Prefabs/AlchemistVillagePrefabs.cpp78
-rw-r--r--src/Generating/Prefabs/CMakeLists.txt31
-rw-r--r--src/Generating/Prefabs/JapaneseVillagePrefabs.cpp86
-rw-r--r--src/Generating/Prefabs/NetherFortPrefabs.cpp857
-rw-r--r--src/Generating/Prefabs/PlainsVillagePrefabs.cpp455
-rw-r--r--src/Generating/Prefabs/RainbowRoadPrefabs.cpp24
-rw-r--r--src/Generating/Prefabs/SandFlatRoofVillagePrefabs.cpp24
-rw-r--r--src/Generating/Prefabs/SandVillagePrefabs.cpp32
-rw-r--r--src/Generating/Prefabs/TestRailsPrefabs.cpp10
-rw-r--r--src/Generating/Prefabs/UnderwaterBasePrefabs.cpp28
-rw-r--r--src/Generating/RainbowRoadsGen.cpp4
-rw-r--r--src/Generating/Ravines.cpp32
-rw-r--r--src/Generating/RoughRavines.cpp300
-rw-r--r--src/Generating/RoughRavines.h86
-rw-r--r--src/Generating/StructGen.cpp89
-rw-r--r--src/Generating/StructGen.h26
-rw-r--r--src/Generating/TestRailsGen.cpp4
-rw-r--r--src/Generating/Trees.cpp140
-rw-r--r--src/Generating/Trees.h4
-rw-r--r--src/Generating/UnderwaterBaseGen.cpp4
-rw-r--r--src/Generating/VillageGen.cpp6
-rw-r--r--src/Globals.h51
-rw-r--r--src/Group.cpp10
-rw-r--r--src/Group.h26
-rw-r--r--src/GroupManager.cpp24
-rw-r--r--src/HTTPServer/CMakeLists.txt27
-rw-r--r--src/HTTPServer/HTTPConnection.cpp2
-rw-r--r--src/HTTPServer/HTTPMessage.cpp11
-rw-r--r--src/HTTPServer/HTTPMessage.h4
-rw-r--r--src/HTTPServer/HTTPServer.cpp6
-rw-r--r--src/HTTPServer/MultipartParser.cpp4
-rw-r--r--src/HTTPServer/NameValueParser.cpp2
-rw-r--r--src/Inventory.cpp66
-rw-r--r--src/Inventory.h12
-rw-r--r--src/Item.cpp68
-rw-r--r--src/Item.h8
-rw-r--r--src/ItemGrid.cpp39
-rw-r--r--src/ItemGrid.h4
-rw-r--r--src/Items/CMakeLists.txt54
-rw-r--r--src/Items/ItemBed.h2
-rw-r--r--src/Items/ItemBow.h12
-rw-r--r--src/Items/ItemBrewingStand.h2
-rw-r--r--src/Items/ItemBucket.h81
-rw-r--r--src/Items/ItemCake.h2
-rw-r--r--src/Items/ItemCauldron.h2
-rw-r--r--src/Items/ItemComparator.h2
-rw-r--r--src/Items/ItemDoor.h6
-rw-r--r--src/Items/ItemFishingRod.h31
-rw-r--r--src/Items/ItemFlowerPot.h2
-rw-r--r--src/Items/ItemFood.h56
-rw-r--r--src/Items/ItemGoldenApple.h58
-rw-r--r--src/Items/ItemHandler.cpp192
-rw-r--r--src/Items/ItemHandler.h50
-rw-r--r--src/Items/ItemHoe.h10
-rw-r--r--src/Items/ItemItemFrame.h4
-rw-r--r--src/Items/ItemLeaves.h4
-rw-r--r--src/Items/ItemLighter.h6
-rw-r--r--src/Items/ItemLilypad.h4
-rw-r--r--src/Items/ItemMilk.h28
-rw-r--r--src/Items/ItemMobHead.h2
-rw-r--r--src/Items/ItemNetherWart.h2
-rw-r--r--src/Items/ItemPainting.h8
-rw-r--r--src/Items/ItemPickaxe.h7
-rw-r--r--src/Items/ItemPotion.h79
-rw-r--r--src/Items/ItemRedstoneDust.h4
-rw-r--r--src/Items/ItemRedstoneRepeater.h2
-rw-r--r--src/Items/ItemSapling.h2
-rw-r--r--src/Items/ItemSeeds.h8
-rw-r--r--src/Items/ItemShears.h27
-rw-r--r--src/Items/ItemShovel.h10
-rw-r--r--src/Items/ItemSign.h9
-rw-r--r--src/Items/ItemSugarcane.h2
-rw-r--r--src/Items/ItemSword.h23
-rw-r--r--src/Items/ItemThrowable.h15
-rw-r--r--src/LightingThread.cpp6
-rw-r--r--src/LightingThread.h8
-rw-r--r--src/LineBlockTracer.cpp57
-rw-r--r--src/Log.cpp169
-rw-r--r--src/Log.h30
-rw-r--r--src/Logger.cpp145
-rw-r--r--src/Logger.h73
-rw-r--r--src/LoggerListeners.cpp322
-rw-r--r--src/LoggerListeners.h31
-rw-r--r--src/MCLogger.cpp267
-rw-r--r--src/MCLogger.h96
-rw-r--r--src/Map.cpp4
-rw-r--r--src/Map.h22
-rw-r--r--src/MapManager.h27
-rw-r--r--src/Matrix4.h8
-rw-r--r--src/MobCensus.cpp4
-rw-r--r--src/MobFamilyCollecter.h4
-rw-r--r--src/MobProximityCounter.cpp16
-rw-r--r--src/MobProximityCounter.h13
-rw-r--r--src/MobSpawner.cpp11
-rw-r--r--src/MobSpawner.h6
-rw-r--r--src/Mobs/AggressiveMonster.cpp12
-rw-r--r--src/Mobs/Bat.h2
-rw-r--r--src/Mobs/Blaze.h2
-rw-r--r--src/Mobs/CMakeLists.txt76
-rw-r--r--src/Mobs/CaveSpider.cpp15
-rw-r--r--src/Mobs/CaveSpider.h3
-rw-r--r--src/Mobs/Chicken.h2
-rw-r--r--src/Mobs/Cow.h2
-rw-r--r--src/Mobs/Creeper.cpp8
-rw-r--r--src/Mobs/Creeper.h2
-rw-r--r--src/Mobs/EnderDragon.h2
-rw-r--r--src/Mobs/Enderman.cpp149
-rw-r--r--src/Mobs/Enderman.h8
-rw-r--r--src/Mobs/Ghast.h2
-rw-r--r--src/Mobs/Giant.h2
-rw-r--r--src/Mobs/Horse.cpp2
-rw-r--r--src/Mobs/Horse.h2
-rw-r--r--src/Mobs/IronGolem.h4
-rw-r--r--src/Mobs/MagmaCube.h2
-rw-r--r--src/Mobs/Monster.cpp110
-rw-r--r--src/Mobs/Monster.h39
-rw-r--r--src/Mobs/Mooshroom.h2
-rw-r--r--src/Mobs/Ocelot.h2
-rw-r--r--src/Mobs/Pig.h2
-rw-r--r--src/Mobs/Sheep.cpp59
-rw-r--r--src/Mobs/Sheep.h21
-rw-r--r--src/Mobs/Silverfish.h2
-rw-r--r--src/Mobs/Skeleton.cpp17
-rw-r--r--src/Mobs/Skeleton.h10
-rw-r--r--src/Mobs/Slime.cpp76
-rw-r--r--src/Mobs/Slime.h15
-rw-r--r--src/Mobs/SnowGolem.cpp2
-rw-r--r--src/Mobs/SnowGolem.h2
-rw-r--r--src/Mobs/Spider.h2
-rw-r--r--src/Mobs/Squid.h2
-rw-r--r--src/Mobs/Villager.cpp6
-rw-r--r--src/Mobs/Villager.h7
-rw-r--r--src/Mobs/Witch.h2
-rw-r--r--src/Mobs/Wither.cpp4
-rw-r--r--src/Mobs/Wither.h6
-rw-r--r--src/Mobs/Wolf.cpp14
-rw-r--r--src/Mobs/Wolf.h12
-rw-r--r--src/Mobs/Zombie.cpp2
-rw-r--r--src/Mobs/Zombie.h10
-rw-r--r--src/Mobs/ZombiePigman.cpp6
-rw-r--r--src/Mobs/ZombiePigman.h6
-rw-r--r--src/MonsterConfig.cpp2
-rw-r--r--src/Noise.cpp112
-rw-r--r--src/Noise.h18
-rw-r--r--src/OSSupport/CMakeLists.txt43
-rw-r--r--src/OSSupport/CriticalSection.cpp10
-rw-r--r--src/OSSupport/CriticalSection.h2
-rw-r--r--src/OSSupport/Errors.cpp12
-rw-r--r--src/OSSupport/Event.cpp4
-rw-r--r--src/OSSupport/File.cpp11
-rw-r--r--src/OSSupport/File.h7
-rw-r--r--src/OSSupport/Queue.h8
-rw-r--r--src/OSSupport/Semaphore.cpp76
-rw-r--r--src/OSSupport/Semaphore.h4
-rw-r--r--src/OSSupport/Sleep.cpp6
-rw-r--r--src/OSSupport/Sleep.h2
-rw-r--r--src/OSSupport/Socket.cpp15
-rw-r--r--src/OSSupport/Socket.h1
-rw-r--r--src/OSSupport/SocketThreads.cpp2
-rw-r--r--src/OSSupport/Thread.cpp42
-rw-r--r--src/OSSupport/Thread.h8
-rw-r--r--src/PolarSSL++/CMakeLists.txt12
-rw-r--r--src/PolarSSL++/Sha1Checksum.cpp2
-rw-r--r--src/Protocol/Authenticator.cpp222
-rw-r--r--src/Protocol/Authenticator.h28
-rw-r--r--src/Protocol/CMakeLists.txt32
-rw-r--r--src/Protocol/MojangAPI.cpp799
-rw-r--r--src/Protocol/MojangAPI.h189
-rw-r--r--src/Protocol/Protocol.h12
-rw-r--r--src/Protocol/Protocol125.cpp119
-rw-r--r--src/Protocol/Protocol125.h19
-rw-r--r--src/Protocol/Protocol132.cpp23
-rw-r--r--src/Protocol/Protocol132.h2
-rw-r--r--src/Protocol/Protocol14x.cpp12
-rw-r--r--src/Protocol/Protocol14x.h2
-rw-r--r--src/Protocol/Protocol15x.cpp2
-rw-r--r--src/Protocol/Protocol16x.cpp18
-rw-r--r--src/Protocol/Protocol16x.h2
-rw-r--r--src/Protocol/Protocol17x.cpp164
-rw-r--r--src/Protocol/Protocol17x.h8
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp28
-rw-r--r--src/Protocol/ProtocolRecognizer.h14
-rw-r--r--src/RCONServer.cpp10
-rw-r--r--src/Root.cpp103
-rw-r--r--src/Root.h51
-rw-r--r--src/Scoreboard.cpp12
-rw-r--r--src/Scoreboard.h29
-rw-r--r--src/Server.cpp30
-rw-r--r--src/Server.h49
-rw-r--r--src/SetChunkData.cpp115
-rw-r--r--src/SetChunkData.h120
-rw-r--r--src/Simulator/CMakeLists.txt35
-rw-r--r--src/Simulator/DelayedFluidSimulator.cpp8
-rw-r--r--src/Simulator/DelayedFluidSimulator.h4
-rw-r--r--src/Simulator/FireSimulator.cpp30
-rw-r--r--src/Simulator/FloodyFluidSimulator.cpp14
-rw-r--r--src/Simulator/FluidSimulator.cpp22
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.cpp455
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.h56
-rw-r--r--src/Simulator/NoopFluidSimulator.h2
-rw-r--r--src/Simulator/NoopRedstoneSimulator.h6
-rw-r--r--src/Simulator/SandSimulator.h2
-rw-r--r--src/Simulator/Simulator.h4
-rw-r--r--src/Simulator/SimulatorManager.cpp6
-rw-r--r--src/Simulator/VaporizeFluidSimulator.cpp4
-rw-r--r--src/Statistics.cpp3
-rw-r--r--src/Statistics.h13
-rw-r--r--src/StringUtils.cpp131
-rw-r--r--src/StringUtils.h21
-rw-r--r--src/Tracer.cpp144
-rw-r--r--src/Tracer.h8
-rw-r--r--src/UI/CMakeLists.txt16
-rw-r--r--src/UI/SlotArea.cpp250
-rw-r--r--src/UI/SlotArea.h35
-rw-r--r--src/UI/Window.cpp134
-rw-r--r--src/UI/Window.h38
-rw-r--r--src/UI/WindowOwner.h2
-rw-r--r--src/Vector3.h2
-rw-r--r--src/WebAdmin.cpp74
-rw-r--r--src/WebAdmin.h22
-rw-r--r--src/World.cpp467
-rw-r--r--src/World.h172
-rw-r--r--src/WorldStorage/CMakeLists.txt35
-rw-r--r--src/WorldStorage/FastNBT.cpp8
-rw-r--r--src/WorldStorage/FastNBT.h8
-rw-r--r--src/WorldStorage/FireworksSerializer.cpp8
-rw-r--r--src/WorldStorage/MapSerializer.h7
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp83
-rw-r--r--src/WorldStorage/NBTChunkSerializer.h5
-rw-r--r--src/WorldStorage/SchematicFileSerializer.cpp2
-rw-r--r--src/WorldStorage/ScoreboardSerializer.cpp10
-rw-r--r--src/WorldStorage/WSSAnvil.cpp213
-rw-r--r--src/WorldStorage/WSSAnvil.h10
-rw-r--r--src/WorldStorage/WSSCompact.cpp153
-rw-r--r--src/WorldStorage/WSSCompact.h6
-rw-r--r--src/WorldStorage/WorldStorage.cpp14
-rw-r--r--src/WorldStorage/WorldStorage.h21
-rw-r--r--src/XMLParser.h38
-rw-r--r--src/main.cpp46
485 files changed, 14413 insertions, 6046 deletions
diff --git a/.gitignore b/.gitignore
index 4a319c5ef..a4cbef72f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ cloc.xsl
*.suo
/EveryNight.cmd
/UploadLuaAPI.cmd
+AllFiles.lst
# IDE Stuff
## Sublime Text
@@ -63,8 +64,9 @@ install_mainfest.txt
src/MCServer
lib/tolua++/tolua
src/Bindings/Bindings.*
-src/Bindings/BindingDependecies.txt
+src/Bindings/BindingDependencies.txt
MCServer.dir/
+src/AllFiles.lst
#win32 cmake stuff
*.vcxproj
diff --git a/.gitmodules b/.gitmodules
index 2aaee3624..8e63ee0a9 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -10,3 +10,6 @@
[submodule "lib/polarssl"]
path = lib/polarssl
url = https://github.com/mc-server/polarssl
+[submodule "lib/SQLiteCpp"]
+ path = lib/SQLiteCpp
+ url = https://github.com/mc-server/SQLiteCpp.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6400c1b4..dd9b1e67c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -53,6 +53,14 @@ endif()
project (MCServer)
+# Set options for SQLiteCpp, disable all their tests and lints:
+set(SQLITECPP_RUN_CPPLINT OFF CACHE BOOL "Run cpplint.py tool for Google C++ StyleGuide." FORCE)
+set(SQLITECPP_RUN_CPPCHECK OFF CACHE BOOL "Run cppcheck C++ static analysis tool." FORCE)
+set(SQLITECPP_RUN_DOXYGEN OFF CACHE BOOL "Run Doxygen C++ documentation tool." FORCE)
+set(SQLITECPP_BUILD_EXAMPLES OFF CACHE BOOL "Build examples." FORCE)
+set(SQLITECPP_BUILD_TESTS OFF CACHE BOOL "Build and run tests." FORCE)
+set(SQLITECPP_INTERNAL_SQLITE OFF CACHE BOOL "Add the internal SQLite3 source to the project." FORCE)
+
# Include all the libraries:
add_subdirectory(lib/inifile/)
add_subdirectory(lib/jsoncpp/)
@@ -60,9 +68,16 @@ add_subdirectory(lib/zlib/)
add_subdirectory(lib/lua/)
add_subdirectory(lib/tolua++/)
add_subdirectory(lib/sqlite/)
+add_subdirectory(lib/SQLiteCpp/)
add_subdirectory(lib/expat/)
add_subdirectory(lib/luaexpat/)
+# Add proper include directories so that SQLiteCpp can find SQLite3:
+get_property(SQLITECPP_INCLUDES DIRECTORY "lib/SQLiteCpp/" PROPERTY INCLUDE_DIRECTORIES)
+set(SQLITECPP_INCLUDES "${SQLITECPP_INCLUDES}" "${CMAKE_CURRENT_SOURCE_DIR}/lib/sqlite/")
+set_property(DIRECTORY lib/SQLiteCpp/ PROPERTY INCLUDE_DIRECTORIES "${SQLITECPP_INCLUDES}")
+set_property(TARGET SQLiteCpp PROPERTY INCLUDE_DIRECTORIES "${SQLITECPP_INCLUDES}")
+
if (WIN32)
add_subdirectory(lib/luaproxy/)
endif()
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 09515aa6b..925e8f35b 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -28,5 +28,6 @@ UltraCoderRU
worktycho
xoft
Yeeeeezus (Donated AlchemistVillage prefabs)
+Howaner
Please add yourself to this list if you contribute to MCServer.
diff --git a/Install/SQLiteCpp-LICENSE.txt b/Install/SQLiteCpp-LICENSE.txt
new file mode 100644
index 000000000..ec952abba
--- /dev/null
+++ b/Install/SQLiteCpp-LICENSE.txt
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2012-2014 Sebastien Rombauts (sebastien.rombauts@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/Install/Zip2008.list b/Install/Zip2008.list
index b118ccbf9..5736867d8 100644
--- a/Install/Zip2008.list
+++ b/Install/Zip2008.list
@@ -11,4 +11,5 @@ MCServer*debug.cmd
Lua-LICENSE.txt
LuaExpat-license.html
LuaSQLite3-LICENSE.txt
+SQLiteCpp-LICENSE.txt
MersenneTwister-LICENSE.txt
diff --git a/MCServer/Plugins/APIDump/APIDesc.lua b/MCServer/Plugins/APIDump/APIDesc.lua
index ea9f38db4..64ba80c5f 100644
--- a/MCServer/Plugins/APIDump/APIDesc.lua
+++ b/MCServer/Plugins/APIDump/APIDesc.lua
@@ -523,12 +523,12 @@ end
Functions =
{
- GenerateOfflineUUID = { Params = "Username", Return = "string", Notes = "(STATIC) Generates an UUID based on the player name provided. This is used for the offline (non-auth) mode, when there's no UUID source. Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same. Returns a 36-char UUID (with dashes)." },
+ GenerateOfflineUUID = { Params = "Username", Return = "string", Notes = "(STATIC) Generates an UUID based on the player name provided. This is used for the offline (non-auth) mode, when there's no UUID source. Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same. Returns a 32-char UUID (no dashes)." },
GetLocale = { Params = "", Return = "Locale", Notes = "Returns the locale string that the client sends as part of the protocol handshake. Can be used to provide localized strings." },
GetPing = { Params = "", Return = "number", Notes = "Returns the ping time, in ms" },
GetPlayer = { Params = "", Return = "{{cPlayer|cPlayer}}", Notes = "Returns the player object connected to this client. Note that this may be nil, for example if the player object is not yet spawned." },
GetUniqueID = { Params = "", Return = "number", Notes = "Returns the UniqueID of the client used to identify the client in the server" },
- GetUUID = { Params = "", Return = "string", Notes = "Returns the authentication-based UUID of the client. This UUID should be used to identify the player when persisting any player-related data." },
+ GetUUID = { Params = "", Return = "string", Notes = "Returns the authentication-based UUID of the client. This UUID should be used to identify the player when persisting any player-related data. Returns a 32-char UUID (no dashes)" },
GetUsername = { Params = "", Return = "string", Notes = "Returns the username that the client has provided" },
GetViewDistance = { Params = "", Return = "number", Notes = "Returns the viewdistance (number of chunks loaded for the player in each direction)" },
HasPluginChannel = { Params = "ChannelName", Return = "bool", Notes = "Returns true if the client has registered to receive messages on the specified plugin channel." },
@@ -1155,6 +1155,7 @@ These ItemGrids are available in the API and can be manipulated by the plugins,
HasItems = { Params = "{{cItem|cItem}}", Return = "bool", Notes = "Returns true if there are at least as many items of the specified type as in the parameter" },
HowManyCanFit = { Params = "{{cItem|cItem}}", Return = "number", Notes = "Returns the number of the specified items that can fit in the storage, including empty slots" },
HowManyItems = { Params = "{{cItem|cItem}}", Return = "number", Notes = "Returns the number of the specified items that are currently stored" },
+ RemoveItem = { Params = "{{cItem}}", Return = "number", Notes = "Removes the specified item from the inventory, as many as possible, up to the item's m_ItemCount. Returns the number of items that were removed." },
RemoveOneEquippedItem = { Params = "", Return = "", Notes = "Removes one item from the hotbar's currently selected slot" },
SetArmorSlot = { Params = "ArmorSlotNum, {{cItem|cItem}}", Return = "", Notes = "Sets the specified armor slot contents" },
SetEquippedSlotNum = { Params = "EquippedSlotNum", Return = "", Notes = "Sets the currently selected hotbar slot number" },
@@ -1384,6 +1385,7 @@ local Item5 = cItem(E_ITEM_DIAMOND_CHESTPLATE, 1, 0, "thorns=1;unbreaking=3");
{ Params = "SlotNum", Return = "bool", Notes = "Returns true if the specified slot is empty, or an invalid slot is specified" },
{ Params = "X, Y", Return = "bool", Notes = "Returns true if the specified slot is empty, or an invalid slot is specified" },
},
+ RemoveItem = { Params = "{{cItem}}", Return = "number", Notes = "Removes the specified item from the grid, as many as possible, up to the item's m_ItemCount. Returns the number of items that were removed." },
RemoveOneItem =
{
{ Params = "SlotNum", Return = "{{cItem|cItem}}", Notes = "Removes one item from the stack in the specified slot and returns it as a single cItem. Empty slots are skipped and an empty item is returned" },
@@ -1604,6 +1606,38 @@ a_Player:OpenWindow(Window);
}, -- cMapManager
+ cMojangAPI =
+ {
+ Desc = [[
+ Provides interface to various API functions that Mojang provides through their servers. Note that
+ some of these calls will wait for a response from the network, and so shouldn't be used while the
+ server is fully running (or at least when there are players connected) to avoid percepted lag.</p>
+ <p>
+ All the functions are static, call them using the <code>cMojangAPI:Function()</code> convention.</p>
+ <p>
+ Mojang uses two formats for UUIDs, short and dashed. MCServer works with short UUIDs internally, but
+ will convert to dashed UUIDs where needed - in the protocol login for example. The MakeUUIDShort()
+ and MakeUUIDDashed() functions are provided for plugins to use for conversion between the two
+ formats.</p>
+ <p>
+ This class will cache values returned by the API service. The cache will hold the values for 7 days
+ by default, after that, they will no longer be available. This is in order to not let the server get
+ banned from using the API service, since they are rate-limited to 600 queries per 10 minutes. The
+ cache contents also gets updated whenever a player successfully joins, since that makes the server
+ contact the API service, too, and retrieve the relevant data.</p>
+ ]],
+ Functions =
+ {
+ AddPlayerNameToUUIDMapping = { Params = "PlayerName, UUID", Return = "", Notes = "(STATIC) Adds the specified PlayerName-to-UUID mapping into the cache, with current timestamp. Accepts both short or dashed UUIDs. " },
+ GetPlayerNameFromUUID = { Params = "UUID, [UseOnlyCached]", Return = "PlayerName", Notes = "(STATIC) Returns the playername that corresponds to the given UUID, or an empty string on error. If UseOnlyCached is false (the default), queries the Mojang servers if the UUID is not in the cache. The UUID can be either short or dashed. <br /><b>WARNING</b>: Do NOT use this function with UseOnlyCached set to false while the server is running. Only use it when the server is starting up (inside the Initialize() method), otherwise you will lag the server severely." },
+ GetUUIDFromPlayerName = { Params = "PlayerName, [UseOnlyCached]", Return = "UUID", Notes = "(STATIC) Returns the (short) UUID that corresponds to the given playername, or an empty string on error. If UseOnlyCached is false (the default), queries the Mojang servers if the playername is not in the cache. <br /><b>WARNING</b>: Do NOT use this function with UseOnlyCached set to false while the server is running. Only use it when the server is starting up (inside the Initialize() method), otherwise you will lag the server severely." },
+ GetUUIDsFromPlayerNames = { Params = "PlayerNames, [UseOnlyCached]", Return = "table", Notes = "(STATIC) Returns a table that contains the map, 'PlayerName' -> '(short) UUID', for all valid playernames in the input array-table. PlayerNames not recognized will not be set in the returned map. If UseOnlyCached is false (the default), queries the Mojang servers for the results that are not in the cache. <br /><b>WARNING</b>: Do NOT use this function with UseOnlyCached set to false while the server is running. Only use it when the server is starting up (inside the Initialize() method), otherwise you will lag the server severely." },
+ MakeUUIDDashed = { Params = "UUID", Return = "DashedUUID", Notes = "(STATIC) Converts the UUID to a dashed format (\"01234567-8901-2345-6789-012345678901\"). Accepts both dashed or short UUIDs. Logs a warning and returns an empty string if UUID format not recognized." },
+ MakeUUIDShort = { Params = "UUID", Return = "ShortUUID", Notes = "(STATIC) Converts the UUID to a short format (without dashes, \"01234567890123456789012345678901\"). Accepts both dashed or short UUIDs. Logs a warning and returns an empty string if UUID format not recognized." },
+ },
+
+ },
+
cMonster =
{
Desc = [[
@@ -1691,6 +1725,9 @@ a_Player:OpenWindow(Window);
TakeDamage = { Return = "" },
KilledBy = { Return = "" },
GetHealth = { Return = "number" },
+ AddEntityEffect = { Params = "EffectType, {{cEntityEffect}}", Return = "", Notes = "Applies an entity effect" },
+ RemoveEntityEffect = { Params = "EffectType", Return = "", Notes = "Removes a currently applied entity effect" },
+ ClearEntityEffects = { Return = "", Notes = "Removes all currently applied entity effects" },
},
Inherits = "cEntity",
}, -- cPawn
@@ -1980,7 +2017,6 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
]],
Functions =
{
- Get = { Params = "", Return = "Root object", Notes = "(STATIC)This function returns the cRoot object." },
BroadcastChat = { Params = "Message", Return = "", Notes = "Broadcasts a message to every player in the server. No formatting is done by the server." },
BroadcastChatFailure = { Params = "Message", Return = "", Notes = "Prepends Rose [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For a command that failed to run because of insufficient permissions, etc." },
BroadcastChatFatal = { Params = "Message", Return = "", Notes = "Prepends Red [FATAL] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For a plugin that crashed, or similar." },
@@ -1991,6 +2027,7 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
FindAndDoWithPlayer = { Params = "PlayerName, CallbackFunction", Return = "", Notes = "Calls the given callback function for all players with names partially (or fully) matching the name string provided." },
ForEachPlayer = { Params = "CallbackFunction", Return = "", Notes = "Calls the given callback function for each player. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|cPlayer}})</pre>" },
ForEachWorld = { Params = "CallbackFunction", Return = "", Notes = "Calls the given callback function for each world. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cWorld|cWorld}})</pre>" },
+ Get = { Params = "", Return = "Root object", Notes = "(STATIC)This function returns the cRoot object." },
GetCraftingRecipes = { Params = "", Return = "{{cCraftingRecipe|cCraftingRecipe}}", Notes = "Returns the CraftingRecipes object" },
GetDefaultWorld = { Params = "", Return = "{{cWorld|cWorld}}", Notes = "Returns the world object from the default world." },
GetFurnaceFuelBurnTime = { Params = "{{cItem|Fuel}}", Return = "number", Notes = "(STATIC) Returns the number of ticks for how long the item would fuel a furnace. Returns zero if not a fuel." },
@@ -2239,6 +2276,7 @@ end
DigBlock = { Params = "X, Y, Z", Return = "", Notes = "Replaces the specified block with air, without dropping the usual pickups for the block. Wakes up the simulators for the block and its neighbors." },
DoExplosionAt = { Params = "Force, X, Y, Z, CanCauseFire, Source, SourceData", Return = "", Notes = "Creates an explosion of the specified relative force in the specified position. If CanCauseFire is set, the explosion will set blocks on fire, too. The Source parameter specifies the source of the explosion, one of the esXXX constants. The SourceData parameter is specific to each source type, usually it provides more info about the source." },
DoWithBlockEntityAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a block entity at the specified coords, calls the CallbackFunction with the {{cBlockEntity}} parameter representing the block entity. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cBlockEntity|BlockEntity}}, [CallbackData])</pre> The function returns false if there is no block entity, or if there is, it returns the bool value that the callback has returned. Use {{tolua}}.cast() to cast the Callback's BlockEntity parameter to the correct {{cBlockEntity}} descendant." },
+ DoWithBeaconAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a beacon at the specified coords, calls the CallbackFunction with the {{cBeaconEntity}} parameter representing the beacon. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cBeaconEntity|BeaconEntity}}, [CallbackData])</pre> The function returns false if there is no beacon, or if there is, it returns the bool value that the callback has returned." },
DoWithChestAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a chest at the specified coords, calls the CallbackFunction with the {{cChestEntity}} parameter representing the chest. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cChestEntity|ChestEntity}}, [CallbackData])</pre> The function returns false if there is no chest, or if there is, it returns the bool value that the callback has returned." },
DoWithCommandBlockAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a command block at the specified coords, calls the CallbackFunction with the {{cCommandBlockEntity}} parameter representing the command block. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cCommandBlockEntity|CommandBlockEntity}}, [CallbackData])</pre> The function returns false if there is no command block, or if there is, it returns the bool value that the callback has returned." },
DoWithDispenserAt = { Params = "X, Y, Z, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a dispenser at the specified coords, calls the CallbackFunction with the {{cDispenserEntity}} parameter representing the dispenser. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cDispenserEntity|DispenserEntity}}, [CallbackData])</pre> The function returns false if there is no dispenser, or if there is, it returns the bool value that the callback has returned." },
@@ -2722,15 +2760,16 @@ end
Functions =
{
AddFaceDirection = {Params = "BlockX, BlockY, BlockZ, BlockFace, [IsInverse]", Return = "BlockX, BlockY, BlockZ", Notes = "Returns the coords of a block adjacent to the specified block through the specified {{Globals#BlockFaces|face}}"},
- BlockFaceToString = { Params = "{{Globals#BlockFaces|eBlockFace}}", Return = "string", Notes = "Returns the string representation of the {{Globals#BlockFaces|eBlockFace}} constant. Uses the axis-direction-based names, such as BLOCK_FACE_XP." },
+ BlockFaceToString = {Params = "{{Globals#BlockFaces|eBlockFace}}", Return = "string", Notes = "Returns the string representation of the {{Globals#BlockFaces|eBlockFace}} constant. Uses the axis-direction-based names, such as BLOCK_FACE_XP." },
BlockStringToType = {Params = "BlockTypeString", Return = "BLOCKTYPE", Notes = "Returns the block type parsed from the given string"},
+ Clamp = {Params = "Number, Min, Max", Return = "number", Notes = "Clamp the number to the specified range."},
ClickActionToString = {Params = "{{Globals#ClickAction|ClickAction}}", Return = "string", Notes = "Returns a string description of the ClickAction enumerated value"},
DamageTypeToString = {Params = "{{Globals#DamageType|DamageType}}", Return = "string", Notes = "Converts the {{Globals#DamageType|DamageType}} enumerated value to a string representation "},
EscapeString = {Params = "string", Return = "string", Notes = "Returns a copy of the string with all quotes and backslashes escaped by a backslash"},
GetChar = {Params = "String, Pos", Return = "string", Notes = "Returns one character from the string, specified by position "},
GetIniItemSet = { Params = "IniFile, SectionName, KeyName, DefaultValue", Return = "{{cItem}}", Notes = "Returns the item that has been read from the specified INI file value. If the value is not present in the INI file, the DefaultValue is stored in the file and parsed as the result. Returns empty item if the value cannot be parsed. " },
GetTime = {Return = "number", Notes = "Returns the current OS time, as a unix time stamp (number of seconds since Jan 1, 1970)"},
- IsBiomeNoDownfall = { Params = "Biome", Return = "bool", Notes = "Returns true if the biome is 'dry', that is, there is no precipitation during rains and storms." },
+ IsBiomeNoDownfall = {Params = "Biome", Return = "bool", Notes = "Returns true if the biome is 'dry', that is, there is no precipitation during rains and storms." },
IsValidBlock = {Params = "BlockType", Return = "bool", Notes = "Returns true if BlockType is a known block type"},
IsValidItem = {Params = "ItemType", Return = "bool", Notes = "Returns true if ItemType is a known item type"},
ItemToFullString = {Params = "{{cItem|cItem}}", Return = "string", Notes = "Returns the string representation of the item, in the format 'ItemTypeText:ItemDamage * Count'"},
diff --git a/MCServer/Plugins/APIDump/Classes/BlockEntities.lua b/MCServer/Plugins/APIDump/Classes/BlockEntities.lua
index de42f66df..90ebf12e6 100644
--- a/MCServer/Plugins/APIDump/Classes/BlockEntities.lua
+++ b/MCServer/Plugins/APIDump/Classes/BlockEntities.lua
@@ -50,6 +50,32 @@ return
},
},
+ cBeaconEntity =
+ {
+ Desc = [[
+ A beacon entity is a {{cBlockEntityWithItems|cBlockEntityWithItems}} descendant that represents a beacon
+ in the world.
+ ]],
+
+ Inherits = "cBlockEntityWithItems",
+
+ Functions =
+ {
+ IsActive = { Params = "", Return = "bool", Notes = "Is the beacon active?" },
+ GetBeaconLevel = { Params = "", Return = "number", Notes = "Returns the beacon level. (0 - 4)" },
+ GetPrimaryEffect = { Params = "", Return = "EffectType", Notes = "Returns the primary effect." },
+ GetSecondaryEffect = { Params = "", Return = "EffectType", Notes = "Returns the secondary effect." },
+ SetPrimaryEffect = { Params = "EffectType", Return = "bool", Notes = "Select the primary effect. Returns false when the effect is invalid." },
+ SetSecondaryEffect = { Params = "EffectType", Return = "bool", Notes = "Select the secondary effect. Returns false when the effect is invalid." },
+ CalculatePyramidLevel = { Params = "", Return = "number", Notes = "Calculate the amount of layers the pyramid below the beacon has." },
+ IsBeaconBlocked = { Params = "", Return = "bool", Notes = "Is the beacon blocked by non-transparent blocks that are higher than the beacon?" },
+ UpdateBeacon = { Params = "", Return = "", Notes = "Update the beacon." },
+ GiveEffects = { Params = "", Return = "", Notes = "Give the near-players the effects." },
+ IsMineralBlock = { Params = "BLOCKTYPE", Return = "bool", Notes = "Returns true if the block is a diamond block, a golden block, an iron block or an emerald block." },
+ IsValidEffect = { Params = "EffectType", Return = "bool", Notes = "Returns true if the effect can be used." },
+ },
+ },
+
cChestEntity =
{
Desc = [[
diff --git a/MCServer/Plugins/APIDump/Hooks/OnEntityAddEffect.lua b/MCServer/Plugins/APIDump/Hooks/OnEntityAddEffect.lua
new file mode 100644
index 000000000..1d1658a6f
--- /dev/null
+++ b/MCServer/Plugins/APIDump/Hooks/OnEntityAddEffect.lua
@@ -0,0 +1,33 @@
+return
+{
+ HOOK_ENTITY_ADD_EFFECT =
+ {
+ CalledWhen = "An entity effect is about to get added to an entity.",
+ DefaultFnName = "OnEntityAddEffect", -- also used as pagename
+ Desc = [[
+ This hook is called whenever an entity effect is about to be added to an entity. The plugin may
+ disallow the addition by returning true.</p>
+ <p>Note that this hook only fires for adding the effect, but not for the actual effect application. See
+ also the {{OnEntityRemoveEffect|HOOK_ENTITY_REMOVE_EFFECT}} for notification about effects expiring /
+ removing, and {{OnEntityApplyEffect|HOOK_ENTITY_APPLY_EFFECT}} for the actual effect application to the
+ entity.
+ ]],
+ Params =
+ {
+ { Name = "Entity", Type = "{{cEntity}}", Notes = "The entity to which the effect is about to be added" },
+ { Name = "EffectType", Type = "number", Notes = "The type of the effect to be added. One of the effXXX constants." },
+ { Name = "EffectDuration", Type = "number", Notes = "The duration of the effect to be added, in ticks." },
+ { Name = "EffectIntensity", Type = "number", Notes = "The intensity (level) of the effect to be added. " },
+ { Name = "DistanceModifier", Type = "number", Notes = "The modifier for the effect intensity, based on distance. Used mainly for splash potions." },
+ },
+ Returns = [[
+ If the plugin returns true, the effect will not be added and none of the remaining hook handlers will
+ be called. If the plugin returns false, MCServer calls all the remaining hook handlers and finally
+ the effect is added to the entity.
+ ]],
+ }, -- HOOK_EXECUTE_COMMAND
+}
+
+
+
+
diff --git a/MCServer/Plugins/APIDump/Hooks/OnPlayerMoving.lua b/MCServer/Plugins/APIDump/Hooks/OnPlayerMoving.lua
index 2756529ef..4385bf94d 100644
--- a/MCServer/Plugins/APIDump/Hooks/OnPlayerMoving.lua
+++ b/MCServer/Plugins/APIDump/Hooks/OnPlayerMoving.lua
@@ -11,9 +11,11 @@ return
Params =
{
{ Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has moved. The object already has the new position stored in it." },
+ { Name = "OldPosition", Type = "{{Vector3d}}", Notes = "The old position." },
+ { Name = "NewPosition", Type = "{{Vector3d}}", Notes = "The new position." },
},
Returns = [[
- If the function returns true, movement is prohibited. FIXME: The player's client is not informed.</p>
+ If the function returns true, movement is prohibited.</p>
<p>
If the function returns false or no value, other plugins' callbacks are called and finally the new
position is permanently stored in the cPlayer object.</p>
diff --git a/MCServer/Plugins/APIDump/Hooks/OnPlayerUsedBlock.lua b/MCServer/Plugins/APIDump/Hooks/OnPlayerUsedBlock.lua
index 4c91ea89e..9a0e036b9 100644
--- a/MCServer/Plugins/APIDump/Hooks/OnPlayerUsedBlock.lua
+++ b/MCServer/Plugins/APIDump/Hooks/OnPlayerUsedBlock.lua
@@ -2,7 +2,7 @@ return
{
HOOK_PLAYER_USED_BLOCK =
{
- CalledWhen = "A player has just used a block (chest, furnace…). Notification only.",
+ CalledWhen = "A player has just used a block (chest, furnace...). Notification only.",
DefaultFnName = "OnPlayerUsedBlock", -- also used as pagename
Desc = [[
This hook is called after a {{cPlayer|player}} has right-clicked a block that can be used, such as a
diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core
-Subproject 3790f78d3f7503ff33a423b8e73e81a27556278
+Subproject 1b16c23c216d359e9fe0334c63deeecc347e69b
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index 918204deb..7e220952e 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -60,9 +60,10 @@ function Initialize(Plugin)
PM:BindCommand("/ff", "debuggers", HandleFurnaceFuel, "- Shows how long the currently held item would burn in a furnace");
PM:BindCommand("/sched", "debuggers", HandleSched, "- Schedules a simple countdown using cWorld:ScheduleTask()");
PM:BindCommand("/cs", "debuggers", HandleChunkStay, "- Tests the ChunkStay Lua integration for the specified chunk coords");
- PM:BindCommand("/compo", "debuggers", HandleCompo, "- Tests the cCompositeChat bindings")
- PM:BindCommand("/sb", "debuggers", HandleSetBiome, "- Sets the biome around you to the specified one")
- PM:BindCommand("/wesel", "debuggers", HandleWESel, "- Expands the current WE selection by 1 block in X/Z")
+ PM:BindCommand("/compo", "debuggers", HandleCompo, "- Tests the cCompositeChat bindings");
+ PM:BindCommand("/sb", "debuggers", HandleSetBiome, "- Sets the biome around you to the specified one");
+ PM:BindCommand("/wesel", "debuggers", HandleWESel, "- Expands the current WE selection by 1 block in X/Z");
+ PM:BindCommand("/rmitem", "debuggers", HandleRMItem, "- Remove the specified item from the inventory.");
Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers)
Plugin:AddWebTab("StressTest", HandleRequest_StressTest)
@@ -79,6 +80,7 @@ function Initialize(Plugin)
TestBlockAreasString()
TestStringBase64()
+ TestUUIDFromName()
--[[
-- Test cCompositeChat usage in console-logging:
@@ -274,6 +276,82 @@ end
+function TestUUIDFromName()
+ LOG("Testing UUID-from-Name resolution...")
+
+ -- Test by querying a few existing names, along with a non-existent one:
+ local PlayerNames =
+ {
+ "xoft",
+ "aloe_vera",
+ "nonexistent_player",
+ }
+ -- WARNING: Blocking operation! DO NOT USE IN TICK THREAD!
+ local UUIDs = cMojangAPI:GetUUIDsFromPlayerNames(PlayerNames)
+
+ -- Log the results:
+ for _, name in ipairs(PlayerNames) do
+ local UUID = UUIDs[name]
+ if (UUID == nil) then
+ LOG(" UUID(" .. name .. ") not found.")
+ else
+ LOG(" UUID(" .. name .. ") = \"" .. UUID .. "\"")
+ end
+ end
+
+ -- Test once more with the same players, valid-only. This should go directly from cache, so fast.
+ LOG("Testing again with the same valid players...")
+ local ValidPlayerNames =
+ {
+ "xoft",
+ "aloe_vera",
+ }
+ UUIDs = cMojangAPI:GetUUIDsFromPlayerNames(ValidPlayerNames);
+
+ -- Log the results:
+ for _, name in ipairs(ValidPlayerNames) do
+ local UUID = UUIDs[name]
+ if (UUID == nil) then
+ LOG(" UUID(" .. name .. ") not found.")
+ else
+ LOG(" UUID(" .. name .. ") = \"" .. UUID .. "\"")
+ end
+ end
+
+ -- Test yet again, cache-only:
+ LOG("Testing once more, cache only...")
+ local PlayerNames3 =
+ {
+ "xoft",
+ "aloe_vera",
+ "notch", -- Valid player name, but not cached (most likely :)
+ }
+ UUIDs = cMojangAPI:GetUUIDsFromPlayerNames(PlayerNames3, true)
+
+ -- Log the results:
+ for _, name in ipairs(PlayerNames3) do
+ local UUID = UUIDs[name]
+ if (UUID == nil) then
+ LOG(" UUID(" .. name .. ") not found.")
+ else
+ LOG(" UUID(" .. name .. ") = \"" .. UUID .. "\"")
+ end
+ end
+
+ LOG("UUID-from-Name resolution tests finished.")
+
+ LOG("Performing a Name-from-UUID test...")
+ -- local NameToTest = "aloe_vera"
+ local NameToTest = "xoft"
+ local Name = cMojangAPI:GetPlayerNameFromUUID(UUIDs[NameToTest])
+ LOG("Name(" .. UUIDs[NameToTest] .. ") = '" .. Name .. "', expected '" .. NameToTest .. "'.")
+ LOG("Name-from-UUID test finished.")
+end
+
+
+
+
+
function TestSQLiteBindings()
LOG("Testing SQLite bindings...");
@@ -533,7 +611,7 @@ function OnTakeDamage(Receiver, TDI)
-- Receiver is cPawn
-- TDI is TakeDamageInfo
- LOG(Receiver:GetClass() .. " was dealt " .. DamageTypeToString(TDI.DamageType) .. " damage: Raw " .. TDI.RawDamage .. ", Final " .. TDI.FinalDamage .. " (" .. (TDI.RawDamage - TDI.FinalDamage) .. " covered by armor)");
+ -- LOG(Receiver:GetClass() .. " was dealt " .. DamageTypeToString(TDI.DamageType) .. " damage: Raw " .. TDI.RawDamage .. ", Final " .. TDI.FinalDamage .. " (" .. (TDI.RawDamage - TDI.FinalDamage) .. " covered by armor)");
return false;
end
@@ -1105,6 +1183,41 @@ end
+function HandleRMItem(a_Split, a_Player)
+ -- Check params:
+ if (a_Split[2] == nil) then
+ a_Player:SendMessage("Usage: /rmitem <Item> [Count]")
+ return true
+ end
+
+ -- Parse the item type:
+ local Item = cItem()
+ if (not StringToItem(a_Split[2], Item)) then
+ a_Player:SendMessageFailure(a_Split[2] .. " isn't a valid item")
+ return true
+ end
+
+ -- Parse the optional item count
+ if (a_Split[3] ~= nil) then
+ local Count = tonumber(a_Split[3])
+ if (Count == nil) then
+ a_Player:SendMessageFailure(a_Split[3] .. " isn't a valid number")
+ return true
+ end
+
+ Item.m_ItemCount = Count
+ end
+
+ -- Remove the item:
+ local NumRemovedItems = a_Player:GetInventory():RemoveItem(Item)
+ a_Player:SendMessageSuccess("Removed " .. NumRemovedItems .. " Items!")
+ return true
+end
+
+
+
+
+
function HandleRequest_Debuggers(a_Request)
local FolderContents = cFile:GetFolderContents("./");
return "<p>The following objects have been returned by cFile:GetFolderContents():<ul><li>" .. table.concat(FolderContents, "</li><li>") .. "</li></ul></p>";
diff --git a/MCServer/Plugins/DiamondMover/DiamondMover.lua b/MCServer/Plugins/DiamondMover/DiamondMover.lua
index 0fdd32250..d3e70acfc 100644
--- a/MCServer/Plugins/DiamondMover/DiamondMover.lua
+++ b/MCServer/Plugins/DiamondMover/DiamondMover.lua
@@ -22,6 +22,8 @@ function Initialize(Plugin)
Plugin:SetVersion(1);
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_USED_ITEM, OnPlayerUsedItem);
+
+ LOG("Initialized " .. Plugin:GetName() .. " v." .. Plugin:GetVersion());
return true;
end
@@ -36,8 +38,8 @@ function OnPlayerUsedItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, Cu
return false;
end;
- if (Player:HasPermission("diamondmover.move") == false) then
- return true;
+ if (not Player:HasPermission("diamondmover.move")) then
+ return false;
end;
-- Rclk with a diamond to push in the direction the player is facing
@@ -56,7 +58,7 @@ function OnPlayerUsedItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, Cu
if (PlayerPitch > 70) then -- looking down
BlockY = BlockY - 1;
else
- local PlayerRot = Player:GetRotation() + 180; -- Convert [-180, 180] into [0, 360] for simpler conditions
+ local PlayerRot = Player:GetYaw() + 180; -- Convert [-180, 180] into [0, 360] for simpler conditions
if ((PlayerRot < 45) or (PlayerRot > 315)) then
BlockZ = BlockZ - 1;
else
diff --git a/MCServer/Plugins/ProtectionAreas b/MCServer/Plugins/ProtectionAreas
-Subproject 9edfee93048f214175cbed7eb2a3f77f7ac4abb
+Subproject 7765048fa740b8f119db72a4ccc546504f86b2a
diff --git a/MCServer/furnace.txt b/MCServer/furnace.txt
index 1e98583ba..d6177184b 100644
--- a/MCServer/furnace.txt
+++ b/MCServer/furnace.txt
@@ -88,3 +88,4 @@
! 269:1 = 200 # 1 Wooden Shovel -> 10 sec
! 290:1 = 200 # 1 Wooden Hoe -> 10 sec
! 268:1 = 200 # 1 Wooden Sword -> 10 sec
+
diff --git a/MCServer/monsters.ini b/MCServer/monsters.ini
index b631fc1a9..c4bc8c810 100644
--- a/MCServer/monsters.ini
+++ b/MCServer/monsters.ini
@@ -44,7 +44,7 @@ MaxHealth=10
AttackRange=2.0
AttackRate=1
AttackDamage=4.0
-SightDistance=25.0
+SightDistance=64.0
MaxHealth=40
[ZombiePigman]
@@ -185,4 +185,10 @@ AttackDamage=6.0
SightDistance=25.0
MaxHealth=100
+[Bat]
+AttackRange=2.0
+AttackRate=1
+AttackDamage=0.0
+SightDistance=25.0
+MaxHealth=6
diff --git a/README.md b/README.md
index b0f1cde35..85ae459a0 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ MCServer is a Minecraft server that is written in C++ and designed to be efficie
MCServer can run on PCs, Macs, and *nix. This includes android phones and tablets as well as Raspberry Pis.
-We currently support the protocol from Minecraft 1.2 all the way up to Minecraft 1.7.9.
+We currently support the protocol from Minecraft 1.2 all the way up to Minecraft 1.7.10.
Installation
------------
diff --git a/SetFlags.cmake b/SetFlags.cmake
index bf467ca01..0e2e0c277 100644
--- a/SetFlags.cmake
+++ b/SetFlags.cmake
@@ -1,3 +1,5 @@
+
+
macro (add_flags_lnk FLAGS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}")
@@ -28,7 +30,7 @@ endmacro()
macro(set_flags)
# Add coverage processing, if requested:
if (NOT MSVC)
-
+
if (CMAKE_BUILD_TYPE STREQUAL "COVERAGE")
message("Including CodeCoverage")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/lib/cmake-coverage/")
@@ -85,7 +87,7 @@ macro(set_flags)
# We use a signed char (fixes #640 on RasPi)
add_flags_cxx("-fsigned-char")
-
+
endif()
@@ -202,7 +204,7 @@ macro(enable_profile)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile;Coverage" CACHE STRING "" FORCE)
endif()
endmacro()
-
+
macro(set_exe_flags)
# Remove disabling the maximum warning level:
# clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings
@@ -216,22 +218,22 @@ macro(set_exe_flags)
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE}")
string(REPLACE "-w" "" CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_COVERAGE}")
add_flags_cxx("-Wall -Wextra -Wno-unused-parameter -Wno-error=switch")
-
+
# we support non-IEEE 754 fpus so can make no guarentees about error
add_flags_cxx("-ffast-math")
-
+
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# clang does not provide the __extern_always_inline macro and a part of libm depends on this when using fast-math
add_flags_cxx("-D__extern_always_inline=inline")
add_flags_cxx("-Werror -Weverything -Wno-c++98-compat-pedantic -Wno-string-conversion")
- add_flags_cxx("-Wno-extra-semi -Wno-error=switch-enum -Wno-documentation")
+ add_flags_cxx("-Wno-error=switch-enum -Wno-documentation -Wno-exit-time-destructors")
add_flags_cxx("-Wno-error=sign-conversion -Wno-error=conversion -Wno-padded")
add_flags_cxx("-Wno-error=deprecated -Wno-error=weak-vtables -Wno-error=float-equal")
add_flags_cxx("-Wno-error=missing-prototypes -Wno-error=non-virtual-dtor")
- add_flags_cxx("-Wno-error=covered-switch-default -Wno-error=shadow")
+ add_flags_cxx("-Wno-error=covered-switch-default -Wno-error=shadow -Wno-error=old-style-cast")
add_flags_cxx("-Wno-error=exit-time-destructors -Wno-error=missing-variable-declarations")
add_flags_cxx("-Wno-error=global-constructors -Wno-implicit-fallthrough")
- add_flags_cxx("-Wno-weak-vtables -Wno-switch-enum -Wno-exit-time-destructors")
+ add_flags_cxx("-Wno-error=extra-semi -Wno-weak-vtables -Wno-switch-enum")
endif()
endif()
diff --git a/Tools/MCADefrag/CMakeLists.txt b/Tools/MCADefrag/CMakeLists.txt
index 2a021049f..42b42018b 100644
--- a/Tools/MCADefrag/CMakeLists.txt
+++ b/Tools/MCADefrag/CMakeLists.txt
@@ -39,14 +39,12 @@ set_exe_flags()
set(SHARED_SRC
../../src/StringCompression.cpp
../../src/StringUtils.cpp
- ../../src/Log.cpp
- ../../src/MCLogger.cpp
+ ../../src/LoggerListeners.cpp
+ ../../src/Logger.cpp
)
set(SHARED_HDR
../../src/ByteBuffer.h
../../src/StringUtils.h
- ../../src/Log.h
- ../../src/MCLogger.h
)
flatten_files(SHARED_SRC)
flatten_files(SHARED_HDR)
diff --git a/Tools/MCADefrag/Globals.h b/Tools/MCADefrag/Globals.h
index 6593187e6..288069599 100644
--- a/Tools/MCADefrag/Globals.h
+++ b/Tools/MCADefrag/Globals.h
@@ -240,7 +240,7 @@ template <typename Type> class cItemCallback
public:
/// Called for each item in the internal list; return true to stop the loop, or false to continue enumerating
virtual bool Item(Type * a_Type) = 0;
- virtual ~cItemCallback() {};
+ virtual ~cItemCallback() {}
} ;
diff --git a/Tools/MCADefrag/MCADefrag.cpp b/Tools/MCADefrag/MCADefrag.cpp
index a2de7f957..d5d233fd2 100644
--- a/Tools/MCADefrag/MCADefrag.cpp
+++ b/Tools/MCADefrag/MCADefrag.cpp
@@ -5,7 +5,8 @@
#include "Globals.h"
#include "MCADefrag.h"
-#include "MCLogger.h"
+#include "Logger.h"
+#include "LoggerListeners.h"
#include "zlib/zlib.h"
@@ -21,7 +22,13 @@ static const Byte g_Zeroes[4096] = {0};
int main(int argc, char ** argv)
{
- new cMCLogger(Printf("Defrag_%08x.log", time(NULL)));
+ cLogger::cListener * consoleLogListener = MakeConsoleListener();
+ cLogger::cListener * fileLogListener = new cFileListener();
+ cLogger::GetInstance().AttachListener(consoleLogListener);
+ cLogger::GetInstance().AttachListener(fileLogListener);
+
+ cLogger::InitiateMultithreading();
+
cMCADefrag Defrag;
if (!Defrag.Init(argc, argv))
{
@@ -30,6 +37,11 @@ int main(int argc, char ** argv)
Defrag.Run();
+ cLogger::GetInstance().DetachListener(consoleLogListener);
+ delete consoleLogListener;
+ cLogger::GetInstance().DetachListener(fileLogListener);
+ delete fileLogListener;
+
return 0;
}
diff --git a/Tools/ProtoProxy/CMakeLists.txt b/Tools/ProtoProxy/CMakeLists.txt
index f0796363c..bc3923d90 100644
--- a/Tools/ProtoProxy/CMakeLists.txt
+++ b/Tools/ProtoProxy/CMakeLists.txt
@@ -34,20 +34,18 @@ set_exe_flags()
set(SHARED_SRC
../../src/ByteBuffer.cpp
../../src/StringUtils.cpp
- ../../src/Log.cpp
- ../../src/MCLogger.cpp
../../src/PolarSSL++/AesCfb128Decryptor.cpp
../../src/PolarSSL++/AesCfb128Encryptor.cpp
../../src/PolarSSL++/CryptoKey.cpp
../../src/PolarSSL++/CtrDrbgContext.cpp
../../src/PolarSSL++/EntropyContext.cpp
../../src/PolarSSL++/RsaPrivateKey.cpp
+ ../../src/LoggerListeners.cpp
+ ../../src/Logger.cpp
)
set(SHARED_HDR
../../src/ByteBuffer.h
../../src/StringUtils.h
- ../../src/Log.h
- ../../src/MCLogger.h
../../src/PolarSSL++/AesCfb128Decryptor.h
../../src/PolarSSL++/AesCfb128Encryptor.h
../../src/PolarSSL++/CryptoKey.h
diff --git a/lib/SQLiteCpp b/lib/SQLiteCpp
new file mode 160000
+Subproject 27b9d111818af3b05bcf4153bb6e380fe1dd681
diff --git a/lib/inifile/iniFile.cpp b/lib/inifile/iniFile.cpp
index ea03f5d35..2bf6c91ed 100644
--- a/lib/inifile/iniFile.cpp
+++ b/lib/inifile/iniFile.cpp
@@ -447,6 +447,15 @@ bool cIniFile::SetValueI(const AString & a_KeyName, const AString & a_ValueName,
+bool cIniFile::SetValueI(const AString & a_Keyname, const AString & a_ValueName, const Int64 a_Value, const bool a_CreateIfNotExists)
+{
+ return SetValue(a_Keyname, a_ValueName, Printf("%lld", a_Value), a_CreateIfNotExists);
+}
+
+
+
+
+
bool cIniFile::SetValueF(const AString & a_KeyName, const AString & a_ValueName, double const a_Value, const bool a_CreateIfNotExists)
{
return SetValue(a_KeyName, a_ValueName, Printf("%f", a_Value), a_CreateIfNotExists);
@@ -571,6 +580,24 @@ int cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, c
+Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue)
+{
+ AString Data;
+ Printf(Data, "%lld", defValue);
+ AString resultstring = GetValueSet(keyname, valuename, Data);
+ Int64 result = defValue;
+#ifdef _WIN32
+ sscanf_s(resultstring.c_str(), "%lld", &result);
+#else
+ sscanf(resultstring.c_str(), "%lld", &result);
+#endif
+ return result;
+}
+
+
+
+
+
bool cIniFile::DeleteValueByID(const int keyID, const int valueID)
{
if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size()))
diff --git a/lib/inifile/iniFile.h b/lib/inifile/iniFile.h
index 0bf1d917e..58fecd0cf 100644
--- a/lib/inifile/iniFile.h
+++ b/lib/inifile/iniFile.h
@@ -119,6 +119,7 @@ public:
AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "");
double GetValueSetF(const AString & keyname, const AString & valuename, const double defValue = 0.0);
int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0);
+ Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0);
bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false)
{
return (GetValueSetI(keyname, valuename, defValue ? 1 : 0) != 0);
@@ -141,6 +142,7 @@ public:
bool SetValue (const int keyID, const int valueID, const AString & value);
bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true);
bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true);
+ bool SetValueI(const AString & a_Keyname, const AString & a_ValueName, const Int64 a_Value, const bool a_CreateIfNotExists = true);
bool SetValueB(const AString & a_KeyName, const AString & a_ValueName, const bool a_Value, const bool a_CreateIfNotExists = true)
{
return SetValueI(a_KeyName, a_ValueName, int(a_Value), a_CreateIfNotExists);
diff --git a/lib/tolua++/src/bin/lua/_driver.lua b/lib/tolua++/src/bin/lua/_driver.lua
index 21db96098..1ca18862b 100644
--- a/lib/tolua++/src/bin/lua/_driver.lua
+++ b/lib/tolua++/src/bin/lua/_driver.lua
@@ -3,24 +3,27 @@
local mobdebugfound, mobdebug = pcall(require, "mobdebug")
if mobdebugfound then mobdebug.start() end
+-- Disable buffering for stdout, so that the results appear immediately:
+io.output():setvbuf("no")
+
-- The list of valid arguments that the ToLua scripts can process:
local KnownArgs = {
['v'] = true,
- ['h'] = true,
- ['p'] = true,
- ['P'] = true,
- ['o'] = true,
- ['n'] = true,
- ['H'] = true,
- ['S'] = true,
- ['1'] = true,
- ['L'] = true,
- ['D'] = true,
- ['W'] = true,
- ['C'] = true,
- ['E'] = true,
- ['t'] = true,
- ['q'] = true,
+ ['h'] = true,
+ ['p'] = true,
+ ['P'] = true,
+ ['o'] = true,
+ ['n'] = true,
+ ['H'] = true,
+ ['S'] = true,
+ ['1'] = true,
+ ['L'] = true,
+ ['D'] = true,
+ ['W'] = true,
+ ['C'] = true,
+ ['E'] = true,
+ ['t'] = true,
+ ['q'] = true,
}
diff --git a/src/AllocationPool.h b/src/AllocationPool.h
index 5d749a79e..3c9dbe8c9 100644
--- a/src/AllocationPool.h
+++ b/src/AllocationPool.h
@@ -61,7 +61,7 @@ class cListAllocationPool : public cAllocationPool<T>
free (m_FreeList.front());
m_FreeList.pop_front();
}
- }
+ }
virtual T * Allocate() override
{
@@ -90,7 +90,7 @@ class cListAllocationPool : public cAllocationPool<T>
}
virtual void Free(T * a_ptr) override
{
- if (a_ptr == NULL)
+ if (a_ptr == NULL)
{
return;
}
@@ -107,3 +107,7 @@ class cListAllocationPool : public cAllocationPool<T>
std::list<void *> m_FreeList;
std::auto_ptr<typename cAllocationPool<T>::cStarvationCallbacks> m_Callbacks;
};
+
+
+
+
diff --git a/src/Bindings/AllToLua.pkg b/src/Bindings/AllToLua.pkg
index 4fe86e1c5..88faa9dfc 100644
--- a/src/Bindings/AllToLua.pkg
+++ b/src/Bindings/AllToLua.pkg
@@ -40,13 +40,14 @@ $cfile "../Entities/Painting.h"
$cfile "../Entities/Pickup.h"
$cfile "../Entities/ProjectileEntity.h"
$cfile "../Entities/TNTEntity.h"
-$cfile "../Entities/Effects.h"
+$cfile "../Entities/EntityEffect.h"
$cfile "../Server.h"
$cfile "../World.h"
$cfile "../Inventory.h"
$cfile "../Enchantments.h"
$cfile "../Item.h"
$cfile "../ItemGrid.h"
+$cfile "../BlockEntities/BeaconEntity.h"
$cfile "../BlockEntities/BlockEntity.h"
$cfile "../BlockEntities/BlockEntityWithItems.h"
$cfile "../BlockEntities/ChestEntity.h"
@@ -77,6 +78,7 @@ $cfile "../Map.h"
$cfile "../MapManager.h"
$cfile "../Scoreboard.h"
$cfile "../Statistics.h"
+$cfile "../Protocol/MojangAPI.h"
diff --git a/src/Bindings/AllToLua_lua.bat.bat b/src/Bindings/AllToLua_lua.bat
index 81c738f32..81c738f32 100644
--- a/src/Bindings/AllToLua_lua.bat.bat
+++ b/src/Bindings/AllToLua_lua.bat
diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt
new file mode 100644
index 000000000..54152668a
--- /dev/null
+++ b/src/Bindings/CMakeLists.txt
@@ -0,0 +1,136 @@
+cmake_minimum_required (VERSION 2.6)
+project (MCServer)
+
+include_directories ("${PROJECT_SOURCE_DIR}/../")
+include_directories (".")
+
+SET (SRCS
+ Bindings.cpp
+ DeprecatedBindings.cpp
+ LuaChunkStay.cpp
+ LuaState.cpp
+ LuaWindow.cpp
+ ManualBindings.cpp
+ Plugin.cpp
+ PluginLua.cpp
+ PluginManager.cpp
+ WebPlugin.cpp
+)
+
+SET (HDRS
+ Bindings.h
+ DeprecatedBindings.h
+ LuaChunkStay.h
+ LuaFunctions.h
+ LuaState.h
+ LuaWindow.h
+ ManualBindings.h
+ Plugin.h
+ PluginLua.h
+ PluginManager.h
+ WebPlugin.h
+ tolua++.h
+)
+
+# List all the files that are generated as part of the Bindings build process
+set (BINDING_OUTPUTS
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bindings.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bindings.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/LuaState_Call.inc
+)
+
+set(BINDING_DEPENDENCIES
+ tolua
+ ../Bindings/virtual_method_hooks.lua
+ ../Bindings/AllToLua.pkg
+ ../Bindings/gen_LuaState_Call.lua
+ ../Bindings/LuaFunctions.h
+ ../Bindings/LuaWindow.h
+ ../Bindings/Plugin.h
+ ../Bindings/PluginLua.h
+ ../Bindings/PluginManager.h
+ ../Bindings/WebPlugin.h
+ ../BiomeDef.h
+ ../BlockArea.h
+ ../BlockEntities/BeaconEntity.h
+ ../BlockEntities/BlockEntity.h
+ ../BlockEntities/BlockEntityWithItems.h
+ ../BlockEntities/ChestEntity.h
+ ../BlockEntities/DispenserEntity.h
+ ../BlockEntities/DropSpenserEntity.h
+ ../BlockEntities/DropperEntity.h
+ ../BlockEntities/FurnaceEntity.h
+ ../BlockEntities/HopperEntity.h
+ ../BlockEntities/JukeboxEntity.h
+ ../BlockEntities/NoteEntity.h
+ ../BlockEntities/SignEntity.h
+ ../BlockEntities/MobHeadEntity.h
+ ../BlockEntities/FlowerPotEntity.h
+ ../BlockID.h
+ ../BoundingBox.h
+ ../ChatColor.h
+ ../ChunkDef.h
+ ../ClientHandle.h
+ ../CraftingRecipes.h
+ ../Cuboid.h
+ ../Defines.h
+ ../Enchantments.h
+ ../Entities/EntityEffect.h
+ ../Entities/Entity.h
+ ../Entities/Floater.h
+ ../Entities/Pawn.h
+ ../Entities/Painting.h
+ ../Entities/Pickup.h
+ ../Entities/Player.h
+ ../Entities/ProjectileEntity.h
+ ../Entities/ArrowEntity.h
+ ../Entities/ThrownEggEntity.h
+ ../Entities/ThrownEnderPearlEntity.h
+ ../Entities/ExpBottleEntity.h
+ ../Entities/ThrownSnowballEntity.h
+ ../Entities/FireChargeEntity.h
+ ../Entities/FireworkEntity.h
+ ../Entities/GhastFireballEntity.h
+ ../Entities/TNTEntity.h
+ ../Entities/ExpOrb.h
+ ../Entities/HangingEntity.h
+ ../Entities/ItemFrame.h
+ ../Generating/ChunkDesc.h
+ ../Group.h
+ ../Inventory.h
+ ../Item.h
+ ../ItemGrid.h
+ ../Mobs/Monster.h
+ ../OSSupport/File.h
+ ../Root.h
+ ../Server.h
+ ../StringUtils.h
+ ../Tracer.h
+ ../UI/Window.h
+ ../Vector3.h
+ ../WebAdmin.h
+ ../World.h
+)
+
+if (NOT MSVC)
+ ADD_CUSTOM_COMMAND(
+ # add any new generated bindings here
+ OUTPUT ${BINDING_OUTPUTS}
+
+ # Regenerate bindings:
+ COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+
+ # add any new generation dependencies here
+ DEPENDS ${BINDING_DEPENDENCIES}
+ )
+endif ()
+set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/Bindings.cpp PROPERTIES GENERATED TRUE)
+set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/Bindings.h PROPERTIES GENERATED TRUE)
+set_source_files_properties(${CMAKE_SOURCE_DIR}/src/Bindings/LuaState_Call.inc PROPERTIES GENERATED TRUE)
+
+if(NOT MSVC)
+ add_library(Bindings ${SRCS} ${HDRS})
+
+ target_link_libraries(Bindings lua sqlite tolualib polarssl)
+endif()
diff --git a/src/Bindings/DeprecatedBindings.cpp b/src/Bindings/DeprecatedBindings.cpp
index d51ba2da3..36243bc92 100644
--- a/src/Bindings/DeprecatedBindings.cpp
+++ b/src/Bindings/DeprecatedBindings.cpp
@@ -25,9 +25,9 @@ static int tolua_get_AllToLua_g_BlockLightValue(lua_State* tolua_S)
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
- if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
+ if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err))
{
- tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
+ tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err);
}
}
#endif
@@ -36,10 +36,10 @@ static int tolua_get_AllToLua_g_BlockLightValue(lua_State* tolua_S)
{
tolua_error(tolua_S, "array indexing out of range.", NULL);
}
- tolua_pushnumber(tolua_S,(lua_Number)cBlockInfo::GetLightValue((BLOCKTYPE)BlockType));
+ tolua_pushnumber(tolua_S, (lua_Number)cBlockInfo::GetLightValue((BLOCKTYPE)BlockType));
return 1;
}
-#endif //#ifndef TOLUA_DISABLE
+#endif // #ifndef TOLUA_DISABLE
@@ -53,8 +53,8 @@ static int tolua_get_AllToLua_g_BlockSpreadLightFalloff(lua_State* tolua_S)
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
- if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
- tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
+ if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err))
+ tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err);
}
#endif
BlockType = (int)tolua_tonumber(tolua_S, 2, 0);
@@ -65,7 +65,7 @@ static int tolua_get_AllToLua_g_BlockSpreadLightFalloff(lua_State* tolua_S)
tolua_pushnumber(tolua_S, (lua_Number)cBlockInfo::GetSpreadLightFalloff((BLOCKTYPE)BlockType));
return 1;
}
-#endif //#ifndef TOLUA_DISABLE
+#endif // #ifndef TOLUA_DISABLE
@@ -79,8 +79,8 @@ static int tolua_get_AllToLua_g_BlockTransparent(lua_State* tolua_S)
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
- if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
- tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
+ if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err))
+ tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err);
}
#endif
BlockType = (int)tolua_tonumber(tolua_S, 2, 0);
@@ -91,7 +91,7 @@ static int tolua_get_AllToLua_g_BlockTransparent(lua_State* tolua_S)
tolua_pushboolean(tolua_S, cBlockInfo::IsTransparent((BLOCKTYPE)BlockType));
return 1;
}
-#endif //#ifndef TOLUA_DISABLE
+#endif // #ifndef TOLUA_DISABLE
@@ -105,8 +105,8 @@ static int tolua_get_AllToLua_g_BlockOneHitDig(lua_State* tolua_S)
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
- if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
- tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
+ if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err))
+ tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err);
}
#endif
BlockType = (int)tolua_tonumber(tolua_S, 2, 0);
@@ -117,7 +117,7 @@ static int tolua_get_AllToLua_g_BlockOneHitDig(lua_State* tolua_S)
tolua_pushboolean(tolua_S, cBlockInfo::IsOneHitDig((BLOCKTYPE)BlockType));
return 1;
}
-#endif //#ifndef TOLUA_DISABLE
+#endif // #ifndef TOLUA_DISABLE
@@ -131,8 +131,8 @@ static int tolua_get_AllToLua_g_BlockPistonBreakable(lua_State* tolua_S)
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
- if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
- tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
+ if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err))
+ tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err);
}
#endif
BlockType = (int)tolua_tonumber(tolua_S, 2, 0);
@@ -143,7 +143,7 @@ static int tolua_get_AllToLua_g_BlockPistonBreakable(lua_State* tolua_S)
tolua_pushboolean(tolua_S, cBlockInfo::IsPistonBreakable((BLOCKTYPE)BlockType));
return 1;
}
-#endif //#ifndef TOLUA_DISABLE
+#endif // #ifndef TOLUA_DISABLE
@@ -157,8 +157,8 @@ static int tolua_get_AllToLua_g_BlockIsSnowable(lua_State* tolua_S)
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
- if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
- tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
+ if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err))
+ tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err);
}
#endif
BlockType = (int)tolua_tonumber(tolua_S, 2, 0);
@@ -169,33 +169,7 @@ static int tolua_get_AllToLua_g_BlockIsSnowable(lua_State* tolua_S)
tolua_pushboolean(tolua_S, cBlockInfo::IsSnowable((BLOCKTYPE)BlockType));
return 1;
}
-#endif //#ifndef TOLUA_DISABLE
-
-
-
-
-
-/* get function: g_BlockRequiresSpecialTool */
-#ifndef TOLUA_DISABLE_tolua_get_AllToLua_g_BlockRequiresSpecialTool
-static int tolua_get_AllToLua_g_BlockRequiresSpecialTool(lua_State* tolua_S)
-{
- int BlockType;
- #ifndef TOLUA_RELEASE
- {
- tolua_Error tolua_err;
- if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
- tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
- }
- #endif
- BlockType = (int)tolua_tonumber(tolua_S, 2, 0);
- if ((BlockType < 0) || (BlockType > E_BLOCK_MAX_TYPE_ID))
- {
- tolua_error(tolua_S, "array indexing out of range.", NULL);
- }
- tolua_pushboolean(tolua_S, cBlockInfo::RequiresSpecialTool((BLOCKTYPE)BlockType));
- return 1;
-}
-#endif //#ifndef TOLUA_DISABLE
+#endif // #ifndef TOLUA_DISABLE
@@ -209,8 +183,8 @@ static int tolua_get_AllToLua_g_BlockIsSolid(lua_State* tolua_S)
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
- if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
- tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
+ if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err))
+ tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err);
}
#endif
BlockType = (int)tolua_tonumber(tolua_S, 2, 0);
@@ -221,7 +195,7 @@ static int tolua_get_AllToLua_g_BlockIsSolid(lua_State* tolua_S)
tolua_pushboolean(tolua_S, (bool)cBlockInfo::IsSolid((BLOCKTYPE)BlockType));
return 1;
}
-#endif //#ifndef TOLUA_DISABLE
+#endif // #ifndef TOLUA_DISABLE
@@ -235,8 +209,8 @@ static int tolua_get_AllToLua_g_BlockFullyOccupiesVoxel(lua_State* tolua_S)
#ifndef TOLUA_RELEASE
{
tolua_Error tolua_err;
- if (!tolua_isnumber(tolua_S,2,0,&tolua_err))
- tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);
+ if (!tolua_isnumber(tolua_S, 2, 0, &tolua_err))
+ tolua_error(tolua_S, "#vinvalid type in array indexing.", &tolua_err);
}
#endif
BlockType = (int)tolua_tonumber(tolua_S, 2, 0);
@@ -247,7 +221,7 @@ static int tolua_get_AllToLua_g_BlockFullyOccupiesVoxel(lua_State* tolua_S)
tolua_pushboolean(tolua_S, (bool)cBlockInfo::FullyOccupiesVoxel((BLOCKTYPE)BlockType));
return 1;
}
-#endif //#ifndef TOLUA_DISABLE
+#endif // #ifndef TOLUA_DISABLE
@@ -263,7 +237,6 @@ void DeprecatedBindings::Bind(lua_State * tolua_S)
tolua_array(tolua_S, "g_BlockOneHitDig", tolua_get_AllToLua_g_BlockOneHitDig, NULL);
tolua_array(tolua_S, "g_BlockPistonBreakable", tolua_get_AllToLua_g_BlockPistonBreakable, NULL);
tolua_array(tolua_S, "g_BlockIsSnowable", tolua_get_AllToLua_g_BlockIsSnowable, NULL);
- tolua_array(tolua_S, "g_BlockRequiresSpecialTool", tolua_get_AllToLua_g_BlockRequiresSpecialTool, NULL);
tolua_array(tolua_S, "g_BlockIsSolid", tolua_get_AllToLua_g_BlockIsSolid, NULL);
tolua_array(tolua_S, "g_BlockFullyOccupiesVoxel", tolua_get_AllToLua_g_BlockFullyOccupiesVoxel, NULL);
diff --git a/src/Bindings/DeprecatedBindings.h b/src/Bindings/DeprecatedBindings.h
index 5fc3cfa80..037d50489 100644
--- a/src/Bindings/DeprecatedBindings.h
+++ b/src/Bindings/DeprecatedBindings.h
@@ -4,5 +4,5 @@ struct lua_State;
class DeprecatedBindings
{
public:
- static void Bind( lua_State* tolua_S );
+ static void Bind( lua_State* tolua_S);
};
diff --git a/src/Bindings/LuaChunkStay.cpp b/src/Bindings/LuaChunkStay.cpp
index 985a18a95..59b02d8f7 100644
--- a/src/Bindings/LuaChunkStay.cpp
+++ b/src/Bindings/LuaChunkStay.cpp
@@ -76,7 +76,7 @@ bool cLuaChunkStay::AddChunks(int a_ChunkCoordTableStackPos)
-void cLuaChunkStay::AddChunkCoord(cLuaState & L, int a_Index)
+void cLuaChunkStay::AddChunkCoord(cLuaState & L, int a_Index)
{
// Check that the element has 2 coords:
int NumCoords = luaL_getn(L, -1);
diff --git a/src/Bindings/LuaFunctions.h b/src/Bindings/LuaFunctions.h
index 629e2d77d..be1d9aaa9 100644
--- a/src/Bindings/LuaFunctions.h
+++ b/src/Bindings/LuaFunctions.h
@@ -1,6 +1,6 @@
#pragma once
-#include "../MCLogger.h"
+#include "Logger.h"
#include <time.h>
// tolua_begin
@@ -9,7 +9,7 @@ inline unsigned int GetTime()
return (unsigned int)time(0);
}
-inline std::string GetChar( std::string & a_Str, unsigned int a_Idx )
+inline std::string GetChar( std::string & a_Str, unsigned int a_Idx)
{
return std::string(1, a_Str[ a_Idx ]);
}
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index 32638df96..e123a87c9 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -40,7 +40,7 @@ const cLuaState::cRet cLuaState::Return = {};
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cLuaState:
cLuaState::cLuaState(const AString & a_SubsystemName) :
@@ -1336,9 +1336,8 @@ void cLuaState::LogStack(lua_State * a_LuaState, const char * a_Header)
{
UNUSED(a_Header); // The param seems unused when compiling for release, so the compiler warns
-
// Format string consisting only of %s is used to appease the compiler
- LOGD("%s",(a_Header != NULL) ? a_Header : "Lua C API Stack contents:");
+ LOGD("%s", (a_Header != NULL) ? a_Header : "Lua C API Stack contents:");
for (int i = lua_gettop(a_LuaState); i > 0; i--)
{
AString Value;
@@ -1371,7 +1370,7 @@ int cLuaState::ReportFnCallErrors(lua_State * a_LuaState)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cLuaState::cRef:
cLuaState::cRef::cRef(void) :
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index b1ac3578a..afac77ce8 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -128,7 +128,7 @@ public:
/** Creates a new instance. The LuaState is not initialized.
- a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins,
+ a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins,
or "LuaScript" for the cLuaScript template
*/
cLuaState(const AString & a_SubsystemName);
diff --git a/src/Bindings/LuaWindow.cpp b/src/Bindings/LuaWindow.cpp
index 733304eb2..1a2582ab0 100644
--- a/src/Bindings/LuaWindow.cpp
+++ b/src/Bindings/LuaWindow.cpp
@@ -7,13 +7,13 @@
#include "../UI/SlotArea.h"
#include "PluginLua.h"
#include "../Entities/Player.h"
-#include "lua/src/lauxlib.h" // Needed for LUA_REFNIL
+#include "lua/src/lauxlib.h" // Needed for LUA_REFNIL
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cLuaWindow:
cLuaWindow::cLuaWindow(cWindow::WindowType a_WindowType, int a_SlotsX, int a_SlotsY, const AString & a_Title) :
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index 88d40bfd9..5aa76eee3 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -16,6 +16,7 @@
#include "../WebAdmin.h"
#include "../ClientHandle.h"
#include "../BlockArea.h"
+#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/DispenserEntity.h"
@@ -26,6 +27,7 @@
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/FlowerPotEntity.h"
#include "../LineBlockTracer.h"
+#include "../Protocol/Authenticator.h"
#include "../WorldStorage/SchematicFileSerializer.h"
#include "../CompositeChat.h"
@@ -33,9 +35,7 @@
-/****************************
- * Better error reporting for Lua
- **/
+// Better error reporting for Lua
static int tolua_do_error(lua_State* L, const char * a_pMsg, tolua_Error * a_pToLuaError)
{
// Retrieve current function name
@@ -81,9 +81,33 @@ static int lua_do_error(lua_State* L, const char * a_pFormat, ...)
-/****************************
- * Lua bound functions with special return types
- **/
+// Lua bound functions with special return types
+static int tolua_Clamp(lua_State * tolua_S)
+{
+ cLuaState LuaState(tolua_S);
+ int NumArgs = lua_gettop(LuaState);
+ if (NumArgs != 3)
+ {
+ return lua_do_error(LuaState, "Error in function call '#funcname#': Requires 3 arguments, got %i", NumArgs);
+ }
+
+ if (!lua_isnumber(LuaState, 1) || !lua_isnumber(LuaState, 2) || !lua_isnumber(LuaState, 3))
+ {
+ return lua_do_error(LuaState, "Error in function call '#funcname#': Expected a number for parameters #1, #2 and #3");
+ }
+
+ lua_Number Number = tolua_tonumber(LuaState, 1, 0);
+ lua_Number Min = tolua_tonumber(LuaState, 2, 0);
+ lua_Number Max = tolua_tonumber(LuaState, 3, 0);
+
+ lua_Number Result = Clamp(Number, Min, Max);
+ LuaState.Push(Result);
+ return 1;
+}
+
+
+
+
static int tolua_StringSplit(lua_State * tolua_S)
{
@@ -144,7 +168,7 @@ static AString GetLogMessage(lua_State * tolua_S)
static int tolua_LOG(lua_State * tolua_S)
{
// If the param is a cCompositeChat, read the log level from it:
- cMCLogger::eLogLevel LogLevel = cMCLogger::llRegular;
+ cLogger::eLogLevel LogLevel = cLogger::llRegular;
tolua_Error err;
if (tolua_isusertype(tolua_S, 1, "cCompositeChat", false, &err))
{
@@ -152,7 +176,7 @@ static int tolua_LOG(lua_State * tolua_S)
}
// Log the message:
- cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), LogLevel);
+ cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), LogLevel);
return 0;
}
@@ -162,7 +186,7 @@ static int tolua_LOG(lua_State * tolua_S)
static int tolua_LOGINFO(lua_State * tolua_S)
{
- cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), cMCLogger::llInfo);
+ cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), cLogger::llInfo);
return 0;
}
@@ -172,7 +196,7 @@ static int tolua_LOGINFO(lua_State * tolua_S)
static int tolua_LOGWARN(lua_State * tolua_S)
{
- cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), cMCLogger::llWarning);
+ cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), cLogger::llWarning);
return 0;
}
@@ -182,7 +206,7 @@ static int tolua_LOGWARN(lua_State * tolua_S)
static int tolua_LOGERROR(lua_State * tolua_S)
{
- cMCLogger::GetInstance()->LogSimple(GetLogMessage(tolua_S).c_str(), cMCLogger::llError);
+ cLogger::GetInstance().LogSimple(GetLogMessage(tolua_S).c_str(), cLogger::llError);
return 0;
}
@@ -324,9 +348,9 @@ static int tolua_DoWith(lua_State* tolua_S)
{
public:
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
- : LuaState( a_LuaState )
- , FuncRef( a_FuncRef )
- , TableRef( a_TableRef )
+ : LuaState( a_LuaState)
+ , FuncRef( a_FuncRef)
+ , TableRef( a_TableRef)
{}
private:
@@ -363,7 +387,7 @@ static int tolua_DoWith(lua_State* tolua_S)
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal );
+ tolua_pushboolean(tolua_S, bRetVal);
return 1;
}
@@ -453,7 +477,7 @@ static int tolua_DoWithID(lua_State* tolua_S)
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal );
+ tolua_pushboolean(tolua_S, bRetVal);
return 1;
}
@@ -483,7 +507,6 @@ static int tolua_DoWithXYZ(lua_State* tolua_S)
int ItemX = ((int)tolua_tonumber(tolua_S, 2, 0));
int ItemY = ((int)tolua_tonumber(tolua_S, 3, 0));
int ItemZ = ((int)tolua_tonumber(tolua_S, 4, 0));
- LOG("x %i y %i z %i", ItemX, ItemY, ItemZ );
if (!lua_isfunction( tolua_S, 5))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #4");
@@ -511,9 +534,9 @@ static int tolua_DoWithXYZ(lua_State* tolua_S)
{
public:
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
- : LuaState( a_LuaState )
- , FuncRef( a_FuncRef )
- , TableRef( a_TableRef )
+ : LuaState( a_LuaState)
+ , FuncRef( a_FuncRef)
+ , TableRef( a_TableRef)
{}
private:
@@ -549,7 +572,7 @@ static int tolua_DoWithXYZ(lua_State* tolua_S)
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal );
+ tolua_pushboolean(tolua_S, bRetVal);
return 1;
}
@@ -557,10 +580,12 @@ static int tolua_DoWithXYZ(lua_State* tolua_S)
-template< class Ty1,
- class Ty2,
- bool (Ty1::*Func1)(int, int, cItemCallback<Ty2> &) >
-static int tolua_ForEachInChunk(lua_State* tolua_S)
+template<
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*Func1)(int, int, cItemCallback<Ty2> &)
+>
+static int tolua_ForEachInChunk(lua_State * tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
if ((NumArgs != 3) && (NumArgs != 4))
@@ -604,9 +629,9 @@ static int tolua_ForEachInChunk(lua_State* tolua_S)
{
public:
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
- : LuaState( a_LuaState )
- , FuncRef( a_FuncRef )
- , TableRef( a_TableRef )
+ : LuaState( a_LuaState)
+ , FuncRef( a_FuncRef)
+ , TableRef( a_TableRef)
{}
private:
@@ -643,7 +668,7 @@ static int tolua_ForEachInChunk(lua_State* tolua_S)
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal );
+ tolua_pushboolean(tolua_S, bRetVal);
return 1;
}
@@ -651,18 +676,20 @@ static int tolua_ForEachInChunk(lua_State* tolua_S)
-template< class Ty1,
- class Ty2,
- bool (Ty1::*Func1)(cItemCallback<Ty2> &) >
+template<
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*Func1)(cItemCallback<Ty2> &)
+>
static int tolua_ForEach(lua_State * tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
- if( NumArgs != 1 && NumArgs != 2)
+ if ((NumArgs != 1) && (NumArgs != 2))
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Requires 1 or 2 arguments, got %i", NumArgs);
}
- Ty1 * self = (Ty1 *) tolua_tousertype(tolua_S, 1, NULL);
+ Ty1 * self = (Ty1 *)tolua_tousertype(tolua_S, 1, NULL);
if (self == NULL)
{
return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
@@ -695,16 +722,16 @@ static int tolua_ForEach(lua_State * tolua_S)
{
public:
cLuaCallback(lua_State* a_LuaState, int a_FuncRef, int a_TableRef)
- : LuaState( a_LuaState )
- , FuncRef( a_FuncRef )
- , TableRef( a_TableRef )
+ : LuaState( a_LuaState)
+ , FuncRef( a_FuncRef)
+ , TableRef( a_TableRef)
{}
private:
virtual bool Item(Ty2 * a_Item) override
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, FuncRef); /* Push function reference */
- tolua_pushusertype( LuaState, a_Item, Ty2::GetClassStatic() );
+ tolua_pushusertype( LuaState, a_Item, Ty2::GetClassStatic());
if (TableRef != LUA_REFNIL)
{
lua_rawgeti( LuaState, LUA_REGISTRYINDEX, TableRef); /* Push table reference */
@@ -734,7 +761,7 @@ static int tolua_ForEach(lua_State * tolua_S)
luaL_unref(tolua_S, LUA_REGISTRYINDEX, FuncRef);
/* Push return value on stack */
- tolua_pushboolean(tolua_S, bRetVal );
+ tolua_pushboolean(tolua_S, bRetVal);
return 1;
}
@@ -959,7 +986,7 @@ tolua_lerror:
static int tolua_cWorld_TryGetHeight(lua_State * tolua_S)
{
// Exported manually, because tolua would require the out-only param a_Height to be used when calling
- // Takes (a_World,) a_BlockX, a_BlockZ
+ // Takes a_World, a_BlockX, a_BlockZ
// Returns Height, IsValid
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
@@ -1361,7 +1388,7 @@ static int tolua_cPluginManager_AddHook(lua_State * tolua_S)
static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
- if( NumArgs != 1)
+ if (NumArgs != 1)
{
LOGWARN("Error in function call 'ForEachCommand': Requires 1 argument, got %i", NumArgs);
return 0;
@@ -1391,8 +1418,8 @@ static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
{
public:
cLuaCallback(lua_State * a_LuaState, int a_FuncRef)
- : LuaState( a_LuaState )
- , FuncRef( a_FuncRef )
+ : LuaState( a_LuaState)
+ , FuncRef( a_FuncRef)
{}
private:
@@ -1438,7 +1465,7 @@ static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
- if( NumArgs != 1)
+ if (NumArgs != 1)
{
LOGWARN("Error in function call 'ForEachConsoleCommand': Requires 1 argument, got %i", NumArgs);
return 0;
@@ -1468,8 +1495,8 @@ static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S)
{
public:
cLuaCallback(lua_State * a_LuaState, int a_FuncRef)
- : LuaState( a_LuaState )
- , FuncRef( a_FuncRef )
+ : LuaState( a_LuaState)
+ , FuncRef( a_FuncRef)
{}
private:
@@ -1927,28 +1954,28 @@ static int tolua_cPluginLua_AddWebTab(lua_State * tolua_S)
int Reference = LUA_REFNIL;
if (
- tolua_isstring(tolua_S, 2, 0, &tolua_err ) &&
- lua_isfunction(tolua_S, 3 )
+ tolua_isstring(tolua_S, 2, 0, &tolua_err) &&
+ lua_isfunction(tolua_S, 3)
)
{
Reference = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
- Title = ((std::string) tolua_tocppstring(tolua_S,2,0));
+ Title = ((std::string)tolua_tocppstring(tolua_S, 2, 0));
}
else
{
return tolua_do_error(tolua_S, "#ferror calling function '#funcname#'", &tolua_err);
}
- if( Reference != LUA_REFNIL )
+ if (Reference != LUA_REFNIL)
{
- if( !self->AddWebTab( Title.c_str(), tolua_S, Reference ) )
+ if (!self->AddWebTab(Title.c_str(), tolua_S, Reference))
{
- luaL_unref( tolua_S, LUA_REGISTRYINDEX, Reference );
+ luaL_unref(tolua_S, LUA_REGISTRYINDEX, Reference);
}
}
else
{
- LOGERROR("ERROR: cPluginLua:AddWebTab invalid function reference in 2nd argument (Title: \"%s\")", Title.c_str() );
+ LOGWARNING("cPluginLua:AddWebTab: invalid function reference in 2nd argument (Title: \"%s\")", Title.c_str());
}
return 0;
@@ -1964,7 +1991,7 @@ static int tolua_cPluginLua_AddTab(lua_State* tolua_S)
LOGWARN("WARNING: Using deprecated function AddTab()! Use AddWebTab() instead. (plugin \"%s\" in folder \"%s\")",
self->GetName().c_str(), self->GetDirectory().c_str()
);
- return tolua_cPluginLua_AddWebTab( tolua_S );
+ return tolua_cPluginLua_AddWebTab( tolua_S);
}
@@ -2012,12 +2039,12 @@ static int tolua_md5(lua_State* tolua_S)
-static int tolua_push_StringStringMap(lua_State* tolua_S, std::map< std::string, std::string >& a_StringStringMap )
+static int tolua_push_StringStringMap(lua_State* tolua_S, std::map< std::string, std::string >& a_StringStringMap)
{
lua_newtable(tolua_S);
int top = lua_gettop(tolua_S);
- for( std::map< std::string, std::string >::iterator it = a_StringStringMap.begin(); it != a_StringStringMap.end(); ++it )
+ for (std::map<std::string, std::string>::iterator it = a_StringStringMap.begin(); it != a_StringStringMap.end(); ++it)
{
const char* key = it->first.c_str();
const char* value = it->second.c_str();
@@ -2061,11 +2088,11 @@ static int tolua_get_HTTPRequest_FormData(lua_State* tolua_S)
lua_newtable(tolua_S);
int top = lua_gettop(tolua_S);
- for( std::map< std::string, HTTPFormData >::iterator it = FormData.begin(); it != FormData.end(); ++it )
+ for (std::map<std::string, HTTPFormData>::iterator it = FormData.begin(); it != FormData.end(); ++it)
{
- lua_pushstring(tolua_S, it->first.c_str() );
- tolua_pushusertype(tolua_S, &(it->second), "HTTPFormData" );
- //lua_pushlstring(tolua_S, it->second.Value.c_str(), it->second.Value.size() ); // Might contain binary data
+ lua_pushstring(tolua_S, it->first.c_str());
+ tolua_pushusertype(tolua_S, &(it->second), "HTTPFormData");
+ // lua_pushlstring(tolua_S, it->second.Value.c_str(), it->second.Value.size()); // Might contain binary data
lua_settable(tolua_S, top);
}
@@ -2101,6 +2128,62 @@ static int tolua_cWebAdmin_GetPlugins(lua_State * tolua_S)
+/** Binding for cWebAdmin::GetHTMLEscapedString.
+Manual code required because ToLua generates an extra return value */
+static int tolua_AllToLua_cWebAdmin_GetHTMLEscapedString(lua_State * tolua_S)
+{
+ // Check the param types:
+ cLuaState S(tolua_S);
+ if (
+ !S.CheckParamUserTable(1, "cWebAdmin") ||
+ !S.CheckParamString(2) ||
+ !S.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Get the parameters:
+ AString Input;
+ S.GetStackValue(2, Input);
+
+ // Convert and return:
+ S.Push(cWebAdmin::GetHTMLEscapedString(Input));
+ return 1;
+}
+
+
+
+
+
+/** Binding for cWebAdmin::GetURLEncodedString.
+Manual code required because ToLua generates an extra return value */
+static int tolua_AllToLua_cWebAdmin_GetURLEncodedString(lua_State * tolua_S)
+{
+ // Check the param types:
+ cLuaState S(tolua_S);
+ if (
+ !S.CheckParamUserTable(1, "cWebAdmin") ||
+ !S.CheckParamString(2) ||
+ !S.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ // Get the parameters:
+ AString Input;
+ S.GetStackValue(2, Input);
+
+ // Convert and return:
+ S.Push(cWebAdmin::GetURLEncodedString(Input));
+ return 1;
+}
+
+
+
+
+
static int tolua_cWebPlugin_GetTabNames(lua_State * tolua_S)
{
cWebPlugin* self = (cWebPlugin*) tolua_tousertype(tolua_S, 1, NULL);
@@ -2110,12 +2193,12 @@ static int tolua_cWebPlugin_GetTabNames(lua_State * tolua_S)
lua_newtable(tolua_S);
int index = 1;
cWebPlugin::TabNameList::const_iterator iter = TabNames.begin();
- while(iter != TabNames.end())
+ while (iter != TabNames.end())
{
const AString & FancyName = iter->first;
const AString & WebName = iter->second;
- tolua_pushstring( tolua_S, WebName.c_str() ); // Because the WebName is supposed to be unique, use it as key
- tolua_pushstring( tolua_S, FancyName.c_str() );
+ tolua_pushstring( tolua_S, WebName.c_str()); // Because the WebName is supposed to be unique, use it as key
+ tolua_pushstring( tolua_S, FancyName.c_str());
//
lua_rawset(tolua_S, -3);
++iter;
@@ -2157,6 +2240,165 @@ static int tolua_cClientHandle_SendPluginMessage(lua_State * L)
+static int tolua_cMojangAPI_AddPlayerNameToUUIDMapping(lua_State * L)
+{
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cMojangAPI") ||
+ !S.CheckParamString(2) ||
+ !S.CheckParamString(3) ||
+ !S.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Retrieve the parameters:
+ AString UUID, PlayerName;
+ S.GetStackValue(2, PlayerName);
+ S.GetStackValue(3, UUID);
+
+ // Store in the cache:
+ cRoot::Get()->GetMojangAPI().AddPlayerNameToUUIDMapping(PlayerName, UUID);
+ return 0;
+}
+
+
+
+
+
+static int tolua_cMojangAPI_GetPlayerNameFromUUID(lua_State * L)
+{
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cMojangAPI") ||
+ !S.CheckParamString(2) ||
+ !S.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ AString UUID;
+ S.GetStackValue(2, UUID);
+
+ // If the UseOnlyCached param was given, read it; default to false
+ bool ShouldUseCacheOnly = false;
+ if (lua_gettop(L) == 3)
+ {
+ ShouldUseCacheOnly = (lua_toboolean(L, 3) != 0);
+ lua_pop(L, 1);
+ }
+
+ // Return the PlayerName:
+ AString PlayerName = cRoot::Get()->GetMojangAPI().GetPlayerNameFromUUID(UUID, ShouldUseCacheOnly);
+ S.Push(PlayerName);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cMojangAPI_GetUUIDFromPlayerName(lua_State * L)
+{
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cMojangAPI") ||
+ !S.CheckParamString(2) ||
+ !S.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ AString PlayerName;
+ S.GetStackValue(2, PlayerName);
+
+ // If the UseOnlyCached param was given, read it; default to false
+ bool ShouldUseCacheOnly = false;
+ if (lua_gettop(L) == 3)
+ {
+ ShouldUseCacheOnly = (lua_toboolean(L, 3) != 0);
+ lua_pop(L, 1);
+ }
+
+ // Return the UUID:
+ AString UUID = cRoot::Get()->GetMojangAPI().GetUUIDFromPlayerName(PlayerName, ShouldUseCacheOnly);
+ S.Push(UUID);
+ return 1;
+}
+
+
+
+
+
+static int tolua_cMojangAPI_GetUUIDsFromPlayerNames(lua_State * L)
+{
+ cLuaState S(L);
+ if (
+ !S.CheckParamUserTable(1, "cMojangAPI") ||
+ !S.CheckParamTable(2) ||
+ !S.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ // Convert the input table into AStringVector:
+ AStringVector PlayerNames;
+ int NumNames = luaL_getn(L, 2);
+ PlayerNames.reserve(NumNames);
+ for (int i = 1; i <= NumNames; i++)
+ {
+ lua_rawgeti(L, 2, i);
+ AString Name;
+ S.GetStackValue(-1, Name);
+ if (!Name.empty())
+ {
+ PlayerNames.push_back(Name);
+ }
+ lua_pop(L, 1);
+ }
+
+ // If the UseOnlyCached param was given, read it; default to false
+ bool ShouldUseCacheOnly = false;
+ if (lua_gettop(L) == 3)
+ {
+ ShouldUseCacheOnly = (lua_toboolean(L, 3) != 0);
+ lua_pop(L, 1);
+ }
+
+ // Push the output table onto the stack:
+ lua_newtable(L);
+
+ // Get the UUIDs:
+ AStringVector UUIDs = cRoot::Get()->GetMojangAPI().GetUUIDsFromPlayerNames(PlayerNames, ShouldUseCacheOnly);
+ if (UUIDs.size() != PlayerNames.size())
+ {
+ // A hard error has occured while processing the request, no UUIDs were returned. Return an empty table:
+ return 1;
+ }
+
+ // Convert to output table, PlayerName -> UUID:
+ size_t len = UUIDs.size();
+ for (size_t i = 0; i < len; i++)
+ {
+ if (UUIDs[i].empty())
+ {
+ // No UUID was provided for PlayerName[i], skip it in the resulting table
+ continue;
+ }
+ lua_pushlstring(L, UUIDs[i].c_str(), UUIDs[i].length());
+ lua_setfield(L, 3, PlayerNames[i].c_str());
+ }
+ return 1;
+}
+
+
+
+
+
static int Lua_ItemGrid_GetSlotCoords(lua_State * L)
{
tolua_Error tolua_err;
@@ -2592,7 +2834,7 @@ static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * tolua_S)
}
AString Filename = tolua_tostring(tolua_S, 2, 0);
- bool res = cSchematicFileSerializer::LoadFromSchematicFile(*self,Filename);
+ bool res = cSchematicFileSerializer::LoadFromSchematicFile(*self, Filename);
tolua_pushboolean(tolua_S, res);
return 1;
}
@@ -2652,7 +2894,7 @@ static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S)
return 0;
}
AString Filename = tolua_tostring(tolua_S, 2, 0);
- bool res = cSchematicFileSerializer::SaveToSchematicFile(*self,Filename);
+ bool res = cSchematicFileSerializer::SaveToSchematicFile(*self, Filename);
tolua_pushboolean(tolua_S, res);
return 1;
}
@@ -2943,6 +3185,7 @@ static int tolua_cCompositeChat_UnderlineUrls(lua_State * tolua_S)
void ManualBindings::Bind(lua_State * tolua_S)
{
tolua_beginmodule(tolua_S, NULL);
+ tolua_function(tolua_S, "Clamp", tolua_Clamp);
tolua_function(tolua_S, "StringSplit", tolua_StringSplit);
tolua_function(tolua_S, "StringSplitAndTrim", tolua_StringSplitAndTrim);
tolua_function(tolua_S, "LOG", tolua_LOG);
@@ -2997,6 +3240,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_beginmodule(tolua_S, "cWorld");
tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay);
tolua_function(tolua_S, "DoWithBlockEntityAt", tolua_DoWithXYZ<cWorld, cBlockEntity, &cWorld::DoWithBlockEntityAt>);
+ tolua_function(tolua_S, "DoWithBeaconAt", tolua_DoWithXYZ<cWorld, cBeaconEntity, &cWorld::DoWithBeaconAt>);
tolua_function(tolua_S, "DoWithChestAt", tolua_DoWithXYZ<cWorld, cChestEntity, &cWorld::DoWithChestAt>);
tolua_function(tolua_S, "DoWithDispenserAt", tolua_DoWithXYZ<cWorld, cDispenserEntity, &cWorld::DoWithDispenserAt>);
tolua_function(tolua_S, "DoWithDropSpenserAt", tolua_DoWithXYZ<cWorld, cDropSpenserEntity, &cWorld::DoWithDropSpenserAt>);
@@ -3066,17 +3310,19 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "AddWebTab", tolua_cPluginLua_AddWebTab);
tolua_endmodule(tolua_S);
- tolua_cclass(tolua_S,"HTTPRequest","HTTPRequest","",NULL);
- tolua_beginmodule(tolua_S,"HTTPRequest");
- // tolua_variable(tolua_S,"Method",tolua_get_HTTPRequest_Method,tolua_set_HTTPRequest_Method);
- // tolua_variable(tolua_S,"Path",tolua_get_HTTPRequest_Path,tolua_set_HTTPRequest_Path);
- tolua_variable(tolua_S,"FormData",tolua_get_HTTPRequest_FormData,0);
- tolua_variable(tolua_S,"Params",tolua_get_HTTPRequest_Params,0);
- tolua_variable(tolua_S,"PostParams",tolua_get_HTTPRequest_PostParams,0);
+ tolua_cclass(tolua_S, "HTTPRequest", "HTTPRequest", "", NULL);
+ tolua_beginmodule(tolua_S, "HTTPRequest");
+ // tolua_variable(tolua_S, "Method", tolua_get_HTTPRequest_Method, tolua_set_HTTPRequest_Method);
+ // tolua_variable(tolua_S, "Path", tolua_get_HTTPRequest_Path, tolua_set_HTTPRequest_Path);
+ tolua_variable(tolua_S, "FormData", tolua_get_HTTPRequest_FormData, 0);
+ tolua_variable(tolua_S, "Params", tolua_get_HTTPRequest_Params, 0);
+ tolua_variable(tolua_S, "PostParams", tolua_get_HTTPRequest_PostParams, 0);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cWebAdmin");
- tolua_function(tolua_S, "GetPlugins", tolua_cWebAdmin_GetPlugins);
+ tolua_function(tolua_S, "GetHTMLEscapedString", tolua_AllToLua_cWebAdmin_GetHTMLEscapedString);
+ tolua_function(tolua_S, "GetPlugins", tolua_cWebAdmin_GetPlugins);
+ tolua_function(tolua_S, "GetURLEncodedString", tolua_AllToLua_cWebAdmin_GetURLEncodedString);
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cWebPlugin");
@@ -3089,6 +3335,13 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "SendPluginMessage", tolua_cClientHandle_SendPluginMessage);
tolua_endmodule(tolua_S);
+ tolua_beginmodule(tolua_S, "cMojangAPI");
+ tolua_function(tolua_S, "AddPlayerNameToUUIDMapping", tolua_cMojangAPI_AddPlayerNameToUUIDMapping);
+ tolua_function(tolua_S, "GetPlayerNameFromUUID", tolua_cMojangAPI_GetPlayerNameFromUUID);
+ tolua_function(tolua_S, "GetUUIDFromPlayerName", tolua_cMojangAPI_GetUUIDFromPlayerName);
+ tolua_function(tolua_S, "GetUUIDsFromPlayerNames", tolua_cMojangAPI_GetUUIDsFromPlayerNames);
+ tolua_endmodule(tolua_S);
+
tolua_beginmodule(tolua_S, "cItemGrid");
tolua_function(tolua_S, "GetSlotCoords", Lua_ItemGrid_GetSlotCoords);
tolua_endmodule(tolua_S);
diff --git a/src/Bindings/ManualBindings.h b/src/Bindings/ManualBindings.h
index f38e26267..36161c6a2 100644
--- a/src/Bindings/ManualBindings.h
+++ b/src/Bindings/ManualBindings.h
@@ -4,5 +4,5 @@ struct lua_State;
class ManualBindings
{
public:
- static void Bind( lua_State* tolua_S );
+ static void Bind( lua_State* tolua_S);
};
diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h
index 8ba20c026..2cc5cade3 100644
--- a/src/Bindings/Plugin.h
+++ b/src/Bindings/Plugin.h
@@ -33,7 +33,7 @@ class cPlugin
public:
// tolua_end
- cPlugin( const AString & a_PluginDirectory );
+ cPlugin( const AString & a_PluginDirectory);
virtual ~cPlugin();
virtual void OnDisable(void) {}
@@ -42,10 +42,7 @@ public:
// Called each tick
virtual void Tick(float a_Dt) = 0;
- /**
- * On all these functions, return true if you want to override default behavior and not call other plugins on that callback.
- * You can also return false, so default behavior is used.
- **/
+ /** Calls the specified hook with the params given. Returns the bool that the hook callback returns.*/
virtual bool OnBlockSpread (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source) = 0;
virtual bool OnBlockToPickups (cWorld * a_World, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cItems & a_Pickups) = 0;
virtual bool OnChat (cPlayer * a_Player, AString & a_Message) = 0;
@@ -57,13 +54,14 @@ public:
virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) = 0;
virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) = 0;
+ virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) = 0;
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) = 0;
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username) = 0;
virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) = 0;
virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) = 0;
- virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer) = 0;
+ virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) = 0;
virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) = 0;
virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) = 0;
virtual bool OnPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
@@ -75,7 +73,7 @@ public:
virtual bool OnPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel) = 0;
virtual bool OnPlayerJoined (cPlayer & a_Player) = 0;
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) = 0;
- virtual bool OnPlayerMoved (cPlayer & a_Player) = 0;
+ virtual bool OnPlayerMoving (cPlayer & a_Player, const Vector3d a_OldPosition, const Vector3d a_NewPosition) = 0;
virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) = 0;
@@ -117,10 +115,10 @@ public:
virtual bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output) = 0;
/// All bound commands are to be removed, do any language-dependent cleanup here
- virtual void ClearCommands(void) {} ;
+ virtual void ClearCommands(void) {}
/// All bound console commands are to be removed, do any language-dependent cleanup here
- virtual void ClearConsoleCommands(void) {} ;
+ virtual void ClearConsoleCommands(void) {}
// tolua_begin
const AString & GetName(void) const { return m_Name; }
@@ -143,7 +141,7 @@ public:
E_SQUIRREL, // OBSOLETE, but kept in place to remind us of the horrors lurking in the history
};
PluginLanguage GetLanguage() { return m_Language; }
- void SetLanguage( PluginLanguage a_Language ) { m_Language = a_Language; }
+ void SetLanguage( PluginLanguage a_Language) { m_Language = a_Language; }
private:
PluginLanguage m_Language;
@@ -151,7 +149,7 @@ private:
int m_Version;
AString m_Directory;
-}; // tolua_export
+}; // tolua_export
diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp
index 104380ea4..37db78994 100644
--- a/src/Bindings/PluginLua.cpp
+++ b/src/Bindings/PluginLua.cpp
@@ -25,7 +25,7 @@ extern "C"
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cPluginLua:
cPluginLua::cPluginLua(const AString & a_PluginDirectory) :
@@ -78,7 +78,7 @@ bool cPluginLua::Initialize(void)
{
cCSLock Lock(m_CriticalSection);
if (!m_LuaState.IsValid())
- {
+ {
m_LuaState.Create();
m_LuaState.RegisterAPILibs();
@@ -420,6 +420,26 @@ bool cPluginLua::OnDisconnect(cClientHandle & a_Client, const AString & a_Reason
+bool cPluginLua::OnEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier)
+{
+ cCSLock Lock(m_CriticalSection);
+ bool res = false;
+ cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_ENTITY_ADD_EFFECT];
+ for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
+ {
+ m_LuaState.Call((int)(**itr), &a_Entity, a_EffectType, a_EffectDurationTicks, a_EffectIntensity, a_DistanceModifier, cLuaState::Return, res);
+ if (res)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split)
{
cCSLock Lock(m_CriticalSection);
@@ -575,14 +595,14 @@ bool cPluginLua::OnHopperPushingItem(cWorld & a_World, cHopperEntity & a_Hopper,
-bool cPluginLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer)
+bool cPluginLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_KILLING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), &a_Victim, a_Killer, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_Victim, a_Killer, &a_TDI, cLuaState::Return, res);
if (res)
{
return true;
@@ -815,14 +835,14 @@ bool cPluginLua::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_Block
-bool cPluginLua::OnPlayerMoved(cPlayer & a_Player)
+bool cPluginLua::OnPlayerMoving(cPlayer & a_Player, const Vector3d a_OldPosition, const Vector3d a_NewPosition)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_MOVING];
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
{
- m_LuaState.Call((int)(**itr), &a_Player, cLuaState::Return, res);
+ m_LuaState.Call((int)(**itr), &a_Player, &a_OldPosition, &a_NewPosition, cLuaState::Return, res);
if (res)
{
return true;
@@ -995,7 +1015,7 @@ bool cPluginLua::OnPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_Block
-bool cPluginLua::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
+bool cPluginLua::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
cCSLock Lock(m_CriticalSection);
bool res = false;
@@ -1274,8 +1294,8 @@ bool cPluginLua::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI)
bool cPluginLua::OnUpdatedSign(
- cWorld * a_World,
- int a_BlockX, int a_BlockY, int a_BlockZ,
+ cWorld * a_World,
+ int a_BlockX, int a_BlockY, int a_BlockZ,
const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4,
cPlayer * a_Player
)
@@ -1299,8 +1319,8 @@ bool cPluginLua::OnUpdatedSign(
bool cPluginLua::OnUpdatingSign(
- cWorld * a_World,
- int a_BlockX, int a_BlockY, int a_BlockZ,
+ cWorld * a_World,
+ int a_BlockX, int a_BlockY, int a_BlockZ,
AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4,
cPlayer * a_Player
)
@@ -1497,7 +1517,7 @@ bool cPluginLua::CanAddOldStyleHook(int a_HookType)
return true;
}
- LOGWARNING("Plugin %s wants to add a hook (%d), but it doesn't provide the callback function \"%s\" for it. The plugin need not work properly.",
+ LOGWARNING("Plugin %s wants to add a hook (%d), but it doesn't provide the callback function \"%s\" for it. The plugin need not work properly.",
GetName().c_str(), a_HookType, FnName
);
m_LuaState.LogStackTrace();
@@ -1524,6 +1544,7 @@ const char * cPluginLua::GetHookFnName(int a_HookType)
case cPluginManager::HOOK_CRAFTING_NO_RECIPE: return "OnCraftingNoRecipe";
case cPluginManager::HOOK_DISCONNECT: return "OnDisconnect";
case cPluginManager::HOOK_PLAYER_ANIMATION: return "OnPlayerAnimation";
+ case cPluginManager::HOOK_ENTITY_ADD_EFFECT: return "OnEntityAddEffect";
case cPluginManager::HOOK_EXECUTE_COMMAND: return "OnExecuteCommand";
case cPluginManager::HOOK_HANDSHAKE: return "OnHandshake";
case cPluginManager::HOOK_KILLING: return "OnKilling";
@@ -1634,7 +1655,7 @@ int cPluginLua::CallFunctionFromForeignState(
-AString cPluginLua::HandleWebRequest(const HTTPRequest * a_Request )
+AString cPluginLua::HandleWebRequest(const HTTPRequest * a_Request)
{
cCSLock Lock(m_CriticalSection);
std::string RetVal = "";
@@ -1649,7 +1670,7 @@ AString cPluginLua::HandleWebRequest(const HTTPRequest * a_Request )
sWebPluginTab * Tab = 0;
for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr)
{
- if ((*itr)->SafeTitle.compare(SafeTabName) == 0) // This is the one! Rawr
+ if ((*itr)->SafeTitle.compare(SafeTabName) == 0) // This is the one! Rawr
{
Tab = *itr;
break;
diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h
index 9c9de95c6..6df86f7a1 100644
--- a/src/Bindings/PluginLua.h
+++ b/src/Bindings/PluginLua.h
@@ -80,13 +80,14 @@ public:
virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) override;
virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) override;
+ virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) override;
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) override;
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username) override;
virtual bool OnHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum) override;
virtual bool OnHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum) override;
- virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer) override;
+ virtual bool OnKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI) override;
virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) override;
virtual bool OnPlayerAnimation (cPlayer & a_Player, int a_Animation) override;
virtual bool OnPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
@@ -97,7 +98,7 @@ public:
virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward) override;
virtual bool OnPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel) override;
virtual bool OnPlayerJoined (cPlayer & a_Player) override;
- virtual bool OnPlayerMoved (cPlayer & a_Player) override;
+ virtual bool OnPlayerMoving (cPlayer & a_Player, const Vector3d a_OldPosition, const Vector3d a_NewPosition) override;
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) override;
virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
@@ -143,8 +144,8 @@ public:
virtual const AString GetWebTitle(void) const {return GetName(); }
// cWebPlugin and WebAdmin stuff
- virtual AString HandleWebRequest(const HTTPRequest * a_Request ) override;
- bool AddWebTab(const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference); // >> EXPORTED IN MANUALBINDINGS <<
+ virtual AString HandleWebRequest(const HTTPRequest * a_Request) override;
+ bool AddWebTab(const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference); // >> EXPORTED IN MANUALBINDINGS <<
/** Binds the command to call the function specified by a Lua function reference. Simply adds to CommandMap. */
void BindCommand(const AString & a_Command, int a_FnRef);
diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp
index 7e6502515..dbc359f0e 100644
--- a/src/Bindings/PluginManager.cpp
+++ b/src/Bindings/PluginManager.cpp
@@ -72,7 +72,7 @@ void cPluginManager::FindPlugins(void)
{
PluginMap::iterator thiz = itr;
++thiz;
- m_Plugins.erase( itr );
+ m_Plugins.erase( itr);
itr = thiz;
continue;
}
@@ -124,44 +124,58 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
// Check if the Plugins section exists.
int KeyNum = a_SettingsIni.FindKey("Plugins");
- // If it does, how many plugins are there?
- int NumPlugins = ((KeyNum != -1) ? (a_SettingsIni.GetNumValues(KeyNum)) : 0);
-
if (KeyNum == -1)
{
InsertDefaultPlugins(a_SettingsIni);
+ KeyNum = a_SettingsIni.FindKey("Plugins");
}
- else if (NumPlugins > 0)
+
+ // How many plugins are there?
+ int NumPlugins = a_SettingsIni.GetNumValues(KeyNum);
+
+ for (int i = 0; i < NumPlugins; i++)
{
- for (int i = 0; i < NumPlugins; i++)
+ AString ValueName = a_SettingsIni.GetValueName(KeyNum, i);
+ if (ValueName.compare("Plugin") == 0)
{
- AString ValueName = a_SettingsIni.GetValueName(KeyNum, i);
- if (ValueName.compare("Plugin") == 0)
+ AString PluginFile = a_SettingsIni.GetValue(KeyNum, i);
+ if (!PluginFile.empty())
{
- AString PluginFile = a_SettingsIni.GetValue(KeyNum, i);
- if (!PluginFile.empty())
+ if (m_Plugins.find(PluginFile) != m_Plugins.end())
{
- if (m_Plugins.find(PluginFile) != m_Plugins.end())
- {
- LoadPlugin(PluginFile);
- }
+ LoadPlugin(PluginFile);
}
}
}
}
+
+ // Remove invalid plugins from the PluginMap.
+ for (PluginMap::iterator itr = m_Plugins.begin(); itr != m_Plugins.end();)
+ {
+ if (itr->second == NULL)
+ {
+ PluginMap::iterator thiz = itr;
+ ++thiz;
+ m_Plugins.erase(itr);
+ itr = thiz;
+ continue;
+ }
+ ++itr;
+ }
+
size_t NumLoadedPlugins = GetNumPlugins();
if (NumLoadedPlugins == 0)
{
LOG("-- No Plugins Loaded --");
}
- else if (NumLoadedPlugins > 1)
+ else if (NumLoadedPlugins == 1)
{
- LOG("-- Loaded %i Plugins --", (int)NumLoadedPlugins);
+ LOG("-- Loaded 1 Plugin --");
}
else
{
- LOG("-- Loaded 1 Plugin --");
+ LOG("-- Loaded %i Plugins --", (int)NumLoadedPlugins);
}
CallHookPluginsLoaded();
}
@@ -474,6 +488,25 @@ bool cPluginManager::CallHookDisconnect(cClientHandle & a_Client, const AString
+bool cPluginManager::CallHookEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier)
+{
+ FIND_HOOK(HOOK_ENTITY_ADD_EFFECT);
+ VERIFY_HOOK;
+
+ for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
+ {
+ if ((*itr)->OnEntityAddEffect(a_Entity, a_EffectType, a_EffectDurationTicks, a_EffectIntensity, a_DistanceModifier))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
bool cPluginManager::CallHookExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split)
{
FIND_HOOK(HOOK_EXECUTE_COMMAND);
@@ -588,14 +621,14 @@ bool cPluginManager::CallHookHopperPushingItem(cWorld & a_World, cHopperEntity &
-bool cPluginManager::CallHookKilling(cEntity & a_Victim, cEntity * a_Killer)
+bool cPluginManager::CallHookKilling(cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI)
{
FIND_HOOK(HOOK_KILLING);
VERIFY_HOOK;
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
- if ((*itr)->OnKilling(a_Victim, a_Killer))
+ if ((*itr)->OnKilling(a_Victim, a_Killer, a_TDI))
{
return true;
}
@@ -816,14 +849,14 @@ bool cPluginManager::CallHookPlayerLeftClick(cPlayer & a_Player, int a_BlockX, i
-bool cPluginManager::CallHookPlayerMoving(cPlayer & a_Player)
+bool cPluginManager::CallHookPlayerMoving(cPlayer & a_Player, const Vector3d a_OldPosition, const Vector3d a_NewPosition)
{
FIND_HOOK(HOOK_PLAYER_MOVING);
VERIFY_HOOK;
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
- if ((*itr)->OnPlayerMoved(a_Player))
+ if ((*itr)->OnPlayerMoving(a_Player, a_OldPosition, a_NewPosition))
{
return true;
}
@@ -1411,11 +1444,11 @@ cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer * a_Player,
-cPlugin * cPluginManager::GetPlugin( const AString & a_Plugin ) const
+cPlugin * cPluginManager::GetPlugin( const AString & a_Plugin) const
{
- for( PluginMap::const_iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr )
+ for (PluginMap::const_iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr)
{
- if (itr->second == NULL ) continue;
+ if (itr->second == NULL) continue;
if (itr->second->GetName().compare(a_Plugin) == 0)
{
return itr->second;
@@ -1465,7 +1498,7 @@ bool cPluginManager::DisablePlugin(const AString & a_PluginName)
if (itr->first.compare(a_PluginName) == 0) // _X 2013_02_01: wtf? Isn't this supposed to be what find() does?
{
m_DisablePluginList.push_back(itr->second);
- itr->second = NULL; // Get rid of this thing right away
+ itr->second = NULL; // Get rid of this thing right away
return true;
}
return false;
diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h
index d435024bb..e0573f386 100644
--- a/src/Bindings/PluginManager.h
+++ b/src/Bindings/PluginManager.h
@@ -51,10 +51,12 @@ class cBlockEntityWithItems;
-class cPluginManager // tolua_export
-{ // tolua_export
-public: // tolua_export
-
+// tolua_begin
+class cPluginManager
+{
+public:
+ // tolua_end
+
// Called each tick
virtual void Tick(float a_Dt);
@@ -82,6 +84,7 @@ public: // tolua_export
HOOK_CRAFTING_NO_RECIPE,
HOOK_DISCONNECT,
HOOK_PLAYER_ANIMATION,
+ HOOK_ENTITY_ADD_EFFECT,
HOOK_EXECUTE_COMMAND,
HOOK_EXPLODED,
HOOK_EXPLODING,
@@ -156,15 +159,17 @@ public: // tolua_export
/** Returns the instance of the Plugin Manager (there is only ever one) */
- static cPluginManager * Get(void); // tolua_export
+ static cPluginManager * Get(void); // tolua_export
typedef std::map< AString, cPlugin * > PluginMap;
typedef std::list< cPlugin * > PluginList;
- cPlugin * GetPlugin( const AString & a_Plugin ) const; // tolua_export
- const PluginMap & GetAllPlugins() const; // >> EXPORTED IN MANUALBINDINGS <<
+ cPlugin * GetPlugin( const AString & a_Plugin) const; // tolua_export
+ const PluginMap & GetAllPlugins() const; // >> EXPORTED IN MANUALBINDINGS <<
- void FindPlugins(); // tolua_export
- void ReloadPlugins(); // tolua_export
+ // tolua_begin
+ void FindPlugins();
+ void ReloadPlugins();
+ // tolua_end
/** Adds the plugin to the list of plugins called for the specified hook type. Handles multiple adds as a single add */
void AddHook(cPlugin * a_Plugin, int a_HookType);
@@ -183,13 +188,14 @@ public: // tolua_export
bool CallHookCollectingPickup (cPlayer * a_Player, cPickup & a_Pickup);
bool CallHookCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookDisconnect (cClientHandle & a_Client, const AString & a_Reason);
+ bool CallHookEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier);
bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split); // If a_Player == NULL, it is a console cmd
bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
bool CallHookExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
bool CallHookHandshake (cClientHandle * a_ClientHandle, const AString & a_Username);
bool CallHookHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum);
bool CallHookHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum);
- bool CallHookKilling (cEntity & a_Victim, cEntity * a_Killer);
+ bool CallHookKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI);
bool CallHookLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username);
bool CallHookPlayerAnimation (cPlayer & a_Player, int a_Animation);
bool CallHookPlayerBreakingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
@@ -200,7 +206,7 @@ public: // tolua_export
bool CallHookPlayerFishing (cPlayer & a_Player, cItems a_Reward);
bool CallHookPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel);
bool CallHookPlayerJoined (cPlayer & a_Player);
- bool CallHookPlayerMoving (cPlayer & a_Player);
+ bool CallHookPlayerMoving (cPlayer & a_Player, const Vector3d a_OldPosition, const Vector3d a_NewPosition);
bool CallHookPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status);
bool CallHookPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
@@ -333,8 +339,8 @@ private:
bool AddPlugin(cPlugin * a_Plugin);
/** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns crExecuted if the command is executed. */
- cPluginManager::CommandResult HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
-} ; // tolua_export
+ cPluginManager::CommandResult HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
+} ; // tolua_export
diff --git a/src/Bindings/WebPlugin.cpp b/src/Bindings/WebPlugin.cpp
index bf45405ba..4fa64d937 100644
--- a/src/Bindings/WebPlugin.cpp
+++ b/src/Bindings/WebPlugin.cpp
@@ -45,12 +45,12 @@ cWebPlugin::~cWebPlugin()
std::list<std::pair<AString, AString> > cWebPlugin::GetTabNames(void)
{
std::list< std::pair< AString, AString > > NameList;
- for( TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr )
+ for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr)
{
std::pair< AString, AString > StringPair;
StringPair.first = (*itr)->Title;
StringPair.second = (*itr)->SafeTitle;
- NameList.push_back( StringPair );
+ NameList.push_back( StringPair);
}
return NameList;
}
@@ -64,27 +64,29 @@ std::pair< AString, AString > cWebPlugin::GetTabNameForRequest(const HTTPRequest
std::pair< AString, AString > Names;
AStringVector Split = StringSplit(a_Request->Path, "/");
- if( Split.size() > 1 )
+ if (Split.size() > 1)
{
- sWebPluginTab* Tab = 0;
- if( Split.size() > 2 ) // If we got the tab name, show that page
+ sWebPluginTab * Tab = NULL;
+ if (Split.size() > 2) // If we got the tab name, show that page
{
- for( TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr )
+ for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr)
{
- if( (*itr)->SafeTitle.compare( Split[2] ) == 0 ) // This is the one! Rawr
+ if ((*itr)->SafeTitle.compare(Split[2]) == 0) // This is the one!
{
Tab = *itr;
break;
}
}
}
- else // Otherwise show the first tab
+ else // Otherwise show the first tab
{
- if( GetTabs().size() > 0 )
+ if (GetTabs().size() > 0)
+ {
Tab = *GetTabs().begin();
+ }
}
- if( Tab )
+ if (Tab != NULL)
{
Names.first = Tab->Title;
Names.second = Tab->SafeTitle;
@@ -97,17 +99,21 @@ std::pair< AString, AString > cWebPlugin::GetTabNameForRequest(const HTTPRequest
-AString cWebPlugin::SafeString( const AString & a_String )
+AString cWebPlugin::SafeString(const AString & a_String)
{
AString RetVal;
- for( unsigned int i = 0; i < a_String.size(); ++i )
+ for (unsigned int i = 0; i < a_String.size(); ++i)
{
char c = a_String[i];
- if( c == ' ' )
+ if (c == ' ')
{
c = '_';
}
- RetVal.push_back( c );
+ RetVal.push_back( c);
}
return RetVal;
}
+
+
+
+
diff --git a/src/Bindings/WebPlugin.h b/src/Bindings/WebPlugin.h
index 22587b892..46bc0cd2d 100644
--- a/src/Bindings/WebPlugin.h
+++ b/src/Bindings/WebPlugin.h
@@ -19,9 +19,9 @@ public:
// tolua_begin
virtual const AString GetWebTitle(void) const = 0;
- virtual AString HandleWebRequest(const HTTPRequest * a_Request ) = 0;
+ virtual AString HandleWebRequest(const HTTPRequest * a_Request) = 0;
- static AString SafeString( const AString & a_String );
+ static AString SafeString( const AString & a_String);
// tolua_end
struct sWebPluginTab
@@ -36,8 +36,8 @@ public:
TabList & GetTabs() { return m_Tabs; }
typedef std::list< std::pair<AString, AString> > TabNameList;
- TabNameList GetTabNames(); // >> EXPORTED IN MANUALBINDINGS <<
- std::pair< AString, AString > GetTabNameForRequest(const HTTPRequest* a_Request );
+ TabNameList GetTabNames(); // >> EXPORTED IN MANUALBINDINGS <<
+ std::pair< AString, AString > GetTabNameForRequest(const HTTPRequest* a_Request);
private:
TabList m_Tabs;
diff --git a/src/Bindings/gen_LuaState_Call.lua b/src/Bindings/gen_LuaState_Call.lua
index fb1797dc0..17bae82b3 100644
--- a/src/Bindings/gen_LuaState_Call.lua
+++ b/src/Bindings/gen_LuaState_Call.lua
@@ -13,7 +13,7 @@ separate the arguments from the return values, a special type of cLuaState::cRet
-print("Generating LuaState_Call.inc...")
+print("Generating LuaState_Call.inc . . .")
@@ -189,7 +189,7 @@ f:close()
-print("LuaState_Call.inc generated")
+print("LuaState_Call.inc generated.")
diff --git a/src/BiomeDef.cpp b/src/BiomeDef.cpp
index 9852b3dd9..02f8c2232 100644
--- a/src/BiomeDef.cpp
+++ b/src/BiomeDef.cpp
@@ -10,12 +10,13 @@
// The "map" used for biome <-> string conversions:
-static struct {
+static struct
+{
EMCSBiome m_Biome;
const char * m_String;
} g_BiomeMap[] =
{
- {biOcean, "Ocean"} ,
+ {biOcean, "Ocean"},
{biPlains, "Plains"},
{biDesert, "Desert"},
{biExtremeHills, "ExtremeHills"},
diff --git a/src/BlockArea.cpp b/src/BlockArea.cpp
index 185582ba3..a0dcb5ec8 100644
--- a/src/BlockArea.cpp
+++ b/src/BlockArea.cpp
@@ -28,10 +28,10 @@ typedef void (CombinatorFunc)(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLE
// This wild construct allows us to pass a function argument and still have it inlined by the compiler :)
/// Merges two blocktypes and blockmetas of the specified sizes and offsets using the specified combinator function
-template<bool MetasValid, CombinatorFunc Combinator>
+template<bool MetasValid, CombinatorFunc Combinator>
void InternalMergeBlocks(
BLOCKTYPE * a_DstTypes, const BLOCKTYPE * a_SrcTypes,
- NIBBLETYPE * a_DstMetas, const NIBBLETYPE * a_SrcMetas,
+ NIBBLETYPE * a_DstMetas, const NIBBLETYPE * a_SrcMetas,
int a_SizeX, int a_SizeY, int a_SizeZ,
int a_SrcOffX, int a_SrcOffY, int a_SrcOffZ,
int a_DstOffX, int a_DstOffY, int a_DstOffZ,
@@ -59,7 +59,7 @@ void InternalMergeBlocks(
}
else
{
- BLOCKTYPE FakeDestMeta = 0;
+ NIBBLETYPE FakeDestMeta = 0;
Combinator(a_DstTypes[DstIdx], a_SrcTypes[SrcIdx], FakeDestMeta, (NIBBLETYPE)0);
}
++DstIdx;
@@ -136,7 +136,7 @@ void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE
return;
}
- // Air is always hollowed out
+ // Air is always hollowed out
if (a_SrcType == E_BLOCK_AIR)
{
a_DstType = E_BLOCK_AIR;
@@ -269,7 +269,7 @@ void MergeCombinatorMask(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBlockArea:
cBlockArea::cBlockArea(void) :
@@ -781,7 +781,7 @@ void cBlockArea::Fill(int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_Block
-void cBlockArea::FillRelCuboid(int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ,
+void cBlockArea::FillRelCuboid(int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ,
int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight
)
@@ -1759,7 +1759,7 @@ NIBBLETYPE cBlockArea::GetNibble(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBL
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBlockArea::cChunkReader:
cBlockArea::cChunkReader::cChunkReader(cBlockArea & a_Area) :
@@ -2226,7 +2226,7 @@ void cBlockArea::MergeByStrategy(const cBlockArea & a_Src, int a_RelX, int a_Rel
m_Size.x, m_Size.y, m_Size.z
);
return;
- } // case msDifference
+ } // case msDifference
case cBlockArea::msMask:
{
diff --git a/src/BlockArea.h b/src/BlockArea.h
index 2bd26facd..a95ba7788 100644
--- a/src/BlockArea.h
+++ b/src/BlockArea.h
@@ -175,7 +175,7 @@ public:
void Fill(int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta = 0, NIBBLETYPE a_BlockLight = 0, NIBBLETYPE a_BlockSkyLight = 0x0f);
/** Fills a cuboid inside the block area with the specified data */
- void FillRelCuboid(int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ,
+ void FillRelCuboid(int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ,
int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta = 0,
NIBBLETYPE a_BlockLight = 0, NIBBLETYPE a_BlockSkyLight = 0x0f
);
@@ -357,7 +357,7 @@ protected:
/** Sets the specified datatypes at the specified location. */
void RelSetData(
- int a_RelX, int a_RelY, int a_RelZ,
+ int a_RelX, int a_RelY, int a_RelZ,
int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
NIBBLETYPE a_BlockLight, NIBBLETYPE a_BlockSkyLight
);
diff --git a/src/BlockEntities/BeaconEntity.cpp b/src/BlockEntities/BeaconEntity.cpp
index 0914353eb..dcf659f47 100644
--- a/src/BlockEntities/BeaconEntity.cpp
+++ b/src/BlockEntities/BeaconEntity.cpp
@@ -3,36 +3,34 @@
#include "BeaconEntity.h"
#include "../BlockArea.h"
+#include "../Entities/Player.h"
-cBeaconEntity::cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
- super(E_BLOCK_BEACON, a_BlockX, a_BlockY, a_BlockZ, a_World)
+cBeaconEntity::cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
+ : super(E_BLOCK_BEACON, a_BlockX, a_BlockY, a_BlockZ, 1, 1, a_World)
+ , m_IsActive(false)
+ , m_BeaconLevel(0)
+ , m_PrimaryEffect(cEntityEffect::effNoEffect)
+ , m_SecondaryEffect(cEntityEffect::effNoEffect)
{
+ UpdateBeacon();
}
-int cBeaconEntity::GetPyramidLevel(void)
+char cBeaconEntity::CalculatePyramidLevel(void)
{
cBlockArea Area;
- int MinY = GetPosY() - 4;
- if (MinY < 0)
- {
- MinY = 0;
- }
- int MaxY = GetPosY() - 1;
- if (MaxY < 0)
- {
- MaxY = 0;
- }
+ int MinY = std::max(GetPosY() - 4, 0);
+ int MaxY = std::max(GetPosY() - 1, 0);
Area.Read(
- m_World,
+ m_World,
GetPosX() - 4, GetPosX() + 4,
MinY, MaxY,
GetPosZ() - 4, GetPosZ() + 4,
@@ -42,7 +40,7 @@ int cBeaconEntity::GetPyramidLevel(void)
int Layer = 1;
int MiddleXZ = 4;
- for (int Y = Area.GetSizeY() - 1; Y > 0; Y--)
+ for (int Y = (Area.GetSizeY() - 1); Y >= 0; Y--)
{
for (int X = MiddleXZ - Layer; X <= (MiddleXZ + Layer); X++)
{
@@ -50,14 +48,99 @@ int cBeaconEntity::GetPyramidLevel(void)
{
if (!IsMineralBlock(Area.GetRelBlockType(X, Y, Z)))
{
- return Layer - 1;
+ return (Layer - 1);
}
}
}
Layer++;
}
- return Layer - 1;
+ return (Layer - 1);
+}
+
+
+
+
+
+bool cBeaconEntity::IsValidEffect(cEntityEffect::eType a_Effect, char a_BeaconLevel)
+{
+ switch (a_Effect)
+ {
+ case cEntityEffect::effRegeneration: return (a_BeaconLevel >= 4);
+ case cEntityEffect::effStrength: return (a_BeaconLevel >= 3);
+ case cEntityEffect::effResistance: return (a_BeaconLevel >= 2);
+ case cEntityEffect::effJumpBoost: return (a_BeaconLevel >= 2);
+ case cEntityEffect::effSpeed: return (a_BeaconLevel >= 1);
+ case cEntityEffect::effHaste: return (a_BeaconLevel >= 1);
+ case cEntityEffect::effNoEffect: return true;
+
+ default:
+ {
+ LOGD("%s: Invalid beacon effect: %d", __FUNCTION__, (int)a_Effect);
+ return false;
+ }
+ }
+}
+
+
+
+
+
+bool cBeaconEntity::SetPrimaryEffect(cEntityEffect::eType a_Effect)
+{
+ if (!IsValidEffect(a_Effect, m_BeaconLevel))
+ {
+ m_PrimaryEffect = cEntityEffect::effNoEffect;
+ return false;
+ }
+
+ m_PrimaryEffect = a_Effect;
+
+ // Send window update:
+ if (GetWindow() != NULL)
+ {
+ GetWindow()->SetProperty(1, m_PrimaryEffect);
+ }
+ return true;
+}
+
+
+
+
+
+bool cBeaconEntity::SetSecondaryEffect(cEntityEffect::eType a_Effect)
+{
+ if (!IsValidEffect(a_Effect, m_BeaconLevel))
+ {
+ m_SecondaryEffect = cEntityEffect::effNoEffect;
+ return false;
+ }
+
+ m_SecondaryEffect = a_Effect;
+
+ // Send window update:
+ if (GetWindow() != NULL)
+ {
+ GetWindow()->SetProperty(2, m_SecondaryEffect);
+ }
+ return true;
+}
+
+
+
+
+
+bool cBeaconEntity::IsBeaconBlocked(void)
+{
+ for (int Y = m_PosY; Y < cChunkDef::Height; ++Y)
+ {
+ BLOCKTYPE Block = m_World->GetBlock(m_PosX, Y, m_PosZ);
+ if (!cBlockInfo::IsTransparent(Block))
+ {
+ return true;
+ }
+ }
+ return false;
}
@@ -66,7 +149,7 @@ int cBeaconEntity::GetPyramidLevel(void)
bool cBeaconEntity::IsMineralBlock(BLOCKTYPE a_BlockType)
{
- switch(a_BlockType)
+ switch (a_BlockType)
{
case E_BLOCK_DIAMOND_BLOCK:
case E_BLOCK_GOLD_BLOCK:
@@ -83,8 +166,113 @@ bool cBeaconEntity::IsMineralBlock(BLOCKTYPE a_BlockType)
+void cBeaconEntity::UpdateBeacon(void)
+{
+ int OldBeaconLevel = m_BeaconLevel;
+
+ if (IsBeaconBlocked())
+ {
+ m_IsActive = false;
+ m_BeaconLevel = 0;
+ }
+ else
+ {
+ m_BeaconLevel = CalculatePyramidLevel();
+ m_IsActive = (m_BeaconLevel > 0);
+ }
+
+ if (m_BeaconLevel != OldBeaconLevel)
+ {
+ // Send window update:
+ if (GetWindow() != NULL)
+ {
+ GetWindow()->SetProperty(0, m_BeaconLevel);
+ }
+ }
+
+ // TODO: Add achievement
+}
+
+
+
+
+
+void cBeaconEntity::GiveEffects(void)
+{
+ if (!m_IsActive || (m_BeaconLevel < 0))
+ {
+ return;
+ }
+
+ int Radius = m_BeaconLevel * 10 + 10;
+ short EffectLevel = 0;
+ if ((m_BeaconLevel >= 4) && (m_PrimaryEffect == m_SecondaryEffect))
+ {
+ EffectLevel = 1;
+ }
+
+ cEntityEffect::eType SecondaryEffect = cEntityEffect::effNoEffect;
+ if ((m_BeaconLevel >= 4) && (m_PrimaryEffect != m_SecondaryEffect) && (m_SecondaryEffect > 0))
+ {
+ SecondaryEffect = m_SecondaryEffect;
+ }
+
+ class cPlayerCallback : public cPlayerListCallback
+ {
+ int m_Radius;
+ int m_PosX, m_PosY, m_PosZ;
+ cEntityEffect::eType m_PrimaryEffect, m_SecondaryEffect;
+ short m_EffectLevel;
+
+ virtual bool Item(cPlayer * a_Player)
+ {
+ Vector3d PlayerPosition = Vector3d(a_Player->GetPosition());
+ if (PlayerPosition.y > (double)m_PosY)
+ {
+ PlayerPosition.y = (double)m_PosY;
+ }
+
+ // TODO: Vanilla minecraft uses an AABB check instead of a radius one
+ Vector3d BeaconPosition = Vector3d(m_PosX, m_PosY, m_PosZ);
+ if ((PlayerPosition - BeaconPosition).Length() <= m_Radius)
+ {
+ a_Player->AddEntityEffect(m_PrimaryEffect, 180, m_EffectLevel);
+
+ if (m_SecondaryEffect != cEntityEffect::effNoEffect)
+ {
+ a_Player->AddEntityEffect(m_SecondaryEffect, 180, 0);
+ }
+ }
+ return false;
+ }
+
+ public:
+ cPlayerCallback(int a_Radius, int a_PosX, int a_PosY, int a_PosZ, cEntityEffect::eType a_PrimaryEffect, cEntityEffect::eType a_SecondaryEffect, short a_EffectLevel)
+ : m_Radius(a_Radius)
+ , m_PosX(a_PosX)
+ , m_PosY(a_PosY)
+ , m_PosZ(a_PosZ)
+ , m_PrimaryEffect(a_PrimaryEffect)
+ , m_SecondaryEffect(a_SecondaryEffect)
+ , m_EffectLevel(a_EffectLevel)
+ {};
+
+ } PlayerCallback(Radius, m_PosX, m_PosY, m_PosZ, m_PrimaryEffect, SecondaryEffect, EffectLevel);
+ GetWorld()->ForEachPlayer(PlayerCallback);
+}
+
+
+
+
+
bool cBeaconEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
+ // Update the beacon every 4 seconds
+ if ((GetWorld()->GetWorldAge() % 80) == 0)
+ {
+ UpdateBeacon();
+ GiveEffects();
+ }
return false;
}
@@ -92,23 +280,94 @@ bool cBeaconEntity::Tick(float a_Dt, cChunk & a_Chunk)
-void cBeaconEntity::SaveToJson(Json::Value& a_Value)
+void cBeaconEntity::UsedBy(cPlayer * a_Player)
{
+ cWindow * Window = GetWindow();
+ if (Window == NULL)
+ {
+ OpenWindow(new cBeaconWindow(m_PosX, m_PosY, m_PosZ, this));
+ Window = GetWindow();
+ }
+
+ if (Window != NULL)
+ {
+ // if (a_Player->GetWindow() != Window)
+ // -> Because mojang doesn't send a 'close window' packet when you click the cancel button in the beacon inventory ...
+ {
+ a_Player->OpenWindow(Window);
+ }
+ }
}
-void cBeaconEntity::SendTo(cClientHandle & a_Client)
+
+bool cBeaconEntity::LoadFromJson(const Json::Value & a_Value)
+{
+ m_PosX = a_Value.get("x", 0).asInt();
+ m_PosY = a_Value.get("y", 0).asInt();
+ m_PosZ = a_Value.get("z", 0).asInt();
+
+ Json::Value AllSlots = a_Value.get("Slots", 0);
+ int SlotIdx = 0;
+ for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr)
+ {
+ cItem Item;
+ Item.FromJson(*itr);
+ SetSlot(SlotIdx, Item);
+ SlotIdx++;
+ }
+
+ m_BeaconLevel = (char)a_Value.get("Level", 0).asInt();
+ int PrimaryEffect = a_Value.get("PrimaryEffect", 0).asInt();
+ int SecondaryEffect = a_Value.get("SecondaryEffect", 0).asInt();
+
+ if ((PrimaryEffect >= 0) && (PrimaryEffect <= (int)cEntityEffect::effSaturation))
+ {
+ m_PrimaryEffect = (cEntityEffect::eType)PrimaryEffect;
+ }
+
+ if ((SecondaryEffect >= 0) && (SecondaryEffect <= (int)cEntityEffect::effSaturation))
+ {
+ m_SecondaryEffect = (cEntityEffect::eType)SecondaryEffect;
+ }
+
+ return true;
+}
+
+
+
+
+
+void cBeaconEntity::SaveToJson(Json::Value& a_Value)
{
+ a_Value["x"] = m_PosX;
+ a_Value["y"] = m_PosY;
+ a_Value["z"] = m_PosZ;
+
+ Json::Value AllSlots;
+ int NumSlots = m_Contents.GetNumSlots();
+ for (int i = 0; i < NumSlots; i++)
+ {
+ Json::Value Slot;
+ m_Contents.GetSlot(i).GetJson(Slot);
+ AllSlots.append(Slot);
+ }
+ a_Value["Slots"] = AllSlots;
+
+ a_Value["Level"] = m_BeaconLevel;
+ a_Value["PrimaryEffect"] = (int)m_PrimaryEffect;
+ a_Value["SecondaryEffect"] = (int)m_SecondaryEffect;
}
-void cBeaconEntity::UsedBy(cPlayer * a_Player)
+void cBeaconEntity::SendTo(cClientHandle & a_Client)
{
+ a_Client.SendUpdateBlockEntity(*this);
}
diff --git a/src/BlockEntities/BeaconEntity.h b/src/BlockEntities/BeaconEntity.h
index b1df68bc4..0d7150aef 100644
--- a/src/BlockEntities/BeaconEntity.h
+++ b/src/BlockEntities/BeaconEntity.h
@@ -1,7 +1,14 @@
+// BeaconEntity.h
+
+// Declares the cBeaconEntity class representing a single beacon in the world
+
+
+
+
#pragma once
-#include "BlockEntity.h"
+#include "BlockEntityWithItems.h"
@@ -16,28 +23,70 @@ namespace Json
+// tolua_begin
class cBeaconEntity :
- public cBlockEntity
+ public cBlockEntityWithItems
{
- typedef cBlockEntity super;
+ typedef cBlockEntityWithItems super;
public:
-
- /** The initial constructor */
+ // tolua_end
+
cBeaconEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
-
- /** Returns the amount of layers the pyramid below the beacon has. */
- int GetPyramidLevel(void);
+
+ bool LoadFromJson(const Json::Value & a_Value);
+ // cBlockEntity overrides:
+ virtual void SaveToJson(Json::Value& a_Value) override;
+ virtual void SendTo(cClientHandle & a_Client) override;
+ virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void UsedBy(cPlayer * a_Player) override;
+
+ /** Modify the beacon level. (It is needed to load the beacon corectly) */
+ void SetBeaconLevel(char a_Level) { m_BeaconLevel = a_Level; }
+
+ // tolua_begin
+
+ /** Is the beacon active? */
+ bool IsActive(void) const { return m_IsActive; }
+
+ /** Returns the beacon level. (0 - 4) */
+ char GetBeaconLevel(void) const { return m_BeaconLevel; }
+
+ cEntityEffect::eType GetPrimaryEffect(void) const { return m_PrimaryEffect; }
+ cEntityEffect::eType GetSecondaryEffect(void) const { return m_SecondaryEffect; }
+
+ /** Sets the primary effect. Returns false when the effect is invalid. */
+ bool SetPrimaryEffect(cEntityEffect::eType a_Effect);
+
+ /** Sets the secondary effect. Returns false when the effect is invalid. */
+ bool SetSecondaryEffect(cEntityEffect::eType a_Effect);
+
+ /** Calculate the amount of layers the pyramid below the beacon has. */
+ char CalculatePyramidLevel(void);
+
+ /** Is the beacon blocked by non-transparent blocks that are higher than the beacon? */
+ bool IsBeaconBlocked(void);
+
+ /** Update the beacon. */
+ void UpdateBeacon(void);
+
+ /** Give the near-players the effects. */
+ void GiveEffects(void);
/** Returns true if the block is a diamond block, a golden block, an iron block or an emerald block. */
static bool IsMineralBlock(BLOCKTYPE a_BlockType);
-
- // cBlockEntity overrides:
- virtual void SaveToJson(Json::Value& a_Value ) override;
- virtual void SendTo(cClientHandle & a_Client) override;
- virtual void UsedBy(cPlayer * a_Player) override;
- virtual bool Tick(float a_Dt, cChunk & /* a_Chunk */) override;
-} ;
+
+ /** Returns true if the effect can be used. */
+ static bool IsValidEffect(cEntityEffect::eType a_Effect, char a_BeaconLevel);
+
+ // tolua_end
+
+protected:
+ bool m_IsActive;
+ char m_BeaconLevel;
+
+ cEntityEffect::eType m_PrimaryEffect, m_SecondaryEffect;
+} ; // tolua_export
diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp
index 430f04551..05ad03a3d 100644
--- a/src/BlockEntities/BlockEntity.cpp
+++ b/src/BlockEntities/BlockEntity.cpp
@@ -28,24 +28,26 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
switch (a_BlockType)
{
case E_BLOCK_BEACON: return new cBeaconEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
- case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World, a_BlockType);
case E_BLOCK_COMMAND_BLOCK: return new cCommandBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
- case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
- case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
+ case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_TRAPPED_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World, a_BlockType);
case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_NOTE_BLOCK: return new cNoteEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
- case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
}
LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)",
__FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str()
);
+ ASSERT(!"Requesting creation of an unknown block entity");
return NULL;
}
diff --git a/src/BlockEntities/BlockEntity.h b/src/BlockEntities/BlockEntity.h
index 7c6688f8d..5710f8543 100644
--- a/src/BlockEntities/BlockEntity.h
+++ b/src/BlockEntities/BlockEntity.h
@@ -38,9 +38,9 @@ protected:
public:
// tolua_end
- virtual ~cBlockEntity() {}; // force a virtual destructor in all descendants
+ virtual ~cBlockEntity() {} // force a virtual destructor in all descendants
- virtual void Destroy(void) {};
+ virtual void Destroy(void) {}
void SetWorld(cWorld * a_World)
{
@@ -79,7 +79,7 @@ public:
virtual void SaveToJson (Json::Value & a_Value) = 0;
/// Called when a player uses this entity; should open the UI window
- virtual void UsedBy( cPlayer * a_Player ) = 0;
+ virtual void UsedBy( cPlayer * a_Player) = 0;
/** Sends the packet defining the block entity to the client specified.
To send to all eligible clients, use cWorld::BroadcastBlockEntity()
diff --git a/src/BlockEntities/BlockEntityWithItems.h b/src/BlockEntities/BlockEntityWithItems.h
index 918781a00..5f1639d45 100644
--- a/src/BlockEntities/BlockEntityWithItems.h
+++ b/src/BlockEntities/BlockEntityWithItems.h
@@ -50,7 +50,7 @@ public:
cItems Pickups;
m_Contents.CopyToItems(Pickups);
m_Contents.Clear();
- m_World->SpawnItemPickups(Pickups, m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5); // Spawn in centre of block
+ m_World->SpawnItemPickups(Pickups, m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5); // Spawn in centre of block
}
// tolua_begin
diff --git a/src/BlockEntities/CMakeLists.txt b/src/BlockEntities/CMakeLists.txt
index 3e3d17f86..d87594b0d 100644
--- a/src/BlockEntities/CMakeLists.txt
+++ b/src/BlockEntities/CMakeLists.txt
@@ -4,9 +4,41 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ BeaconEntity.cpp
+ BlockEntity.cpp
+ ChestEntity.cpp
+ CommandBlockEntity.cpp
+ DispenserEntity.cpp
+ DropSpenserEntity.cpp
+ DropperEntity.cpp
+ EnderChestEntity.cpp
+ FlowerPotEntity.cpp
+ FurnaceEntity.cpp
+ HopperEntity.cpp
+ JukeboxEntity.cpp
+ MobHeadEntity.cpp
+ NoteEntity.cpp
+ SignEntity.cpp)
-add_library(BlockEntities ${SOURCE})
+SET (HDRS
+ BeaconEntity.h
+ BlockEntity.h
+ BlockEntityWithItems.h
+ ChestEntity.h
+ CommandBlockEntity.h
+ DispenserEntity.h
+ DropSpenserEntity.h
+ DropperEntity.h
+ EnderChestEntity.h
+ FlowerPotEntity.h
+ FurnaceEntity.h
+ HopperEntity.h
+ JukeboxEntity.h
+ MobHeadEntity.h
+ NoteEntity.h
+ SignEntity.h)
+
+if(NOT MSVC)
+ add_library(BlockEntities ${SRCS} ${HDRS})
+endif()
diff --git a/src/BlockEntities/ChestEntity.cpp b/src/BlockEntities/ChestEntity.cpp
index cb9cc89bf..21e1f6ba2 100644
--- a/src/BlockEntities/ChestEntity.cpp
+++ b/src/BlockEntities/ChestEntity.cpp
@@ -11,8 +11,9 @@
-cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
- super(E_BLOCK_CHEST, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World)
+cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, BLOCKTYPE a_Type) :
+ super(a_Type, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
+ m_NumActivePlayers(0)
{
cBlockEntityWindowOwner::SetBlockEntity(this);
}
@@ -113,7 +114,7 @@ void cChestEntity::UsedBy(cPlayer * a_Player)
// The few false positives aren't much to worry about
int ChunkX, ChunkZ;
cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ);
- m_World->MarkChunkDirty(ChunkX, ChunkZ);
+ m_World->MarkChunkDirty(ChunkX, ChunkZ, true);
}
@@ -168,15 +169,15 @@ void cChestEntity::OpenNewWindow(void)
if (
m_World->DoWithChestAt(m_PosX - 1, m_PosY, m_PosZ, OpenDbl) ||
m_World->DoWithChestAt(m_PosX + 1, m_PosY, m_PosZ, OpenDbl) ||
- m_World->DoWithChestAt(m_PosX , m_PosY, m_PosZ - 1, OpenDbl) ||
- m_World->DoWithChestAt(m_PosX , m_PosY, m_PosZ + 1, OpenDbl)
+ m_World->DoWithChestAt(m_PosX, m_PosY, m_PosZ - 1, OpenDbl) ||
+ m_World->DoWithChestAt(m_PosX, m_PosY, m_PosZ + 1, OpenDbl)
)
{
// The double-chest window has been opened in the callback
return;
}
- // There is no chest neighbor, open a single-chest window:
+ // There is no chest neighbor, open a single-chest window:
OpenWindow(new cChestWindow(this));
}
diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h
index ce16f84d7..cd06b3e2c 100644
--- a/src/BlockEntities/ChestEntity.h
+++ b/src/BlockEntities/ChestEntity.h
@@ -27,15 +27,16 @@ class cChestEntity :
typedef cBlockEntityWithItems super;
public:
- enum {
+ enum
+ {
ContentsHeight = 3,
ContentsWidth = 9,
} ;
// tolua_end
- /// Constructor used for normal operation
- cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
+ /** Constructor used for normal operation */
+ cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, BLOCKTYPE a_Type);
virtual ~cChestEntity();
@@ -48,8 +49,20 @@ public:
virtual void SendTo(cClientHandle & a_Client) override;
virtual void UsedBy(cPlayer * a_Player) override;
- /// Opens a new chest window for this chest. Scans for neighbors to open a double chest window, if appropriate.
+ /** Opens a new chest window for this chest.
+ Scans for neighbors to open a double chest window, if appropriate. */
void OpenNewWindow(void);
+
+ /** Gets the number of players who currently have this chest open */
+ int GetNumberOfPlayers(void) const { return m_NumActivePlayers; }
+
+ /** Sets the number of players who currently have this chest open */
+ void SetNumberOfPlayers(int a_NumActivePlayers) { m_NumActivePlayers = a_NumActivePlayers; }
+
+private:
+
+ /** Number of players who currently have this chest open */
+ int m_NumActivePlayers;
} ; // tolua_export
diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp
index 146ad915b..45f8a3e4d 100644
--- a/src/BlockEntities/CommandBlockEntity.cpp
+++ b/src/BlockEntities/CommandBlockEntity.cpp
@@ -11,7 +11,7 @@
#include "../CommandOutput.h"
#include "../Root.h"
-#include "../Server.h" // ExecuteConsoleCommand()
+#include "../Server.h" // ExecuteConsoleCommand()
#include "../Chunk.h"
diff --git a/src/BlockEntities/CommandBlockEntity.h b/src/BlockEntities/CommandBlockEntity.h
index 12157670f..d02bf7d7b 100644
--- a/src/BlockEntities/CommandBlockEntity.h
+++ b/src/BlockEntities/CommandBlockEntity.h
@@ -26,7 +26,7 @@ namespace Json
// tolua_begin
-class cCommandBlockEntity :
+class cCommandBlockEntity :
public cBlockEntity
{
typedef cBlockEntity super;
@@ -38,8 +38,8 @@ public:
/// Creates a new empty command block entity
cCommandBlockEntity(int a_X, int a_Y, int a_Z, cWorld * a_World);
- bool LoadFromJson( const Json::Value& a_Value );
- virtual void SaveToJson(Json::Value& a_Value ) override;
+ bool LoadFromJson( const Json::Value& a_Value);
+ virtual void SaveToJson(Json::Value& a_Value) override;
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void SendTo(cClientHandle & a_Client) override;
diff --git a/src/BlockEntities/DropSpenserEntity.cpp b/src/BlockEntities/DropSpenserEntity.cpp
index 0012742fb..dc38e3e9b 100644
--- a/src/BlockEntities/DropSpenserEntity.cpp
+++ b/src/BlockEntities/DropSpenserEntity.cpp
@@ -42,7 +42,7 @@ cDropSpenserEntity::~cDropSpenserEntity()
void cDropSpenserEntity::AddDropSpenserDir(int & a_BlockX, int & a_BlockY, int & a_BlockZ, NIBBLETYPE a_Direction)
{
- switch (a_Direction)
+ switch (a_Direction & 0x07) // Vanilla uses the 8th bit to determine power state - we don't
{
case E_META_DROPSPENSER_FACING_YM: a_BlockY--; return;
case E_META_DROPSPENSER_FACING_YP: a_BlockY++; return;
@@ -90,7 +90,7 @@ void cDropSpenserEntity::DropSpense(cChunk & a_Chunk)
int SmokeDir = 0;
switch (Meta)
{
- case E_META_DROPSPENSER_FACING_YP: SmokeDir = 4; break; // YP & YM don't have associated smoke dirs, just do 4 (centre of block)
+ case E_META_DROPSPENSER_FACING_YP: SmokeDir = 4; break; // YP & YM don't have associated smoke dirs, just do 4 (centre of block)
case E_META_DROPSPENSER_FACING_YM: SmokeDir = 4; break;
case E_META_DROPSPENSER_FACING_XM: SmokeDir = 3; break;
case E_META_DROPSPENSER_FACING_XP: SmokeDir = 5; break;
@@ -99,7 +99,7 @@ void cDropSpenserEntity::DropSpense(cChunk & a_Chunk)
}
m_World->BroadcastSoundParticleEffect(2000, m_PosX, m_PosY, m_PosZ, SmokeDir);
m_World->BroadcastSoundEffect("random.click", m_PosX * 8, m_PosY * 8, m_PosZ * 8, 1.0f, 1.0f);
-}
+}
@@ -235,7 +235,7 @@ void cDropSpenserEntity::DropFromSlot(cChunk & a_Chunk, int a_SlotNum)
cItems Pickups;
Pickups.push_back(m_Contents.RemoveOneItem(a_SlotNum));
- const int PickupSpeed = m_World->GetTickRandomNumber(4) + 2; // At least 2, at most 6
+ const int PickupSpeed = m_World->GetTickRandomNumber(4) + 2; // At least 2, at most 6
int PickupSpeedX = 0, PickupSpeedY = 0, PickupSpeedZ = 0;
switch (Meta)
{
@@ -249,7 +249,7 @@ void cDropSpenserEntity::DropFromSlot(cChunk & a_Chunk, int a_SlotNum)
double MicroX, MicroY, MicroZ;
MicroX = DispX + 0.5;
- MicroY = DispY + 0.4; // Slightly less than half, to accomodate actual texture hole on DropSpenser
+ MicroY = DispY + 0.4; // Slightly less than half, to accomodate actual texture hole on DropSpenser
MicroZ = DispZ + 0.5;
diff --git a/src/BlockEntities/DropSpenserEntity.h b/src/BlockEntities/DropSpenserEntity.h
index 47d3bd492..be56447aa 100644
--- a/src/BlockEntities/DropSpenserEntity.h
+++ b/src/BlockEntities/DropSpenserEntity.h
@@ -11,7 +11,7 @@
#pragma once
#include "BlockEntityWithItems.h"
-
+#include "RedstonePoweredEntity.h"
@@ -31,11 +31,15 @@ class cServer;
// tolua_begin
class cDropSpenserEntity :
public cBlockEntityWithItems
+ // tolua_end
+ , public cRedstonePoweredEntity
+ // tolua_begin
{
typedef cBlockEntityWithItems super;
public:
- enum {
+ enum
+ {
ContentsHeight = 3,
ContentsWidth = 3,
} ;
@@ -63,10 +67,10 @@ public:
/// Sets the dropspenser to dropspense an item in the next tick
void Activate(void);
- /// Sets the internal redstone power flag to "on" or "off", depending on the parameter. Calls Activate() if appropriate
- void SetRedstonePower(bool a_IsPowered);
-
// tolua_end
+
+ /// Sets the internal redstone power flag to "on" or "off", depending on the parameter. Calls Activate() if appropriate
+ virtual void SetRedstonePower(bool a_IsPowered) override;
protected:
bool m_ShouldDropSpense; ///< If true, the dropspenser will dropspense an item in the next tick
diff --git a/src/BlockEntities/EnderChestEntity.h b/src/BlockEntities/EnderChestEntity.h
index 04af67683..ed178f6fc 100644
--- a/src/BlockEntities/EnderChestEntity.h
+++ b/src/BlockEntities/EnderChestEntity.h
@@ -16,10 +16,10 @@ class cEnderChestEntity :
{
typedef cBlockEntity super;
-public:
+public:
// tolua_end
- cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
+ cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
virtual ~cEnderChestEntity();
static const char * GetClassStatic(void) { return "cEnderChestEntity"; }
diff --git a/src/BlockEntities/FlowerPotEntity.cpp b/src/BlockEntities/FlowerPotEntity.cpp
index 87bf8b921..e001634b8 100644
--- a/src/BlockEntities/FlowerPotEntity.cpp
+++ b/src/BlockEntities/FlowerPotEntity.cpp
@@ -1,7 +1,7 @@
// FlowerPotEntity.cpp
-// Implements the cFlowerPotEntity class representing a single sign in the world
+// Implements the cFlowerPotEntity class representing a single flower pot in the world
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "json/json.h"
diff --git a/src/BlockEntities/FlowerPotEntity.h b/src/BlockEntities/FlowerPotEntity.h
index da3fe9b7e..89901cf2d 100644
--- a/src/BlockEntities/FlowerPotEntity.h
+++ b/src/BlockEntities/FlowerPotEntity.h
@@ -27,7 +27,7 @@ namespace Json
// tolua_begin
-class cFlowerPotEntity :
+class cFlowerPotEntity :
public cBlockEntity
{
typedef cBlockEntity super;
@@ -39,8 +39,8 @@ public:
/** Creates a new flowerpot entity at the specified block coords. a_World may be NULL */
cFlowerPotEntity(int a_BlocX, int a_BlockY, int a_BlockZ, cWorld * a_World);
- bool LoadFromJson( const Json::Value& a_Value );
- virtual void SaveToJson(Json::Value& a_Value ) override;
+ bool LoadFromJson( const Json::Value& a_Value);
+ virtual void SaveToJson(Json::Value& a_Value) override;
virtual void Destroy(void) override;
@@ -53,7 +53,7 @@ public:
cItem GetItem(void) const { return m_Item; }
/** Set the item in the flower pot */
- void SetItem(const cItem a_Item) { m_Item = a_Item; }
+ void SetItem(const cItem & a_Item) { m_Item = a_Item; }
// tolua_end
diff --git a/src/BlockEntities/FurnaceEntity.cpp b/src/BlockEntities/FurnaceEntity.cpp
index 1b1741713..72fd7f2b3 100644
--- a/src/BlockEntities/FurnaceEntity.cpp
+++ b/src/BlockEntities/FurnaceEntity.cpp
@@ -160,7 +160,7 @@ bool cFurnaceEntity::LoadFromJson(const Json::Value & a_Value)
-void cFurnaceEntity::SaveToJson( Json::Value& a_Value )
+void cFurnaceEntity::SaveToJson( Json::Value& a_Value)
{
a_Value["x"] = m_PosX;
a_Value["y"] = m_PosY;
diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp
index 5856f20d1..88e7b8e1b 100644
--- a/src/BlockEntities/HopperEntity.cpp
+++ b/src/BlockEntities/HopperEntity.cpp
@@ -157,6 +157,7 @@ bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
bool res = false;
switch (a_Chunk.GetBlock(m_RelX, m_PosY + 1, m_RelZ))
{
+ case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_CHEST:
{
// Chests have special handling because of double-chests
@@ -218,7 +219,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
}
Vector3f EntityPos = a_Entity->GetPosition();
- Vector3f BlockPos(m_Pos.x + 0.5f, (float)m_Pos.y + 1, m_Pos.z + 0.5f); // One block above hopper, and search from center outwards
+ Vector3f BlockPos(m_Pos.x + 0.5f, (float)m_Pos.y + 1, m_Pos.z + 0.5f); // One block above hopper, and search from center outwards
double Distance = (EntityPos - BlockPos).Length();
if (Distance < 0.5)
@@ -242,7 +243,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
{
m_bFoundPickupsAbove = true;
m_Contents.SetSlot(i, Item);
- a_Pickup->Destroy(); // Kill pickup
+ a_Pickup->Destroy(); // Kill pickup
return true;
}
@@ -252,11 +253,11 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
int PreviousCount = m_Contents.GetSlot(i).m_ItemCount;
- Item.m_ItemCount -= m_Contents.ChangeSlotCount(i, Item.m_ItemCount) - PreviousCount; // Set count to however many items were added
+ Item.m_ItemCount -= m_Contents.ChangeSlotCount(i, Item.m_ItemCount) - PreviousCount; // Set count to however many items were added
if (Item.IsEmpty())
{
- a_Pickup->Destroy(); // Kill pickup if all items were added
+ a_Pickup->Destroy(); // Kill pickup if all items were added
}
return true;
}
@@ -322,6 +323,7 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
bool res = false;
switch (DestChunk->GetBlock(OutRelX, OutY, OutRelZ))
{
+ case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_CHEST:
{
// Chests have special handling because of double-chests
@@ -366,19 +368,19 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
/// Moves items from a chest (dblchest) above the hopper into this hopper. Returns true if contents have changed.
bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
{
- cChestEntity * Chest = (cChestEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ);
- if (Chest == NULL)
+ cChestEntity * MainChest = (cChestEntity *)a_Chunk.GetBlockEntity(m_PosX, m_PosY + 1, m_PosZ);
+ if (MainChest == NULL)
{
LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX, m_PosY + 1, m_PosZ);
return false;
}
- if (MoveItemsFromGrid(*Chest))
+ if (MoveItemsFromGrid(*MainChest))
{
// Moved the item from the chest directly above the hopper
return true;
}
- // Check if the chest is a double-chest, if so, try to move from there:
+ // Check if the chest is a double-chest (chest directly above was empty), if so, try to move from there:
static const struct
{
int x, z;
@@ -395,21 +397,26 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
int x = m_RelX + Coords[i].x;
int z = m_RelZ + Coords[i].z;
cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z);
- if (
- (Neighbor == NULL) ||
- (Neighbor->GetBlock(x, m_PosY + 1, z) != E_BLOCK_CHEST)
- )
+ if (Neighbor == NULL)
{
continue;
}
- Chest = (cChestEntity *)Neighbor->GetBlockEntity(m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z);
- if (Chest == NULL)
+
+ BLOCKTYPE Block = Neighbor->GetBlock(x, m_PosY + 1, z);
+ if (Block != MainChest->GetBlockType())
+ {
+ // Not the same kind of chest
+ continue;
+ }
+
+ cChestEntity * SideChest = (cChestEntity *)Neighbor->GetBlockEntity(m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z);
+ if (SideChest == NULL)
{
LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z);
}
else
{
- if (MoveItemsFromGrid(*Chest))
+ if (MoveItemsFromGrid(*SideChest))
{
return true;
}
@@ -542,18 +549,19 @@ bool cHopperEntity::MoveItemsFromSlot(cBlockEntityWithItems & a_Entity, int a_Sl
bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Try the chest directly connected to the hopper:
- cChestEntity * Chest = (cChestEntity *)a_Chunk.GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ);
- if (Chest == NULL)
+ cChestEntity * ConnectedChest = (cChestEntity *)a_Chunk.GetBlockEntity(a_BlockX, a_BlockY, a_BlockZ);
+ if (ConnectedChest == NULL)
{
LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d}", __FUNCTION__, a_BlockX, a_BlockY, a_BlockZ);
return false;
}
- if (MoveItemsToGrid(*Chest))
+ if (MoveItemsToGrid(*ConnectedChest))
{
+ // Chest block directly connected was not full
return true;
}
- // Check if the chest is a double-chest, if so, try to move into the other half:
+ // Check if the chest is a double-chest (chest block directly connected was full), if so, try to move into the other half:
static const struct
{
int x, z;
@@ -572,14 +580,19 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block
int x = RelX + Coords[i].x;
int z = RelZ + Coords[i].z;
cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z);
- if (
- (Neighbor == NULL) ||
- (Neighbor->GetBlock(x, a_BlockY, z) != E_BLOCK_CHEST)
- )
+ if (Neighbor == NULL)
{
continue;
}
- Chest = (cChestEntity *)Neighbor->GetBlockEntity(a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z);
+
+ BLOCKTYPE Block = Neighbor->GetBlock(x, a_BlockY, z);
+ if (Block != ConnectedChest->GetBlockType())
+ {
+ // Not the same kind of chest
+ continue;
+ }
+
+ cChestEntity * Chest = (cChestEntity *)Neighbor->GetBlockEntity(a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z);
if (Chest == NULL)
{
LOGWARNING("%s: A chest entity was not found where expected, at {%d, %d, %d} (%d, %d)", __FUNCTION__, a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z, x, z);
diff --git a/src/BlockEntities/HopperEntity.h b/src/BlockEntities/HopperEntity.h
index 6ef98f43a..8e856fcda 100644
--- a/src/BlockEntities/HopperEntity.h
+++ b/src/BlockEntities/HopperEntity.h
@@ -22,7 +22,8 @@ class cHopperEntity :
typedef cBlockEntityWithItems super;
public:
- enum {
+ enum
+ {
ContentsHeight = 1,
ContentsWidth = 5,
TICKS_PER_TRANSFER = 8, ///< How many ticks at minimum between two item transfers to or from the hopper
diff --git a/src/BlockEntities/JukeboxEntity.h b/src/BlockEntities/JukeboxEntity.h
index 3d1d604f7..d677d340f 100644
--- a/src/BlockEntities/JukeboxEntity.h
+++ b/src/BlockEntities/JukeboxEntity.h
@@ -19,7 +19,7 @@ namespace Json
// tolua_begin
-class cJukeboxEntity :
+class cJukeboxEntity :
public cBlockEntity
{
typedef cBlockEntity super;
@@ -58,7 +58,7 @@ public:
static const char * GetClassStatic(void) { return "cJukeboxEntity"; }
virtual void UsedBy(cPlayer * a_Player) override;
- virtual void SendTo(cClientHandle &) override { };
+ virtual void SendTo(cClientHandle &) override {}
private:
int m_Record;
diff --git a/src/BlockEntities/MobHeadEntity.h b/src/BlockEntities/MobHeadEntity.h
index 367eb15e7..f91a3cc9e 100644
--- a/src/BlockEntities/MobHeadEntity.h
+++ b/src/BlockEntities/MobHeadEntity.h
@@ -25,7 +25,7 @@ namespace Json
// tolua_begin
-class cMobHeadEntity :
+class cMobHeadEntity :
public cBlockEntity
{
typedef cBlockEntity super;
@@ -37,8 +37,8 @@ public:
/** Creates a new mob head entity at the specified block coords. a_World may be NULL */
cMobHeadEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
- bool LoadFromJson( const Json::Value& a_Value );
- virtual void SaveToJson(Json::Value& a_Value ) override;
+ bool LoadFromJson( const Json::Value& a_Value);
+ virtual void SaveToJson(Json::Value& a_Value) override;
// tolua_begin
diff --git a/src/BlockEntities/NoteEntity.cpp b/src/BlockEntities/NoteEntity.cpp
index 58b05a324..95145c117 100644
--- a/src/BlockEntities/NoteEntity.cpp
+++ b/src/BlockEntities/NoteEntity.cpp
@@ -91,7 +91,7 @@ void cNoteEntity::MakeSound(void)
// TODO: instead of calculating the power function over and over, make a precalculated table - there's only 24 pitches after all
float calcPitch = pow(2.0f, ((float)m_Pitch - 12.0f) / 12.0f);
- m_World->BroadcastSoundEffect(sampleName, m_PosX * 8, m_PosY * 8, m_PosZ * 8, 3.0f, calcPitch);
+ m_World->BroadcastSoundEffect(sampleName, (double)m_PosX, (double)m_PosY, (double)m_PosZ, 3.0f, calcPitch);
}
diff --git a/src/BlockEntities/NoteEntity.h b/src/BlockEntities/NoteEntity.h
index b698899c0..f538de060 100644
--- a/src/BlockEntities/NoteEntity.h
+++ b/src/BlockEntities/NoteEntity.h
@@ -2,6 +2,7 @@
#pragma once
#include "BlockEntity.h"
+#include "RedstonePoweredEntity.h"
namespace Json
@@ -28,8 +29,11 @@ enum ENUM_NOTE_INSTRUMENTS
// tolua_begin
-class cNoteEntity :
+class cNoteEntity :
public cBlockEntity
+ // tolua_end
+ , public cRedstonePoweredEntity
+ // tolua_begin
{
typedef cBlockEntity super;
public:
@@ -38,6 +42,7 @@ public:
/// Creates a new note entity. a_World may be NULL
cNoteEntity(int a_X, int a_Y, int a_Z, cWorld * a_World);
+ virtual ~cNoteEntity() {}
bool LoadFromJson(const Json::Value & a_Value);
virtual void SaveToJson(Json::Value & a_Value) override;
@@ -52,7 +57,15 @@ public:
// tolua_end
virtual void UsedBy(cPlayer * a_Player) override;
- virtual void SendTo(cClientHandle &) override { };
+ virtual void SendTo(cClientHandle &) override {}
+
+ virtual void SetRedstonePower(bool a_Value)
+ {
+ if (a_Value)
+ {
+ MakeSound();
+ }
+ }
static const char * GetClassStatic(void) { return "cNoteEntity"; }
diff --git a/src/BlockEntities/RedstonePoweredEntity.h b/src/BlockEntities/RedstonePoweredEntity.h
new file mode 100644
index 000000000..f11df4fc4
--- /dev/null
+++ b/src/BlockEntities/RedstonePoweredEntity.h
@@ -0,0 +1,13 @@
+
+#pragma once
+
+// Interface class representing a blockEntity that responds to redstone
+class cRedstonePoweredEntity
+{
+public:
+
+ virtual ~cRedstonePoweredEntity() {};
+
+ /// Sets the internal redstone power flag to "on" or "off", depending on the parameter. Calls Activate() if appropriate
+ virtual void SetRedstonePower(bool a_IsPowered) = 0;
+};
diff --git a/src/BlockEntities/SignEntity.h b/src/BlockEntities/SignEntity.h
index 80c7bbfdf..33af100a4 100644
--- a/src/BlockEntities/SignEntity.h
+++ b/src/BlockEntities/SignEntity.h
@@ -25,7 +25,7 @@ namespace Json
// tolua_begin
-class cSignEntity :
+class cSignEntity :
public cBlockEntity
{
typedef cBlockEntity super;
@@ -37,8 +37,8 @@ public:
/// Creates a new empty sign entity at the specified block coords and block type (wall or standing). a_World may be NULL
cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorld * a_World);
- bool LoadFromJson( const Json::Value& a_Value );
- virtual void SaveToJson(Json::Value& a_Value ) override;
+ bool LoadFromJson( const Json::Value& a_Value);
+ virtual void SaveToJson(Json::Value& a_Value) override;
// tolua_begin
diff --git a/src/BlockID.cpp b/src/BlockID.cpp
index bfe826f40..07a1fc9e5 100644
--- a/src/BlockID.cpp
+++ b/src/BlockID.cpp
@@ -17,7 +17,7 @@ class cBlockIDMap
// Making the map case-insensitive:
struct Comparator
{
- bool operator()(const AString & a_Item1, const AString & a_Item2) const
+ bool operator ()(const AString & a_Item1, const AString & a_Item2) const
{
return (NoCaseCompare(a_Item1, a_Item2) > 0);
}
@@ -255,7 +255,8 @@ AString ItemToFullString(const cItem & a_Item)
int StringToMobType(const AString & a_MobString)
{
- static struct {
+ static struct
+ {
int m_MobType;
const char * m_String;
} MobMap [] =
@@ -286,7 +287,7 @@ int StringToMobType(const AString & a_MobString)
{cMonster::mtMooshroom, "Mooshroom"},
{cMonster::mtSnowGolem, "SnowGolem"},
{cMonster::mtOcelot, "Ocelot"},
- {cMonster::mtIronGolem, "IronGolem"},
+ {cMonster::mtIronGolem, "IronGolem"},
{cMonster::mtVillager, "Villager"},
};
for (size_t i = 0; i < ARRAYCOUNT(MobMap); i++)
@@ -345,6 +346,37 @@ eDimension StringToDimension(const AString & a_DimensionString)
+AString DimensionToString(eDimension a_Dimension)
+{
+ // Decode using a built-in map:
+ static struct
+ {
+ eDimension m_Dimension;
+ const char * m_String;
+ } DimensionMap[] =
+ {
+ { dimOverworld, "Overworld" },
+ { dimNether, "Nether" },
+ { dimEnd, "End" },
+ };
+
+ for (size_t i = 0; i < ARRAYCOUNT(DimensionMap); i++)
+ {
+ if (DimensionMap[i].m_Dimension == a_Dimension)
+ {
+ return DimensionMap[i].m_String;
+ }
+ } // for i - DimensionMap[]
+
+ // Not found
+ LOGWARNING("Unknown dimension: \"%i\". Setting to Overworld", (int)a_Dimension);
+ return "Overworld";
+}
+
+
+
+
+
/// Translates damage type constant to a string representation (built-in).
AString DamageTypeToString(eDamageType a_DamageType)
{
@@ -363,6 +395,7 @@ AString DamageTypeToString(eDamageType a_DamageType)
case dtLightning: return "dtLightning";
case dtOnFire: return "dtOnFire";
case dtPoisoning: return "dtPoisoning";
+ case dtWithering: return "dtWithering";
case dtPotionOfHarming: return "dtPotionOfHarming";
case dtRangedAttack: return "dtRangedAttack";
case dtStarving: return "dtStarving";
@@ -408,6 +441,7 @@ eDamageType StringToDamageType(const AString & a_DamageTypeString)
{ dtCactusContact, "dtCactusContact"},
{ dtLavaContact, "dtLavaContact"},
{ dtPoisoning, "dtPoisoning"},
+ { dtWithering, "dtWithering"},
{ dtOnFire, "dtOnFire"},
{ dtFireContact, "dtFireContact"},
{ dtInVoid, "dtInVoid"},
@@ -433,6 +467,7 @@ eDamageType StringToDamageType(const AString & a_DamageTypeString)
{ dtCactusContact, "dtCacti"},
{ dtLavaContact, "dtLava"},
{ dtPoisoning, "dtPoison"},
+ { dtWithering, "dtWither"},
{ dtOnFire, "dtBurning"},
{ dtFireContact, "dtInFire"},
{ dtAdmin, "dtPlugin"},
diff --git a/src/BlockID.h b/src/BlockID.h
index 272fd319d..08c576886 100644
--- a/src/BlockID.h
+++ b/src/BlockID.h
@@ -171,12 +171,12 @@ enum ENUM_BLOCK_ID
E_BLOCK_DROPPER = 158,
E_BLOCK_STAINED_CLAY = 159,
E_BLOCK_STAINED_GLASS_PANE = 160,
- E_BLOCK_NEW_LEAVES = 161, // Acacia and Dark Oak IDs in Minecraft 1.7.x
+ E_BLOCK_NEW_LEAVES = 161, // Acacia and Dark Oak IDs in Minecraft 1.7.x
E_BLOCK_NEW_LOG = 162,
E_BLOCK_ACACIA_WOOD_STAIRS = 163,
E_BLOCK_DARK_OAK_WOOD_STAIRS = 164,
E_BLOCK_HAY_BALE = 170,
- E_BLOCK_CARPET = 171,
+ E_BLOCK_CARPET = 171,
E_BLOCK_HARDENED_CLAY = 172,
E_BLOCK_BLOCK_OF_COAL = 173,
E_BLOCK_PACKED_ICE = 174,
@@ -187,7 +187,7 @@ enum ENUM_BLOCK_ID
E_BLOCK_NUMBER_OF_TYPES, ///< Number of individual (different) blocktypes
E_BLOCK_MAX_TYPE_ID = E_BLOCK_NUMBER_OF_TYPES - 1, ///< Maximum BlockType number used
- // Synonym or ID compatibility
+ // Synonym or ID compatibility
E_BLOCK_YELLOW_FLOWER = E_BLOCK_DANDELION,
E_BLOCK_RED_ROSE = E_BLOCK_FLOWER,
E_BLOCK_LOCKED_CHEST = E_BLOCK_STAINED_GLASS,
@@ -319,7 +319,8 @@ enum ENUM_ITEM_ID
E_ITEM_GHAST_TEAR = 370,
E_ITEM_GOLD_NUGGET = 371,
E_ITEM_NETHER_WART = 372,
- E_ITEM_POTIONS = 373,
+ E_ITEM_POTION = 373,
+ E_ITEM_POTIONS = 373, // OBSOLETE, use E_ITEM_POTION instead
E_ITEM_GLASS_BOTTLE = 374,
E_ITEM_SPIDER_EYE = 375,
E_ITEM_FERMENTED_SPIDER_EYE = 376,
@@ -398,7 +399,7 @@ enum
// Please keep this list alpha-sorted by the blocktype / itemtype part
// then number-sorted for the same block / item
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Block metas:
// E_BLOCK_BIG_FLOWER metas
@@ -677,7 +678,7 @@ enum
E_META_WOOL_RED = 14,
E_META_WOOL_BLACK = 15,
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Item metas:
// E_ITEM_COAL metas:
@@ -811,6 +812,7 @@ enum eDamageType
dtCactusContact, // Contact with a cactus block
dtLavaContact, // Contact with a lava block
dtPoisoning, // Having the poison effect
+ dtWithering, // Having the wither effect
dtOnFire, // Being on fire
dtFireContact, // Standing inside a fire block
dtInVoid, // Falling into the Void (Y < 0)
@@ -837,6 +839,7 @@ enum eDamageType
dtCacti = dtCactusContact,
dtLava = dtLavaContact,
dtPoison = dtPoisoning,
+ dtWither = dtWithering,
dtBurning = dtOnFire,
dtInFire = dtFireContact,
dtPlugin = dtAdmin,
@@ -917,9 +920,14 @@ extern AString ItemToFullString(const cItem & a_Item);
/// Translates a mob string ("ocelot") to mobtype (E_ENTITY_TYPE_OCELOT)
extern int StringToMobType(const AString & a_MobString);
-/// Translates a dimension string to dimension enum. Takes either a number or a dimension alias (built-in). Returns -1000 on failure
+/// Translates a dimension string to dimension enum. Takes either a number or a dimension alias (built-in). Returns dimOverworld on failure
extern eDimension StringToDimension(const AString & a_DimensionString);
+/** Translates a dimension enum to dimension string.
+Takes an eDimension enum value and returns "Overworld" on failure
+*/
+extern AString DimensionToString(eDimension a_Dimension);
+
/// Translates damage type constant to a string representation (built-in).
extern AString DamageTypeToString(eDamageType a_DamageType);
diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp
index 9a953e396..a59229f87 100644
--- a/src/BlockInfo.cpp
+++ b/src/BlockInfo.cpp
@@ -14,10 +14,10 @@ cBlockInfo::cBlockInfo()
, m_Transparent(false)
, m_OneHitDig(false)
, m_PistonBreakable(false)
- , m_IsSnowable(true)
- , m_RequiresSpecialTool(false)
+ , m_IsSnowable(false)
, m_IsSolid(true)
, m_FullyOccupiesVoxel(false)
+ , m_CanBeTerraformed(false)
, m_Handler(NULL)
{}
@@ -65,47 +65,117 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
}
// Emissive blocks
+ a_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_LightValue = 9;
+ a_Info[E_BLOCK_BEACON ].m_LightValue = 15;
+ a_Info[E_BLOCK_BREWING_STAND ].m_LightValue = 1;
+ a_Info[E_BLOCK_BROWN_MUSHROOM ].m_LightValue = 1;
+ a_Info[E_BLOCK_BURNING_FURNACE ].m_LightValue = 13;
+ a_Info[E_BLOCK_DRAGON_EGG ].m_LightValue = 1;
+ a_Info[E_BLOCK_END_PORTAL ].m_LightValue = 15;
+ a_Info[E_BLOCK_END_PORTAL_FRAME ].m_LightValue = 1;
+ a_Info[E_BLOCK_ENDER_CHEST ].m_LightValue = 7;
a_Info[E_BLOCK_FIRE ].m_LightValue = 15;
a_Info[E_BLOCK_GLOWSTONE ].m_LightValue = 15;
a_Info[E_BLOCK_JACK_O_LANTERN ].m_LightValue = 15;
a_Info[E_BLOCK_LAVA ].m_LightValue = 15;
- a_Info[E_BLOCK_STATIONARY_LAVA ].m_LightValue = 15;
- a_Info[E_BLOCK_END_PORTAL ].m_LightValue = 15;
- a_Info[E_BLOCK_REDSTONE_LAMP_ON ].m_LightValue = 15;
- a_Info[E_BLOCK_TORCH ].m_LightValue = 14;
- a_Info[E_BLOCK_BURNING_FURNACE ].m_LightValue = 13;
a_Info[E_BLOCK_NETHER_PORTAL ].m_LightValue = 11;
+ a_Info[E_BLOCK_REDSTONE_LAMP_ON ].m_LightValue = 15;
a_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_LightValue = 9;
a_Info[E_BLOCK_REDSTONE_REPEATER_ON].m_LightValue = 9;
a_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_LightValue = 7;
- a_Info[E_BLOCK_BREWING_STAND ].m_LightValue = 1;
- a_Info[E_BLOCK_BROWN_MUSHROOM ].m_LightValue = 1;
- a_Info[E_BLOCK_DRAGON_EGG ].m_LightValue = 1;
+ a_Info[E_BLOCK_STATIONARY_LAVA ].m_LightValue = 15;
+ a_Info[E_BLOCK_TORCH ].m_LightValue = 14;
// Spread blocks
+ a_Info[E_BLOCK_ACTIVATOR_RAIL ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_AIR ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_ANVIL ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_BEACON ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_BED ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_BIG_FLOWER ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_BROWN_MUSHROOM ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_BREWING_STAND ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_CACTUS ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_CAKE ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_CARPET ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_CARROTS ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_CAULDRON ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_CHEST ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_COBBLESTONE_WALL ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_COCOA_POD ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_COBWEB ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_CROPS ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_DANDELION ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_DAYLIGHT_SENSOR ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_DEAD_BUSH ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_DETECTOR_RAIL ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_DRAGON_EGG ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_ENCHANTMENT_TABLE ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_ENDER_CHEST ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_END_PORTAL ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_END_PORTAL_FRAME ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_FARMLAND ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_FENCE ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_FENCE_GATE ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_FIRE ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_FLOWER ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_FLOWER_POT ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_GLASS ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_GLASS_PANE ].m_SpreadLightFalloff = 1;
- a_Info[E_BLOCK_GLOWSTONE ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_HEAD ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_HOPPER ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_ICE ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_IRON_BARS ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_IRON_DOOR ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_LADDER ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_LEAVES ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_LEVER ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_LILY_PAD ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_MELON_STEM ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_MOB_SPAWNER ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_NETHER_PORTAL ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_NETHER_WART ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_NEW_LEAVES ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_PISTON ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_PISTON_EXTENSION ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_PISTON_MOVED_BLOCK ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_POTATOES ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_POWERED_RAIL ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_PUMPKIN_STEM ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_RAIL ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_RED_MUSHROOM ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_REDSTONE_REPEATER_OFF].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_REDSTONE_REPEATER_ON].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_REDSTONE_TORCH_OFF ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_REDSTONE_WIRE ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_SAPLING ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_SIGN_POST ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_SNOW ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_STAINED_GLASS ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_STAINED_GLASS_PANE ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_STICKY_PISTON ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_STONE_BUTTON ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_STONE_SLAB ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_SUGARCANE ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_TALL_GRASS ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_TORCH ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_TRAPDOOR ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_TRAPPED_CHEST ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_TRIPWIRE ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_VINES ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_WALLSIGN ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_WOODEN_BUTTON ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_WOODEN_DOOR ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_WOODEN_PRESSURE_PLATE].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_WOODEN_SLAB ].m_SpreadLightFalloff = 1;
// Light in water and lava dissapears faster:
a_Info[E_BLOCK_LAVA ].m_SpreadLightFalloff = 3;
@@ -116,19 +186,34 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
// Transparent blocks
a_Info[E_BLOCK_ACTIVATOR_RAIL ].m_Transparent = true;
+ a_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_Transparent = true;
a_Info[E_BLOCK_AIR ].m_Transparent = true;
a_Info[E_BLOCK_ANVIL ].m_Transparent = true;
+ a_Info[E_BLOCK_BEACON ].m_Transparent = true;
+ a_Info[E_BLOCK_BED ].m_Transparent = true;
a_Info[E_BLOCK_BIG_FLOWER ].m_Transparent = true;
a_Info[E_BLOCK_BROWN_MUSHROOM ].m_Transparent = true;
+ a_Info[E_BLOCK_BREWING_STAND ].m_Transparent = true;
+ a_Info[E_BLOCK_CACTUS ].m_Transparent = true;
a_Info[E_BLOCK_CAKE ].m_Transparent = true;
+ a_Info[E_BLOCK_CARPET ].m_Transparent = true;
a_Info[E_BLOCK_CARROTS ].m_Transparent = true;
+ a_Info[E_BLOCK_CAULDRON ].m_Transparent = true;
a_Info[E_BLOCK_CHEST ].m_Transparent = true;
a_Info[E_BLOCK_COBBLESTONE_WALL ].m_Transparent = true;
+ a_Info[E_BLOCK_COCOA_POD ].m_Transparent = true;
a_Info[E_BLOCK_COBWEB ].m_Transparent = true;
a_Info[E_BLOCK_CROPS ].m_Transparent = true;
a_Info[E_BLOCK_DANDELION ].m_Transparent = true;
+ a_Info[E_BLOCK_DAYLIGHT_SENSOR ].m_Transparent = true;
+ a_Info[E_BLOCK_DEAD_BUSH ].m_Transparent = true;
a_Info[E_BLOCK_DETECTOR_RAIL ].m_Transparent = true;
+ a_Info[E_BLOCK_DRAGON_EGG ].m_Transparent = true;
+ a_Info[E_BLOCK_ENCHANTMENT_TABLE ].m_Transparent = true;
a_Info[E_BLOCK_ENDER_CHEST ].m_Transparent = true;
+ a_Info[E_BLOCK_END_PORTAL ].m_Transparent = true;
+ a_Info[E_BLOCK_END_PORTAL_FRAME ].m_Transparent = true;
+ a_Info[E_BLOCK_FARMLAND ].m_Transparent = true;
a_Info[E_BLOCK_FENCE ].m_Transparent = true;
a_Info[E_BLOCK_FENCE_GATE ].m_Transparent = true;
a_Info[E_BLOCK_FIRE ].m_Transparent = true;
@@ -138,42 +223,61 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_GLASS_PANE ].m_Transparent = true;
a_Info[E_BLOCK_HEAD ].m_Transparent = true;
a_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_Transparent = true;
+ a_Info[E_BLOCK_HOPPER ].m_Transparent = true;
a_Info[E_BLOCK_ICE ].m_Transparent = true;
+ a_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_Transparent = true;
+ a_Info[E_BLOCK_IRON_BARS ].m_Transparent = true;
a_Info[E_BLOCK_IRON_DOOR ].m_Transparent = true;
a_Info[E_BLOCK_LADDER ].m_Transparent = true;
a_Info[E_BLOCK_LAVA ].m_Transparent = true;
a_Info[E_BLOCK_LEAVES ].m_Transparent = true;
a_Info[E_BLOCK_LEVER ].m_Transparent = true;
+ a_Info[E_BLOCK_LILY_PAD ].m_Transparent = true;
a_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_Transparent = true;
a_Info[E_BLOCK_MELON_STEM ].m_Transparent = true;
+ a_Info[E_BLOCK_MOB_SPAWNER ].m_Transparent = true;
a_Info[E_BLOCK_NETHER_BRICK_FENCE ].m_Transparent = true;
+ a_Info[E_BLOCK_NETHER_PORTAL ].m_Transparent = true;
+ a_Info[E_BLOCK_NETHER_WART ].m_Transparent = true;
a_Info[E_BLOCK_NEW_LEAVES ].m_Transparent = true;
+ a_Info[E_BLOCK_PISTON ].m_Transparent = true;
+ a_Info[E_BLOCK_PISTON_EXTENSION ].m_Transparent = true;
+ a_Info[E_BLOCK_PISTON_MOVED_BLOCK ].m_Transparent = true;
a_Info[E_BLOCK_POTATOES ].m_Transparent = true;
a_Info[E_BLOCK_POWERED_RAIL ].m_Transparent = true;
- a_Info[E_BLOCK_PISTON_EXTENSION ].m_Transparent = true;
a_Info[E_BLOCK_PUMPKIN_STEM ].m_Transparent = true;
a_Info[E_BLOCK_RAIL ].m_Transparent = true;
a_Info[E_BLOCK_RED_MUSHROOM ].m_Transparent = true;
+ a_Info[E_BLOCK_REDSTONE_REPEATER_OFF].m_Transparent = true;
+ a_Info[E_BLOCK_REDSTONE_REPEATER_ON].m_Transparent = true;
+ a_Info[E_BLOCK_REDSTONE_TORCH_OFF ].m_Transparent = true;
+ a_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_Transparent = true;
+ a_Info[E_BLOCK_REDSTONE_WIRE ].m_Transparent = true;
+ a_Info[E_BLOCK_SAPLING ].m_Transparent = true;
a_Info[E_BLOCK_SIGN_POST ].m_Transparent = true;
a_Info[E_BLOCK_SNOW ].m_Transparent = true;
a_Info[E_BLOCK_STAINED_GLASS ].m_Transparent = true;
a_Info[E_BLOCK_STAINED_GLASS_PANE ].m_Transparent = true;
a_Info[E_BLOCK_STATIONARY_LAVA ].m_Transparent = true;
a_Info[E_BLOCK_STATIONARY_WATER ].m_Transparent = true;
+ a_Info[E_BLOCK_STICKY_PISTON ].m_Transparent = true;
a_Info[E_BLOCK_STONE_BUTTON ].m_Transparent = true;
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_Transparent = true;
- a_Info[E_BLOCK_TRIPWIRE ].m_Transparent = true;
- a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_Transparent = true;
+ a_Info[E_BLOCK_STONE_SLAB ].m_Transparent = true;
+ a_Info[E_BLOCK_SUGARCANE ].m_Transparent = true;
a_Info[E_BLOCK_TALL_GRASS ].m_Transparent = true;
a_Info[E_BLOCK_TORCH ].m_Transparent = true;
+ a_Info[E_BLOCK_TRAPDOOR ].m_Transparent = true;
+ a_Info[E_BLOCK_TRAPPED_CHEST ].m_Transparent = true;
+ a_Info[E_BLOCK_TRIPWIRE ].m_Transparent = true;
+ a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_Transparent = true;
a_Info[E_BLOCK_VINES ].m_Transparent = true;
a_Info[E_BLOCK_WALLSIGN ].m_Transparent = true;
a_Info[E_BLOCK_WATER ].m_Transparent = true;
a_Info[E_BLOCK_WOODEN_BUTTON ].m_Transparent = true;
a_Info[E_BLOCK_WOODEN_DOOR ].m_Transparent = true;
a_Info[E_BLOCK_WOODEN_PRESSURE_PLATE].m_Transparent = true;
-
- // TODO: Any other transparent blocks?
+ a_Info[E_BLOCK_WOODEN_SLAB ].m_Transparent = true;
// One hit break blocks:
@@ -183,11 +287,14 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_CARROTS ].m_OneHitDig = true;
a_Info[E_BLOCK_CROPS ].m_OneHitDig = true;
a_Info[E_BLOCK_DANDELION ].m_OneHitDig = true;
+ a_Info[E_BLOCK_DEAD_BUSH ].m_OneHitDig = true;
a_Info[E_BLOCK_FIRE ].m_OneHitDig = true;
a_Info[E_BLOCK_FLOWER ].m_OneHitDig = true;
a_Info[E_BLOCK_FLOWER_POT ].m_OneHitDig = true;
a_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_OneHitDig = true;
+ a_Info[E_BLOCK_LILY_PAD ].m_OneHitDig = true;
a_Info[E_BLOCK_MELON_STEM ].m_OneHitDig = true;
+ a_Info[E_BLOCK_NETHER_WART ].m_OneHitDig = true;
a_Info[E_BLOCK_POTATOES ].m_OneHitDig = true;
a_Info[E_BLOCK_PUMPKIN_STEM ].m_OneHitDig = true;
a_Info[E_BLOCK_REDSTONE_REPEATER_OFF].m_OneHitDig = true;
@@ -210,24 +317,32 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_BED ].m_PistonBreakable = true;
a_Info[E_BLOCK_BIG_FLOWER ].m_PistonBreakable = true;
a_Info[E_BLOCK_BROWN_MUSHROOM ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_CACTUS ].m_PistonBreakable = true;
a_Info[E_BLOCK_CAKE ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_CARROTS ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_COCOA_POD ].m_PistonBreakable = true;
a_Info[E_BLOCK_COBWEB ].m_PistonBreakable = true;
a_Info[E_BLOCK_CROPS ].m_PistonBreakable = true;
a_Info[E_BLOCK_DANDELION ].m_PistonBreakable = true;
a_Info[E_BLOCK_DEAD_BUSH ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_DRAGON_EGG ].m_PistonBreakable = true;
a_Info[E_BLOCK_FIRE ].m_PistonBreakable = true;
a_Info[E_BLOCK_FLOWER ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_FLOWER_POT ].m_PistonBreakable = true;
a_Info[E_BLOCK_HEAD ].m_PistonBreakable = true;
a_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_PistonBreakable = true;
a_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_PistonBreakable = true;
a_Info[E_BLOCK_IRON_DOOR ].m_PistonBreakable = true;
a_Info[E_BLOCK_JACK_O_LANTERN ].m_PistonBreakable = true;
a_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_PistonBreakable = true;
+ a_Info[E_BLOCK_LILY_PAD ].m_PistonBreakable = true;
a_Info[E_BLOCK_LADDER ].m_PistonBreakable = true;
a_Info[E_BLOCK_LAVA ].m_PistonBreakable = true;
a_Info[E_BLOCK_LEVER ].m_PistonBreakable = true;
a_Info[E_BLOCK_MELON ].m_PistonBreakable = true;
a_Info[E_BLOCK_MELON_STEM ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_NETHER_WART ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_POTATOES ].m_PistonBreakable = true;
a_Info[E_BLOCK_PUMPKIN ].m_PistonBreakable = true;
a_Info[E_BLOCK_PUMPKIN_STEM ].m_PistonBreakable = true;
a_Info[E_BLOCK_REDSTONE_REPEATER_OFF].m_PistonBreakable = true;
@@ -237,6 +352,8 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_REDSTONE_WIRE ].m_PistonBreakable = true;
a_Info[E_BLOCK_RED_MUSHROOM ].m_PistonBreakable = true;
a_Info[E_BLOCK_REEDS ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_SAPLING ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_SIGN_POST ].m_PistonBreakable = true;
a_Info[E_BLOCK_SNOW ].m_PistonBreakable = true;
a_Info[E_BLOCK_STATIONARY_LAVA ].m_PistonBreakable = true;
a_Info[E_BLOCK_STATIONARY_WATER ].m_PistonBreakable = true;
@@ -244,104 +361,85 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_PistonBreakable = true;
a_Info[E_BLOCK_TALL_GRASS ].m_PistonBreakable = true;
a_Info[E_BLOCK_TORCH ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_TRAPDOOR ].m_PistonBreakable = true;
a_Info[E_BLOCK_TRIPWIRE ].m_PistonBreakable = true;
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_PistonBreakable = true;
a_Info[E_BLOCK_VINES ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_WALLSIGN ].m_PistonBreakable = true;
a_Info[E_BLOCK_WATER ].m_PistonBreakable = true;
a_Info[E_BLOCK_WOODEN_BUTTON ].m_PistonBreakable = true;
a_Info[E_BLOCK_WOODEN_DOOR ].m_PistonBreakable = true;
a_Info[E_BLOCK_WOODEN_PRESSURE_PLATE].m_PistonBreakable = true;
- // Blocks that cannot be snowed over:
- a_Info[E_BLOCK_ACTIVE_COMPARATOR ].m_IsSnowable = false;
- a_Info[E_BLOCK_AIR ].m_IsSnowable = false;
- a_Info[E_BLOCK_BIG_FLOWER ].m_IsSnowable = false;
- a_Info[E_BLOCK_BROWN_MUSHROOM ].m_IsSnowable = false;
- a_Info[E_BLOCK_CACTUS ].m_IsSnowable = false;
- a_Info[E_BLOCK_CHEST ].m_IsSnowable = false;
- a_Info[E_BLOCK_CROPS ].m_IsSnowable = false;
- a_Info[E_BLOCK_COBBLESTONE_WALL ].m_IsSnowable = false;
- a_Info[E_BLOCK_DANDELION ].m_IsSnowable = false;
- a_Info[E_BLOCK_FIRE ].m_IsSnowable = false;
- a_Info[E_BLOCK_FLOWER ].m_IsSnowable = false;
- a_Info[E_BLOCK_GLASS ].m_IsSnowable = false;
- a_Info[E_BLOCK_ICE ].m_IsSnowable = false;
- a_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_IsSnowable = false;
- a_Info[E_BLOCK_LAVA ].m_IsSnowable = false;
- a_Info[E_BLOCK_LILY_PAD ].m_IsSnowable = false;
- a_Info[E_BLOCK_REDSTONE_REPEATER_OFF].m_IsSnowable = false;
- a_Info[E_BLOCK_REDSTONE_REPEATER_ON].m_IsSnowable = false;
- a_Info[E_BLOCK_REDSTONE_TORCH_OFF ].m_IsSnowable = false;
- a_Info[E_BLOCK_REDSTONE_TORCH_ON ].m_IsSnowable = false;
- a_Info[E_BLOCK_REDSTONE_WIRE ].m_IsSnowable = false;
- a_Info[E_BLOCK_RED_MUSHROOM ].m_IsSnowable = false;
- a_Info[E_BLOCK_REEDS ].m_IsSnowable = false;
- a_Info[E_BLOCK_SAPLING ].m_IsSnowable = false;
- a_Info[E_BLOCK_SIGN_POST ].m_IsSnowable = false;
- a_Info[E_BLOCK_SNOW ].m_IsSnowable = false;
- a_Info[E_BLOCK_STAINED_GLASS ].m_IsSnowable = false;
- a_Info[E_BLOCK_STAINED_GLASS_PANE ].m_IsSnowable = false;
- a_Info[E_BLOCK_STATIONARY_LAVA ].m_IsSnowable = false;
- a_Info[E_BLOCK_STATIONARY_WATER ].m_IsSnowable = false;
- a_Info[E_BLOCK_TALL_GRASS ].m_IsSnowable = false;
- a_Info[E_BLOCK_TNT ].m_IsSnowable = false;
- a_Info[E_BLOCK_TORCH ].m_IsSnowable = false;
- a_Info[E_BLOCK_TRIPWIRE ].m_IsSnowable = false;
- a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_IsSnowable = false;
- a_Info[E_BLOCK_VINES ].m_IsSnowable = false;
- a_Info[E_BLOCK_WALLSIGN ].m_IsSnowable = false;
- a_Info[E_BLOCK_WATER ].m_IsSnowable = false;
- a_Info[E_BLOCK_RAIL ].m_IsSnowable = false;
- a_Info[E_BLOCK_ACTIVATOR_RAIL ].m_IsSnowable = false;
- a_Info[E_BLOCK_POWERED_RAIL ].m_IsSnowable = false;
- a_Info[E_BLOCK_DETECTOR_RAIL ].m_IsSnowable = false;
- a_Info[E_BLOCK_COBWEB ].m_IsSnowable = false;
- a_Info[E_BLOCK_HEAD ].m_IsSnowable = false;
-
-
- // Blocks that don't drop without a special tool:
- a_Info[E_BLOCK_BRICK ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_CAULDRON ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_COAL_ORE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_COBBLESTONE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_COBBLESTONE_WALL ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_COBBLESTONE_STAIRS ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_COBWEB ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_DIAMOND_BLOCK ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_DIAMOND_ORE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_DOUBLE_STONE_SLAB ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_EMERALD_ORE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_END_STONE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_GOLD_BLOCK ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_GOLD_ORE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_IRON_BLOCK ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_IRON_ORE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_LAPIS_BLOCK ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_LAPIS_ORE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_MOSSY_COBBLESTONE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_NETHERRACK ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_NETHER_BRICK ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_NETHER_BRICK_STAIRS ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_OBSIDIAN ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_REDSTONE_ORE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_SANDSTONE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_SANDSTONE_STAIRS ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_SNOW ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_STONE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_STONE_BRICKS ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_STONE_BRICK_STAIRS ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_STONE_SLAB ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_VINES ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_FURNACE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_LIT_FURNACE ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_ANVIL ].m_RequiresSpecialTool = true;
- a_Info[E_BLOCK_ENCHANTMENT_TABLE ].m_RequiresSpecialTool = true;
-
+ // Blocks that can be snowed over:
+ a_Info[E_BLOCK_BEDROCK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_BLOCK_OF_COAL ].m_IsSnowable = true;
+ a_Info[E_BLOCK_BLOCK_OF_REDSTONE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_BOOKCASE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_BRICK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_CLAY ].m_IsSnowable = true;
+ a_Info[E_BLOCK_CRAFTING_TABLE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_COAL_ORE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_COMMAND_BLOCK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_COBBLESTONE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_DIAMOND_BLOCK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_DIAMOND_ORE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_DIRT ].m_IsSnowable = true;
+ a_Info[E_BLOCK_DISPENSER ].m_IsSnowable = true;
+ a_Info[E_BLOCK_DOUBLE_STONE_SLAB ].m_IsSnowable = true;
+ a_Info[E_BLOCK_DOUBLE_WOODEN_SLAB ].m_IsSnowable = true;
+ a_Info[E_BLOCK_DROPPER ].m_IsSnowable = true;
+ a_Info[E_BLOCK_EMERALD_BLOCK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_EMERALD_ORE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_END_STONE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_FURNACE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_GLOWSTONE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_GOLD_BLOCK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_GOLD_ORE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_GRASS ].m_IsSnowable = true;
+ a_Info[E_BLOCK_GRAVEL ].m_IsSnowable = true;
+ a_Info[E_BLOCK_HARDENED_CLAY ].m_IsSnowable = true;
+ a_Info[E_BLOCK_HAY_BALE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_HUGE_BROWN_MUSHROOM ].m_IsSnowable = true;
+ a_Info[E_BLOCK_HUGE_RED_MUSHROOM ].m_IsSnowable = true;
+ a_Info[E_BLOCK_IRON_BLOCK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_IRON_ORE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_JACK_O_LANTERN ].m_IsSnowable = true;
+ a_Info[E_BLOCK_JUKEBOX ].m_IsSnowable = true;
+ a_Info[E_BLOCK_LAPIS_BLOCK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_LAPIS_ORE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_LEAVES ].m_IsSnowable = true;
+ a_Info[E_BLOCK_LIT_FURNACE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_LOG ].m_IsSnowable = true;
+ a_Info[E_BLOCK_MELON ].m_IsSnowable = true;
+ a_Info[E_BLOCK_MOSSY_COBBLESTONE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_MYCELIUM ].m_IsSnowable = true;
+ a_Info[E_BLOCK_NETHER_BRICK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_NETHER_QUARTZ_ORE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_NETHERRACK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_NEW_LEAVES ].m_IsSnowable = true;
+ a_Info[E_BLOCK_NEW_LOG ].m_IsSnowable = true;
+ a_Info[E_BLOCK_NOTE_BLOCK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_OBSIDIAN ].m_IsSnowable = true;
+ a_Info[E_BLOCK_PLANKS ].m_IsSnowable = true;
+ a_Info[E_BLOCK_PUMPKIN ].m_IsSnowable = true;
+ a_Info[E_BLOCK_QUARTZ_BLOCK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_REDSTONE_LAMP_OFF ].m_IsSnowable = true;
+ a_Info[E_BLOCK_REDSTONE_LAMP_ON ].m_IsSnowable = true;
+ a_Info[E_BLOCK_REDSTONE_ORE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_IsSnowable = true;
+ a_Info[E_BLOCK_SAND ].m_IsSnowable = true;
+ a_Info[E_BLOCK_SANDSTONE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_SILVERFISH_EGG ].m_IsSnowable = true;
+ a_Info[E_BLOCK_SNOW_BLOCK ].m_IsSnowable = true;
+ a_Info[E_BLOCK_SOULSAND ].m_IsSnowable = true;
+ a_Info[E_BLOCK_SPONGE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_STAINED_CLAY ].m_IsSnowable = true;
+ a_Info[E_BLOCK_STONE ].m_IsSnowable = true;
+ a_Info[E_BLOCK_STONE_BRICKS ].m_IsSnowable = true;
+ a_Info[E_BLOCK_TNT ].m_IsSnowable = true;
+ a_Info[E_BLOCK_WOOL ].m_IsSnowable = true;
// Nonsolid blocks:
a_Info[E_BLOCK_ACTIVATOR_RAIL ].m_IsSolid = false;
@@ -355,8 +453,6 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_DANDELION ].m_IsSolid = false;
a_Info[E_BLOCK_DETECTOR_RAIL ].m_IsSolid = false;
a_Info[E_BLOCK_END_PORTAL ].m_IsSolid = false;
- a_Info[E_BLOCK_FENCE ].m_IsSolid = false;
- a_Info[E_BLOCK_FENCE_GATE ].m_IsSolid = false;
a_Info[E_BLOCK_FIRE ].m_IsSolid = false;
a_Info[E_BLOCK_FLOWER ].m_IsSolid = false;
a_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_IsSolid = false;
@@ -388,7 +484,6 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_WATER ].m_IsSolid = false;
a_Info[E_BLOCK_WOODEN_BUTTON ].m_IsSolid = false;
a_Info[E_BLOCK_WOODEN_PRESSURE_PLATE].m_IsSolid = false;
- a_Info[E_BLOCK_WOODEN_SLAB ].m_IsSolid = false;
// Blocks that fully occupy their voxel - used as a guide for torch placeable blocks, amongst other things:
@@ -452,9 +547,30 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_SILVERFISH_EGG ].m_FullyOccupiesVoxel = true;
a_Info[E_BLOCK_SPONGE ].m_FullyOccupiesVoxel = true;
a_Info[E_BLOCK_STAINED_CLAY ].m_FullyOccupiesVoxel = true;
- a_Info[E_BLOCK_WOOL ].m_FullyOccupiesVoxel = true;
a_Info[E_BLOCK_STONE ].m_FullyOccupiesVoxel = true;
a_Info[E_BLOCK_STONE_BRICKS ].m_FullyOccupiesVoxel = true;
+ a_Info[E_BLOCK_WOOL ].m_FullyOccupiesVoxel = true;
+
+
+ // Blocks that can be terraformed
+ a_Info[E_BLOCK_COAL_ORE ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_COBBLESTONE ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_DIAMOND_ORE ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_DIRT ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_GOLD_ORE ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_GRASS ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_GRAVEL ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_HARDENED_CLAY ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_IRON_ORE ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_MYCELIUM ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_NETHERRACK ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_REDSTONE_ORE ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_REDSTONE_ORE_GLOWING].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_SAND ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_SANDSTONE ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_SOULSAND ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_STAINED_CLAY ].m_CanBeTerraformed = true;
+ a_Info[E_BLOCK_STONE ].m_CanBeTerraformed = true;
}
diff --git a/src/BlockInfo.h b/src/BlockInfo.h
index d6d4e7430..4c66c095a 100644
--- a/src/BlockInfo.h
+++ b/src/BlockInfo.h
@@ -39,15 +39,15 @@ public:
/** Can this block hold snow atop? */
bool m_IsSnowable;
- /** Does this block require a tool to drop? */
- bool m_RequiresSpecialTool;
-
/** Is this block solid (player cannot walk through)? */
bool m_IsSolid;
/** Does this block fully occupy its voxel - is it a 'full' block? */
bool m_FullyOccupiesVoxel;
+ /** Can a finisher change it? */
+ bool m_CanBeTerraformed;
+
// tolua_end
/** Associated block handler. */
@@ -61,9 +61,9 @@ public:
inline static bool IsOneHitDig (BLOCKTYPE a_Type) { return Get(a_Type).m_OneHitDig; }
inline static bool IsPistonBreakable (BLOCKTYPE a_Type) { return Get(a_Type).m_PistonBreakable; }
inline static bool IsSnowable (BLOCKTYPE a_Type) { return Get(a_Type).m_IsSnowable; }
- inline static bool RequiresSpecialTool (BLOCKTYPE a_Type) { return Get(a_Type).m_RequiresSpecialTool; }
inline static bool IsSolid (BLOCKTYPE a_Type) { return Get(a_Type).m_IsSolid; }
inline static bool FullyOccupiesVoxel (BLOCKTYPE a_Type) { return Get(a_Type).m_FullyOccupiesVoxel; }
+ inline static bool CanBeTerraformed (BLOCKTYPE a_Type) { return Get(a_Type).m_CanBeTerraformed; }
// tolua_end
@@ -81,7 +81,7 @@ protected:
/** Initializes the specified BlockInfo structures with block-specific values. */
static void Initialize(cBlockInfoArray & a_BlockInfos);
-}; // tolua_export
+}; // tolua_export
diff --git a/src/BlockTracer.h b/src/BlockTracer.h
index a18c8df4d..c569b4ec6 100644
--- a/src/BlockTracer.h
+++ b/src/BlockTracer.h
@@ -39,13 +39,13 @@ public:
/** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded
When this callback returns true, the tracing is aborted.
*/
- virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace)
- {
+ virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace)
+ {
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_EntryFace);
- return false;
+ return false;
}
/** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
@@ -54,8 +54,8 @@ public:
Note that some paths can go out of the world and come back again (parabola),
in such a case this callback is followed by OnIntoWorld() and further OnNextBlock() calls
*/
- virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ)
- {
+ virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ)
+ {
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
@@ -68,12 +68,12 @@ public:
Note that some paths can go out of the world and come back again (parabola),
in such a case this callback is followed by further OnNextBlock() calls
*/
- virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ)
- {
+ virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ)
+ {
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
- return false;
+ return false;
}
/** Called when the path is sure not to hit any more blocks.
diff --git a/src/Blocks/BlockAnvil.h b/src/Blocks/BlockAnvil.h
index 35a356678..5c4661c11 100644
--- a/src/Blocks/BlockAnvil.h
+++ b/src/Blocks/BlockAnvil.h
@@ -34,7 +34,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp
index 6a3c6a55b..cd5783f58 100644
--- a/src/Blocks/BlockBed.cpp
+++ b/src/Blocks/BlockBed.cpp
@@ -15,7 +15,7 @@ void cBlockBedHandler::OnPlacedByPlayer(
if (a_BlockMeta < 8)
{
Vector3i Direction = MetaDataToDirection(a_BlockMeta);
- a_ChunkInterface.SetBlock(a_WorldInterface,a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z, E_BLOCK_BED, a_BlockMeta | 0x8);
+ a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z, E_BLOCK_BED, a_BlockMeta | 0x8);
}
}
@@ -27,8 +27,8 @@ void cBlockBedHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInt
{
NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- Vector3i ThisPos( a_BlockX, a_BlockY, a_BlockZ );
- Vector3i Direction = MetaDataToDirection( OldMeta & 0x7 );
+ Vector3i ThisPos( a_BlockX, a_BlockY, a_BlockZ);
+ Vector3i Direction = MetaDataToDirection( OldMeta & 0x7);
if (OldMeta & 0x8)
{
// Was pillow
@@ -108,7 +108,7 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (Meta & 0x4)
{
- a_Player->SendMessageFailure("This bed is occupied.");
+ a_Player->SendMessageFailure("This bed is occupied");
}
else
{
@@ -116,23 +116,25 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
if (Meta & 0x8)
{
- // Is pillow
+ // Is pillow
a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX, a_BlockY, a_BlockZ);
}
else
{
// Is foot end
- VERIFY((Meta & 0x4) != 0x4); // Occupied flag should never be set, else our compilator (intended) is broken
+ VERIFY((Meta & 0x4) != 0x4); // Occupied flag should never be set, else our compilator (intended) is broken
PillowDirection = MetaDataToDirection(Meta & 0x7);
- if (a_ChunkInterface.GetBlock(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z) == E_BLOCK_BED) // Must always use pillow location for sleeping
+ if (a_ChunkInterface.GetBlock(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z) == E_BLOCK_BED) // Must always use pillow location for sleeping
{
a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z);
}
}
- a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta | 0x4); // Where 0x4 = occupied bit
+ a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta | 0x4); // Where 0x4 = occupied bit
a_Player->SetIsInBed(true);
+ a_Player->SetBedPos(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
+ a_Player->SendMessageSuccess("Home position set successfully");
cTimeFastForwardTester Tester;
if (a_WorldInterface.ForEachPlayer(Tester))
@@ -140,9 +142,9 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
cPlayerBedStateUnsetter Unsetter(Vector3i(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z), a_WorldInterface);
a_WorldInterface.ForEachPlayer(Unsetter);
a_WorldInterface.SetTimeOfDay(0);
- a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0xB); // Where 0xB = 1011, and zero is to make sure 'occupied' bit is always unset
+ a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0xB); // Where 0xB = 1011, and zero is to make sure 'occupied' bit is always unset
}
- }
+ }
}
else
{
diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h
index 51e79b888..bf9d9c01d 100644
--- a/src/Blocks/BlockBed.h
+++ b/src/Blocks/BlockBed.h
@@ -16,7 +16,7 @@ class cBlockBedHandler :
{
public:
cBlockBedHandler(BLOCKTYPE a_BlockType)
- : cMetaRotator<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01,true>(a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01, true>(a_BlockType)
{
}
diff --git a/src/Blocks/BlockBigFlower.h b/src/Blocks/BlockBigFlower.h
index 39fd3cac8..72e552dee 100644
--- a/src/Blocks/BlockBigFlower.h
+++ b/src/Blocks/BlockBigFlower.h
@@ -19,16 +19,16 @@ public:
}
- virtual void DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual void DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_CanDrop, bool a_DropVerbatim) override
{
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (Meta & 0x8)
{
- super::DropBlock(a_ChunkInterface, a_WorldInterface, a_BlockPluginInterface, a_Digger, a_BlockX, a_BlockY - 1, a_BlockZ);
+ super::DropBlock(a_ChunkInterface, a_WorldInterface, a_BlockPluginInterface, a_Digger, a_BlockX, a_BlockY - 1, a_BlockZ, a_CanDrop, a_DropVerbatim);
}
else
{
- super::DropBlock(a_ChunkInterface, a_WorldInterface, a_BlockPluginInterface, a_Digger, a_BlockX, a_BlockY, a_BlockZ);
+ super::DropBlock(a_ChunkInterface, a_WorldInterface, a_BlockPluginInterface, a_Digger, a_BlockX, a_BlockY, a_BlockZ, a_CanDrop, a_DropVerbatim);
}
}
@@ -37,7 +37,7 @@ public:
{
NIBBLETYPE Meta = a_BlockMeta & 0x7;
- if ((Meta == 2) || (Meta == 3))
+ if ((Meta == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS) || (Meta == E_META_BIG_FLOWER_LARGE_FERN))
{
return;
}
@@ -63,11 +63,11 @@ public:
if (r1.randInt(10) == 5)
{
cItems Pickups;
- if (FlowerMeta == 2)
+ if (FlowerMeta == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS)
{
Pickups.Add(E_BLOCK_TALL_GRASS, 2, 1);
}
- else if (FlowerMeta == 3)
+ else if (FlowerMeta == E_META_BIG_FLOWER_LARGE_FERN)
{
Pickups.Add(E_BLOCK_TALL_GRASS, 2, 2);
}
@@ -86,8 +86,8 @@ public:
virtual void OnPlacedByPlayer(
- cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
) override
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index ada7d58f7..3b45afff8 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.h
@@ -24,7 +24,7 @@ public:
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
a_WorldInterface.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
- a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
+ a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
// Queue a button reset (unpress)
a_ChunkInterface.QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x07), m_BlockType == E_BLOCK_STONE_BUTTON ? 20 : 30, m_BlockType, a_WorldInterface);
@@ -46,7 +46,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -74,7 +74,7 @@ public:
default:
{
ASSERT(!"Unhandled block face!");
- return 0x0; // No idea, give a special meta (button in centre of block)
+ return 0x0; // No idea, give a special meta (button in centre of block)
}
}
}
diff --git a/src/Blocks/BlockCake.h b/src/Blocks/BlockCake.h
index 36e133388..f05f468e5 100644
--- a/src/Blocks/BlockCake.h
+++ b/src/Blocks/BlockCake.h
@@ -19,7 +19,7 @@ public:
{
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- if (!a_Player->Feed(2, 0.1))
+ if (!a_Player->Feed(2, 0.4))
{
return;
}
diff --git a/src/Blocks/BlockCarpet.h b/src/Blocks/BlockCarpet.h
index 33dc1da6c..d1aa52687 100644
--- a/src/Blocks/BlockCarpet.h
+++ b/src/Blocks/BlockCarpet.h
@@ -32,7 +32,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Blocks/BlockCauldron.h b/src/Blocks/BlockCauldron.h
index 41b79b6c3..e0f86f4cb 100644
--- a/src/Blocks/BlockCauldron.h
+++ b/src/Blocks/BlockCauldron.h
@@ -58,6 +58,24 @@ public:
{
return true;
}
+
+ virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
+ {
+ int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
+ int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
+ if (!a_WorldInterface.IsWeatherWetAt(BlockX, BlockZ) || (a_RelY != a_WorldInterface.GetHeight(BlockX, BlockZ)))
+ {
+ // It's not raining at our current location or we do not have a direct view of the sky
+ // We cannot eat the rain :(
+ return;
+ }
+
+ NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
+ if (Meta < 3)
+ {
+ a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, Meta + 1);
+ }
+ }
} ;
diff --git a/src/Blocks/BlockChest.h b/src/Blocks/BlockChest.h
index c9a769c75..28adbed4f 100644
--- a/src/Blocks/BlockChest.h
+++ b/src/Blocks/BlockChest.h
@@ -22,7 +22,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -44,16 +44,16 @@ public:
}
double yaw = a_Player->GetYaw();
if (
- (Area.GetRelBlockType(0, 0, 1) == E_BLOCK_CHEST) ||
- (Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
+ (Area.GetRelBlockType(0, 0, 1) == m_BlockType) ||
+ (Area.GetRelBlockType(2, 0, 1) == m_BlockType)
)
{
a_BlockMeta = ((yaw >= -90) && (yaw < 90)) ? 2 : 3;
return true;
}
if (
- (Area.GetRelBlockType(0, 0, 1) == E_BLOCK_CHEST) ||
- (Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
+ (Area.GetRelBlockType(0, 0, 1) == m_BlockType) ||
+ (Area.GetRelBlockType(2, 0, 1) == m_BlockType)
)
{
// FIXME: This is unreachable, as the condition is the same as the above one
@@ -68,7 +68,7 @@ public:
virtual void OnPlacedByPlayer(
- cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
+ cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
@@ -130,12 +130,12 @@ public:
}
int NumChestNeighbors = 0;
- if (Area.GetRelBlockType(1, 0, 2) == E_BLOCK_CHEST)
+ if (Area.GetRelBlockType(1, 0, 2) == m_BlockType)
{
if (
- (Area.GetRelBlockType(0, 0, 2) == E_BLOCK_CHEST) ||
- (Area.GetRelBlockType(1, 0, 1) == E_BLOCK_CHEST) ||
- (Area.GetRelBlockType(1, 0, 3) == E_BLOCK_CHEST)
+ (Area.GetRelBlockType(0, 0, 2) == m_BlockType) ||
+ (Area.GetRelBlockType(1, 0, 1) == m_BlockType) ||
+ (Area.GetRelBlockType(1, 0, 3) == m_BlockType)
)
{
// Already a doublechest neighbor, disallow:
@@ -143,12 +143,12 @@ public:
}
NumChestNeighbors += 1;
}
- if (Area.GetRelBlockType(3, 0, 2) == E_BLOCK_CHEST)
+ if (Area.GetRelBlockType(3, 0, 2) == m_BlockType)
{
if (
- (Area.GetRelBlockType(4, 0, 2) == E_BLOCK_CHEST) ||
- (Area.GetRelBlockType(3, 0, 1) == E_BLOCK_CHEST) ||
- (Area.GetRelBlockType(3, 0, 3) == E_BLOCK_CHEST)
+ (Area.GetRelBlockType(4, 0, 2) == m_BlockType) ||
+ (Area.GetRelBlockType(3, 0, 1) == m_BlockType) ||
+ (Area.GetRelBlockType(3, 0, 3) == m_BlockType)
)
{
// Already a doublechest neighbor, disallow:
@@ -156,12 +156,12 @@ public:
}
NumChestNeighbors += 1;
}
- if (Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
+ if (Area.GetRelBlockType(2, 0, 1) == m_BlockType)
{
if (
- (Area.GetRelBlockType(2, 0, 0) == E_BLOCK_CHEST) ||
- (Area.GetRelBlockType(1, 0, 1) == E_BLOCK_CHEST) ||
- (Area.GetRelBlockType(3, 0, 1) == E_BLOCK_CHEST)
+ (Area.GetRelBlockType(2, 0, 0) == m_BlockType) ||
+ (Area.GetRelBlockType(1, 0, 1) == m_BlockType) ||
+ (Area.GetRelBlockType(3, 0, 1) == m_BlockType)
)
{
// Already a doublechest neighbor, disallow:
@@ -169,12 +169,12 @@ public:
}
NumChestNeighbors += 1;
}
- if (Area.GetRelBlockType(2, 0, 3) == E_BLOCK_CHEST)
+ if (Area.GetRelBlockType(2, 0, 3) == m_BlockType)
{
if (
- (Area.GetRelBlockType(2, 0, 4) == E_BLOCK_CHEST) ||
- (Area.GetRelBlockType(1, 0, 3) == E_BLOCK_CHEST) ||
- (Area.GetRelBlockType(3, 0, 3) == E_BLOCK_CHEST)
+ (Area.GetRelBlockType(2, 0, 4) == m_BlockType) ||
+ (Area.GetRelBlockType(1, 0, 3) == m_BlockType) ||
+ (Area.GetRelBlockType(3, 0, 3) == m_BlockType)
)
{
// Already a doublechest neighbor, disallow:
@@ -217,7 +217,7 @@ public:
/// If there's a chest in the a_Area in the specified coords, modifies its meta to a_NewMeta and returns true.
bool CheckAndAdjustNeighbor(cChunkInterface & a_ChunkInterface, const cBlockArea & a_Area, int a_RelX, int a_RelZ, NIBBLETYPE a_NewMeta)
{
- if (a_Area.GetRelBlockType(a_RelX, 0, a_RelZ) != E_BLOCK_CHEST)
+ if (a_Area.GetRelBlockType(a_RelX, 0, a_RelZ) != m_BlockType)
{
return false;
}
@@ -228,7 +228,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- a_Pickups.push_back(cItem(E_BLOCK_CHEST, 1, 0));
+ a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
} ;
diff --git a/src/Blocks/BlockCloth.h b/src/Blocks/BlockCloth.h
index a136d3b9d..3c1ae7c25 100644
--- a/src/Blocks/BlockCloth.h
+++ b/src/Blocks/BlockCloth.h
@@ -16,13 +16,6 @@ public:
{
}
-
- virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
- {
- a_Pickups.push_back(cItem(E_BLOCK_WOOL, 1, a_BlockMeta));
- }
-
-
virtual const char * GetStepSound(void) override
{
return "step.cloth";
diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h
index 4dd05366d..6caaaab13 100644
--- a/src/Blocks/BlockComparator.h
+++ b/src/Blocks/BlockComparator.h
@@ -22,7 +22,7 @@ public:
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- Meta ^= 0x04; // Toggle 3rd (addition/subtraction) bit with XOR
+ Meta ^= 0x04; // Toggle 3rd (addition/subtraction) bit with XOR
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
}
diff --git a/src/Blocks/BlockCrops.h b/src/Blocks/BlockCrops.h
index 8606cf3f3..ae6e490e1 100644
--- a/src/Blocks/BlockCrops.h
+++ b/src/Blocks/BlockCrops.h
@@ -71,7 +71,7 @@ public:
}
}
}
- }
+ }
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
diff --git a/src/Blocks/BlockDirt.h b/src/Blocks/BlockDirt.h
index 2d4fccbac..d458c6062 100644
--- a/src/Blocks/BlockDirt.h
+++ b/src/Blocks/BlockDirt.h
@@ -81,7 +81,7 @@ public:
Chunk->GetBlockTypeMeta(BlockX, BlockY + 1, BlockZ, AboveDest, AboveMeta);
if (cBlockInfo::GetHandler(AboveDest)->CanDirtGrowGrass(AboveMeta))
{
- if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, BlockX * cChunkDef::Width, BlockY, BlockZ * cChunkDef::Width, ssGrassSpread))
+ if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(Chunk->GetWorld(), Chunk->GetPosX() * cChunkDef::Width + BlockX, BlockY, Chunk->GetPosZ() * cChunkDef::Width + BlockZ, ssGrassSpread))
{
Chunk->FastSetBlock(BlockX, BlockY, BlockZ, E_BLOCK_GRASS, 0);
}
diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp
index 934a01994..e80473cb5 100644
--- a/src/Blocks/BlockDoor.cpp
+++ b/src/Blocks/BlockDoor.cpp
@@ -152,7 +152,7 @@ NIBBLETYPE cBlockDoorHandler::MetaMirrorXY(NIBBLETYPE a_Meta)
// Return a_Meta if panel is a top panel (0x08 bit is set to 1)
// Note: Currently, you can not properly mirror the hinges on a double door. The orientation of the door is stored
- // in only the bottom tile while the hinge position is in the top tile. This function only operates on one tile at a time,
+ // in only the bottom tile while the hinge position is in the top tile. This function only operates on one tile at a time,
// so the function can only see either the hinge position or orientation, but not both, at any given time. The class itself
// needs extra datamembers.
if (a_Meta & 0x08) return a_Meta;
@@ -179,7 +179,7 @@ NIBBLETYPE cBlockDoorHandler::MetaMirrorYZ(NIBBLETYPE a_Meta)
// Return a_Meta if panel is a top panel (0x08 bit is set to 1)
// Note: Currently, you can not properly mirror the hinges on a double door. The orientation of the door is stored
- // in only the bottom tile while the hinge position is in the top tile. This function only operates on one tile at a time,
+ // in only the bottom tile while the hinge position is in the top tile. This function only operates on one tile at a time,
// so the function can only see either the hinge position or orientation, but not both, at any given time.The class itself
// needs extra datamembers.
diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h
index 049c4a334..c86fe829b 100644
--- a/src/Blocks/BlockDoor.h
+++ b/src/Blocks/BlockDoor.h
@@ -28,7 +28,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Blocks/BlockDropSpenser.h b/src/Blocks/BlockDropSpenser.h
index e2b3039fd..ba96c716a 100644
--- a/src/Blocks/BlockDropSpenser.h
+++ b/src/Blocks/BlockDropSpenser.h
@@ -24,7 +24,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -43,8 +43,8 @@ public:
// Mirrors defined by by a table. (Source, mincraft.gamepedia.com) 0x07 == 0111
switch (a_Meta & 0x07)
{
- case 0x00: return 0x01 + OtherMeta; // Down -> Up
- case 0x01: return 0x00 + OtherMeta; // Up -> Down
+ case 0x00: return 0x01 + OtherMeta; // Down -> Up
+ case 0x01: return 0x00 + OtherMeta; // Up -> Down
}
// Not Facing Up or Down; No change.
return a_Meta;
diff --git a/src/Blocks/BlockEnderchest.h b/src/Blocks/BlockEnderchest.h
index 67955f8ce..4672f1459 100644
--- a/src/Blocks/BlockEnderchest.h
+++ b/src/Blocks/BlockEnderchest.h
@@ -18,7 +18,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- //todo: Drop Ender Chest if using silk touch pickaxe
+ // todo: Drop Ender Chest if using silk touch pickaxe
a_Pickups.push_back(cItem(E_BLOCK_OBSIDIAN, 8, 0));
}
diff --git a/src/Blocks/BlockFarmland.h b/src/Blocks/BlockFarmland.h
index 3dd5bcd1d..bb624e54f 100644
--- a/src/Blocks/BlockFarmland.h
+++ b/src/Blocks/BlockFarmland.h
@@ -19,15 +19,13 @@
class cBlockFarmlandHandler :
public cBlockHandler
{
- typedef cBlockHandler super;
public:
- cBlockFarmlandHandler(void) :
- super(E_BLOCK_FARMLAND)
+ cBlockFarmlandHandler(BLOCKTYPE a_BlockType) :
+ cBlockHandler(a_BlockType)
{
}
-
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
{
bool Found = false;
@@ -56,10 +54,7 @@ public:
BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
for (size_t i = 0; i < NumBlocks; i++)
{
- if (
- (BlockTypes[i] == E_BLOCK_WATER) ||
- (BlockTypes[i] == E_BLOCK_STATIONARY_WATER)
- )
+ if (IsBlockWater(BlockTypes[i]))
{
Found = true;
break;
@@ -105,6 +100,11 @@ public:
}
}
}
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ a_Pickups.Add(E_BLOCK_DIRT, 1, 0); // Reset meta
+ }
} ;
diff --git a/src/Blocks/BlockFenceGate.h b/src/Blocks/BlockFenceGate.h
index e992870d4..ae99a4f94 100644
--- a/src/Blocks/BlockFenceGate.h
+++ b/src/Blocks/BlockFenceGate.h
@@ -19,7 +19,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -35,6 +35,7 @@ public:
NIBBLETYPE OldMetaData = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
NIBBLETYPE NewMetaData = PlayerYawToMetaData(a_Player->GetYaw());
OldMetaData ^= 4; // Toggle the gate
+
if ((OldMetaData & 1) == (NewMetaData & 1))
{
// Standing in front of the gate - apply new direction
diff --git a/src/Blocks/BlockFire.h b/src/Blocks/BlockFire.h
index 147e4b53e..c6a3e62cf 100644
--- a/src/Blocks/BlockFire.h
+++ b/src/Blocks/BlockFire.h
@@ -60,8 +60,8 @@ public:
return "step.wood";
}
- /// Traces along YP until it finds an obsidian block, returns Y difference or 0 if no portal, and -1 for border
- /// Takes the X, Y, and Z of the base block; with an optional MaxY for portal border finding
+ /** Traces along YP until it finds an obsidian block, returns Y difference or 0 if no portal, and -1 for border
+ Takes the X, Y, and Z of the base block; with an optional MaxY for portal border finding */
int FindObsidianCeiling(int X, int Y, int Z, cChunkInterface & a_ChunkInterface, int MaxY = 0)
{
if (a_ChunkInterface.GetBlock(X, Y, Z) != E_BLOCK_OBSIDIAN)
@@ -91,16 +91,15 @@ public:
return newY;
}
}
- else { return 0; }
}
return 0;
}
- /// Evaluates if coords have a valid border on top, based on MaxY
+ /** Evaluates if coords have a valid border on top, based on MaxY */
bool EvaluatePortalBorder(int X, int FoundObsidianY, int Z, int MaxY, cChunkInterface & a_ChunkInterface)
{
- for (int checkBorder = FoundObsidianY + 1; checkBorder <= MaxY - 1; checkBorder++) // FoundObsidianY + 1: FoundObsidianY has already been checked in FindObsidianCeiling; MaxY - 1: portal doesn't need corners
+ for (int checkBorder = FoundObsidianY + 1; checkBorder <= MaxY - 1; checkBorder++) // FoundObsidianY + 1: FoundObsidianY has already been checked in FindObsidianCeiling; MaxY - 1: portal doesn't need corners
{
if (a_ChunkInterface.GetBlock(X, checkBorder, Z) != E_BLOCK_OBSIDIAN)
{
@@ -115,10 +114,10 @@ public:
/// Finds entire frame in any direction with the coordinates of a base block and fills hole with nether portal (START HERE)
void FindAndSetPortalFrame(int X, int Y, int Z, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface)
{
- int MaxY = FindObsidianCeiling(X, Y, Z, a_ChunkInterface); // Get topmost obsidian block as reference for all other checks
- int X1 = X + 1, Z1 = Z + 1, X2 = X - 1, Z2 = Z - 1; // Duplicate XZ values, add/subtract one as we've checked the original already the line above
+ int MaxY = FindObsidianCeiling(X, Y, Z, a_ChunkInterface); // Get topmost obsidian block as reference for all other checks
+ int X1 = X + 1, Z1 = Z + 1, X2 = X - 1, Z2 = Z - 1; // Duplicate XZ values, add/subtract one as we've checked the original already the line above
- if (MaxY == 0) // Oh noes! Not a portal coordinate :(
+ if (MaxY == 0) // Oh noes! Not a portal coordinate :(
{
return;
}
@@ -127,11 +126,11 @@ public:
{
if (!FindPortalSliceZ(X, Y, Z1, Z2, MaxY, a_ChunkInterface))
{
- return; // No eligible portal construct, abort abort abort!!
+ return; // No eligible portal construct, abort abort abort!!
}
}
- for (int Height = Y + 1; Height <= MaxY - 1; Height++) // Loop through boundary to set portal blocks
+ for (int Height = Y + 1; Height <= MaxY - 1; Height++) // Loop through boundary to set portal blocks
{
for (int Width = XZM; Width <= XZP; Width++)
{
@@ -149,27 +148,28 @@ public:
return;
}
- /// Evaluates if coordinates are a portal going XP/XM; returns true if so, and writes boundaries to variable
- /// Takes coordinates of base block and Y coord of target obsidian ceiling
+ /** Evaluates if coordinates are a portal going XP/XM; returns true if so, and writes boundaries to variable
+ Takes coordinates of base block and Y coord of target obsidian ceiling */
bool FindPortalSliceX(int X1, int X2, int Y, int Z, int MaxY, cChunkInterface & a_ChunkInterface)
{
- Dir = 1; // Set assumed direction (will change if portal turns out to be facing the other direction)
+ Dir = 1; // Set assumed direction (will change if portal turns out to be facing the other direction)
bool FoundFrameXP = false, FoundFrameXM = false;
- for (; ((a_ChunkInterface.GetBlock(X1, Y, Z) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X1, Y + 1, Z) == E_BLOCK_OBSIDIAN)); X1++) // Check XP for obsidian blocks, exempting corners
+ for (; ((a_ChunkInterface.GetBlock(X1, Y, Z) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X1, Y + 1, Z) == E_BLOCK_OBSIDIAN)); X1++) // Check XP for obsidian blocks, exempting corners
{
int Value = FindObsidianCeiling(X1, Y, Z, a_ChunkInterface, MaxY);
- int ValueTwo = FindObsidianCeiling(X1, Y + 1, Z, a_ChunkInterface, MaxY); // For corners without obsidian
- if ((Value == -1) || (ValueTwo == -1)) // FindObsidianCeiling returns -1 upon frame-find
+ int ValueTwo = FindObsidianCeiling(X1, Y + 1, Z, a_ChunkInterface, MaxY); // For corners without obsidian
+ if ((Value == -1) || (ValueTwo == -1)) // FindObsidianCeiling returns -1 upon frame-find
{
- FoundFrameXP = true; // Found a frame border in this direction, proceed in other direction (don't go further)
+ FoundFrameXP = true; // Found a frame border in this direction, proceed in other direction (don't go further)
break;
}
- else if ((Value != MaxY) && (ValueTwo != MaxY)) // Make sure that there is a valid portal 'slice'
+ else if ((Value != MaxY) && (ValueTwo != MaxY)) // Make sure that there is a valid portal 'slice'
{
- return false; // Not valid slice, no portal can be formed
+ return false; // Not valid slice, no portal can be formed
}
- } XZP = X1 - 1; // Set boundary of frame interior
- for (; ((a_ChunkInterface.GetBlock(X2, Y, Z) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X2, Y + 1, Z) == E_BLOCK_OBSIDIAN)); X2--) // Go the other direction (XM)
+ }
+ XZP = X1 - 1; // Set boundary of frame interior
+ for (; ((a_ChunkInterface.GetBlock(X2, Y, Z) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X2, Y + 1, Z) == E_BLOCK_OBSIDIAN)); X2--) // Go the other direction (XM)
{
int Value = FindObsidianCeiling(X2, Y, Z, a_ChunkInterface, MaxY);
int ValueTwo = FindObsidianCeiling(X2, Y + 1, Z, a_ChunkInterface, MaxY);
@@ -182,7 +182,9 @@ public:
{
return false;
}
- } XZM = X2 + 1; // Set boundary, see previous
+ }
+ XZM = X2 + 1; // Set boundary, see previous
+
return (FoundFrameXP && FoundFrameXM);
}
@@ -204,7 +206,8 @@ public:
{
return false;
}
- } XZP = Z1 - 1;
+ }
+ XZP = Z1 - 1;
for (; ((a_ChunkInterface.GetBlock(X, Y, Z2) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X, Y + 1, Z2) == E_BLOCK_OBSIDIAN)); Z2--)
{
int Value = FindObsidianCeiling(X, Y, Z2, a_ChunkInterface, MaxY);
@@ -218,7 +221,9 @@ public:
{
return false;
}
- } XZM = Z2 + 1;
+ }
+ XZM = Z2 + 1;
+
return (FoundFrameZP && FoundFrameZM);
}
};
diff --git a/src/Blocks/BlockFlower.h b/src/Blocks/BlockFlower.h
index e8fd4c7f6..6f64c062b 100644
--- a/src/Blocks/BlockFlower.h
+++ b/src/Blocks/BlockFlower.h
@@ -19,7 +19,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- // Reset meta to 0
+ // Reset meta to zero
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
diff --git a/src/Blocks/BlockFluid.h b/src/Blocks/BlockFluid.h
index d0c4ea55b..8c0aae041 100644
--- a/src/Blocks/BlockFluid.h
+++ b/src/Blocks/BlockFluid.h
@@ -17,7 +17,7 @@ public:
: cBlockHandler(a_BlockType)
{
- }
+ }
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
diff --git a/src/Blocks/BlockFurnace.h b/src/Blocks/BlockFurnace.h
index 74582c3b3..2c7310ac9 100644
--- a/src/Blocks/BlockFurnace.h
+++ b/src/Blocks/BlockFurnace.h
@@ -13,7 +13,7 @@ class cBlockFurnaceHandler :
public cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
{
public:
- cBlockFurnaceHandler(BLOCKTYPE a_BlockType)
+ cBlockFurnaceHandler(BLOCKTYPE a_BlockType)
: cMetaRotator<cBlockEntityHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
{
}
@@ -27,7 +27,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Blocks/BlockGlowstone.h b/src/Blocks/BlockGlowstone.h
index 6c198efc4..d1353e29a 100644
--- a/src/Blocks/BlockGlowstone.h
+++ b/src/Blocks/BlockGlowstone.h
@@ -15,13 +15,13 @@ public:
: cBlockHandler(a_BlockType)
{
}
-
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
- MTRand r1;
- a_Pickups.push_back(cItem(E_ITEM_GLOWSTONE_DUST, (char)(2 + r1.randInt(2)), 0));
+ cFastRandom Random;
+ a_Pickups.push_back(cItem(E_ITEM_GLOWSTONE_DUST, (char)(2 + Random.NextInt(3)), 0));
}
} ;
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index 3ddb7531d..028277e4c 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -45,13 +45,11 @@
#include "BlockLadder.h"
#include "BlockLeaves.h"
#include "BlockLilypad.h"
-#include "BlockNewLeaves.h"
#include "BlockLever.h"
#include "BlockMelon.h"
#include "BlockMushroom.h"
#include "BlockMycelium.h"
#include "BlockNetherWart.h"
-#include "BlockNote.h"
#include "BlockOre.h"
#include "BlockPiston.h"
#include "BlockPlanks.h"
@@ -70,7 +68,7 @@
#include "BlockSand.h"
#include "BlockSapling.h"
#include "BlockSideways.h"
-#include "BlockSign.h"
+#include "BlockSignPost.h"
#include "BlockSlab.h"
#include "BlockSnow.h"
#include "BlockStairs.h"
@@ -81,6 +79,7 @@
#include "BlockTorch.h"
#include "BlockTrapdoor.h"
#include "BlockVine.h"
+#include "BlockWallSign.h"
#include "BlockWorkbench.h"
@@ -174,12 +173,13 @@ public:
cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
{
- switch(a_BlockType)
+ switch (a_BlockType)
{
// Block handlers, alphabetically sorted:
case E_BLOCK_ACACIA_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
case E_BLOCK_ANVIL: return new cBlockAnvilHandler (a_BlockType);
+ case E_BLOCK_BEACON: return new cBlockEntityHandler (a_BlockType);
case E_BLOCK_BED: return new cBlockBedHandler (a_BlockType);
case E_BLOCK_BIG_FLOWER: return new cBlockBigFlowerHandler (a_BlockType);
case E_BLOCK_BIRCH_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
@@ -211,7 +211,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_EMERALD_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_ENCHANTMENT_TABLE: return new cBlockEnchantmentTableHandler(a_BlockType);
case E_BLOCK_ENDER_CHEST: return new cBlockEnderchestHandler (a_BlockType);
- case E_BLOCK_FARMLAND: return new cBlockFarmlandHandler ( );
+ case E_BLOCK_FARMLAND: return new cBlockFarmlandHandler (a_BlockType);
case E_BLOCK_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
case E_BLOCK_FIRE: return new cBlockFireHandler (a_BlockType);
case E_BLOCK_FLOWER_POT: return new cBlockFlowerPotHandler (a_BlockType);
@@ -238,9 +238,9 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_LAPIS_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_LAVA: return new cBlockLavaHandler (a_BlockType);
case E_BLOCK_LEAVES: return new cBlockLeavesHandler (a_BlockType);
+ case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return new cBlockPressurePlateHandler(a_BlockType);
case E_BLOCK_LILY_PAD: return new cBlockLilypadHandler (a_BlockType);
case E_BLOCK_LIT_FURNACE: return new cBlockFurnaceHandler (a_BlockType);
- case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return new cBlockPressurePlateHandler(a_BlockType);
case E_BLOCK_LOG: return new cBlockSidewaysHandler (a_BlockType);
case E_BLOCK_MELON: return new cBlockMelonHandler (a_BlockType);
case E_BLOCK_MELON_STEM: return new cBlockStemsHandler (a_BlockType);
@@ -249,11 +249,11 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_NETHER_PORTAL: return new cBlockPortalHandler (a_BlockType);
case E_BLOCK_NETHER_WART: return new cBlockNetherWartHandler (a_BlockType);
case E_BLOCK_NETHER_QUARTZ_ORE: return new cBlockOreHandler (a_BlockType);
- case E_BLOCK_NEW_LEAVES: return new cBlockNewLeavesHandler (a_BlockType);
+ case E_BLOCK_NEW_LEAVES: return new cBlockLeavesHandler (a_BlockType);
case E_BLOCK_NEW_LOG: return new cBlockSidewaysHandler (a_BlockType);
- case E_BLOCK_NOTE_BLOCK: return new cBlockNoteHandler (a_BlockType);
+ case E_BLOCK_NOTE_BLOCK: return new cBlockEntityHandler (a_BlockType);
case E_BLOCK_PISTON: return new cBlockPistonHandler (a_BlockType);
- case E_BLOCK_PISTON_EXTENSION: return new cBlockPistonHeadHandler ( );
+ case E_BLOCK_PISTON_EXTENSION: return new cBlockPistonHeadHandler;
case E_BLOCK_PLANKS: return new cBlockPlanksHandler (a_BlockType);
case E_BLOCK_POTATOES: return new cBlockCropsHandler (a_BlockType);
case E_BLOCK_POWERED_RAIL: return new cBlockRailHandler (a_BlockType);
@@ -275,7 +275,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_SAND: return new cBlockSandHandler (a_BlockType);
case E_BLOCK_SANDSTONE_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_SAPLING: return new cBlockSaplingHandler (a_BlockType);
- case E_BLOCK_SIGN_POST: return new cBlockSignHandler (a_BlockType);
+ case E_BLOCK_SIGN_POST: return new cBlockSignPostHandler (a_BlockType);
case E_BLOCK_SNOW: return new cBlockSnowHandler (a_BlockType);
case E_BLOCK_SPRUCE_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_STAINED_GLASS: return new cBlockGlassHandler (a_BlockType);
@@ -293,10 +293,11 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_TORCH: return new cBlockTorchHandler (a_BlockType);
case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType);
case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType);
+ case E_BLOCK_TRAPPED_CHEST: return new cBlockChestHandler (a_BlockType);
case E_BLOCK_TRIPWIRE: return new cBlockTripwireHandler (a_BlockType);
case E_BLOCK_TRIPWIRE_HOOK: return new cBlockTripwireHookHandler (a_BlockType);
case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType);
- case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType); // TODO: This needs a special handler
+ case E_BLOCK_WALLSIGN: return new cBlockWallSignHandler (a_BlockType);
case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType);
case E_BLOCK_WOODEN_BUTTON: return new cBlockButtonHandler (a_BlockType);
case E_BLOCK_WOODEN_DOOR: return new cBlockDoorHandler (a_BlockType);
@@ -326,7 +327,7 @@ cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
bool cBlockHandler::GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
)
@@ -406,39 +407,6 @@ void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, int a_Bl
-
-void cBlockHandler::OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
-{
-}
-
-
-
-
-
-void cBlockHandler::OnDigging(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
-{
-}
-
-
-
-
-
-void cBlockHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
-{
-}
-
-
-
-
-
-void cBlockHandler::OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
-{
-}
-
-
-
-
-
void cBlockHandler::ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta)
{
// Setting the meta to a_BlockMeta keeps most textures. The few other blocks have to override this.
@@ -449,11 +417,23 @@ void cBlockHandler::ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta)
-void cBlockHandler::DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ)
+void cBlockHandler::DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_CanDrop, bool a_DropVerbatim)
{
cItems Pickups;
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- ConvertToPickups(Pickups, Meta);
+
+ if (a_CanDrop)
+ {
+ if (!a_DropVerbatim)
+ {
+ ConvertToPickups(Pickups, Meta);
+ }
+ else
+ {
+ // TODO: Add a proper overridable function for this
+ Pickups.Add(m_BlockType, 1, Meta);
+ }
+ }
// Allow plugins to modify the pickups:
a_BlockPluginInterface.CallHookBlockToPickups(a_Digger, a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta, Pickups);
diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h
index fb6cae729..de90ce55b 100644
--- a/src/Blocks/BlockHandler.h
+++ b/src/Blocks/BlockHandler.h
@@ -30,14 +30,14 @@ public:
/// Note that the coords are chunk-relative!
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
- /** Called before a block is placed into a world.
+ /** Called before a block is placed into a world.
The handler should return true to allow placement, false to refuse.
Also, the handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block.
Called by cItemHandler::GetPlacementBlockTypeMeta() if the item is a block
*/
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
);
@@ -47,8 +47,8 @@ public:
/// Called by cClientHandle::HandlePlaceBlock() after the player has placed a new block. Called after OnPlaced().
virtual void OnPlacedByPlayer(
- cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
);
@@ -60,25 +60,29 @@ public:
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ);
/// Called when a direct neighbor of this block has been changed (The position is the own position, not the neighbor position)
- virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ);
+ virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) {}
/// Notifies all neighbors of the given block about a change
static void NeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ);
/// Called while the player diggs the block.
- virtual void OnDigging(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ);
+ virtual void OnDigging(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) {}
/// Called if the user right clicks the block and the block is useable
- virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
+ virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) {}
- /** Called when a Right Click to this Block is cancelled */
- virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace);
+ /** Called when a right click to this block is cancelled */
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) {}
/// <summary>Called when the item is mined to convert it into pickups. Pickups may specify multiple items. Appends items to a_Pickups, preserves its original contents</summary>
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta);
- /// Handles the dropping of a block based on what ConvertToDrops() returns. This will not destroy the block. a_Digger is the entity causing the drop; it may be NULL
- virtual void DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ);
+ /** Handles the dropping, but not destruction, of a block based on what ConvertTo(Verbatim)Pickups() returns, including the spawning of pickups and alertion of plugins
+ @param a_Digger The entity causing the drop; it may be NULL
+ @param a_CanDrop Informs the handler whether the block should be dropped at all. One example when this is false is when stone is destroyed by hand
+ @param a_DropVerbatim Calls ConvertToVerbatimPickups() instead of its counterpart, meaning the block itself is dropped by default (due to a speical tool or enchantment)
+ */
+ virtual void DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_CanDrop = true, bool a_DropVerbatim = false);
/// Returns step sound name of block
virtual const char * GetStepSound(void);
@@ -90,7 +94,7 @@ public:
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta);
/** Checks if the block can be placed at this point.
- Default: CanBeAt(...)
+ Default: CanBeAt(...)
NOTE: This call doesn't actually place the block
*/
// virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
@@ -98,27 +102,27 @@ public:
/// Called to check whether this block supports a rclk action. If it returns true, OnUse() is called
virtual bool IsUseable(void);
- /** Indicates whether the client will click through this block.
+ /** Indicates whether the client will click through this block.
For example digging a fire will hit the block below the fire so fire is clicked through
*/
virtual bool IsClickedThrough(void);
- /** Checks if the player can build "inside" this block.
+ /** Checks if the player can build "inside" this block.
For example blocks placed "on" snow will be placed at the same position. So: Snow ignores Build collision
*/
virtual bool DoesIgnoreBuildCollision(void);
/// <summary>Similar to DoesIgnoreBuildCollision(void), but is used for cases where block meta/player item-in-hand is needed to determine collision (thin snow)</summary>
- virtual bool DoesIgnoreBuildCollision(cPlayer *, NIBBLETYPE a_Meta)
- {
+ virtual bool DoesIgnoreBuildCollision(cPlayer *, NIBBLETYPE a_Meta)
+ {
UNUSED(a_Meta);
- return DoesIgnoreBuildCollision();
+ return DoesIgnoreBuildCollision();
}
/// <summary>Returns if this block drops if it gets destroyed by an unsuitable situation. Default: true</summary>
virtual bool DoesDropOnUnsuitable(void);
- /** Called when one of the neighbors gets set; equivalent to MC block update.
+ /** Called when one of the neighbors gets set; equivalent to MC block update.
By default drops if position no more suitable (CanBeAt(), DoesDropOnUnsuitable(), Drop()),
and wakes up all simulators on the block.
*/
diff --git a/src/Blocks/BlockHayBale.h b/src/Blocks/BlockHayBale.h
index 5b646e264..3c6472adb 100644
--- a/src/Blocks/BlockHayBale.h
+++ b/src/Blocks/BlockHayBale.h
@@ -1,7 +1,6 @@
#pragma once
-#include "BlockHandler.h"
#include "BlockSideways.h"
diff --git a/src/Blocks/BlockHopper.h b/src/Blocks/BlockHopper.h
index a882bb077..4a5d32dd5 100644
--- a/src/Blocks/BlockHopper.h
+++ b/src/Blocks/BlockHopper.h
@@ -19,7 +19,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Blocks/BlockIce.h b/src/Blocks/BlockIce.h
index 8dfe7ddac..c38630fe3 100644
--- a/src/Blocks/BlockIce.h
+++ b/src/Blocks/BlockIce.h
@@ -24,12 +24,22 @@ public:
}
- virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual void OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
{
- // TODO: Ice destroyed with air below it should turn into air instead of water
+ if (a_Player->IsGameModeCreative() || (a_BlockY <= 0))
+ {
+ return;
+ }
+
+ BLOCKTYPE BlockBelow = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
+ if (!cBlockInfo::FullyOccupiesVoxel(BlockBelow) && !IsBlockLiquid(BlockBelow))
+ {
+ return;
+ }
+
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_WATER, 0);
// This is called later than the real destroying of this ice block
- }
+ }
} ;
diff --git a/src/Blocks/BlockLadder.h b/src/Blocks/BlockLadder.h
index a605edf3f..284d1d732 100644
--- a/src/Blocks/BlockLadder.h
+++ b/src/Blocks/BlockLadder.h
@@ -3,24 +3,26 @@
#include "BlockHandler.h"
#include "../World.h"
+#include "ClearMetaOnDrop.h"
class cBlockLadderHandler :
- public cMetaRotator<cBlockHandler, 0x07, 0x02, 0x05, 0x03, 0x04>
+ public cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x07, 0x02, 0x05, 0x03, 0x04> >
{
+ typedef cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x07, 0x02, 0x05, 0x03, 0x04> > super;
public:
cBlockLadderHandler(BLOCKTYPE a_BlockType)
- : cMetaRotator<cBlockHandler, 0x07, 0x02, 0x05, 0x03, 0x04>(a_BlockType)
+ : super(a_BlockType)
{
- }
+ }
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -41,21 +43,27 @@ public:
}
- static NIBBLETYPE DirectionToMetaData(eBlockFace a_Direction) // tolua_export
- { // tolua_export
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ a_Pickups.Add(m_BlockType, 1, 0); // Reset meta
+ }
+
+
+ static NIBBLETYPE DirectionToMetaData(eBlockFace a_Direction)
+ {
switch (a_Direction)
{
case BLOCK_FACE_ZM: return 0x2;
case BLOCK_FACE_ZP: return 0x3;
case BLOCK_FACE_XM: return 0x4;
case BLOCK_FACE_XP: return 0x5;
- default: return 0x2;
+ default: return 0x2;
}
- } // tolua_export
+ }
- static eBlockFace MetaDataToDirection(NIBBLETYPE a_MetaData) // tolua_export
- { // tolua_export
+ static eBlockFace MetaDataToDirection(NIBBLETYPE a_MetaData)
+ {
switch (a_MetaData)
{
case 0x2: return BLOCK_FACE_ZM;
@@ -64,10 +72,10 @@ public:
case 0x5: return BLOCK_FACE_XP;
default: return BLOCK_FACE_ZM;
}
- } // tolua_export
+ }
- /// Finds a suitable Direction for the Ladder. Returns BLOCK_FACE_BOTTOM on failure
+ /** Finds a suitable Direction for the Ladder. Returns BLOCK_FACE_BOTTOM on failure */
static eBlockFace FindSuitableBlockFace(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
{
for (int FaceInt = BLOCK_FACE_ZM; FaceInt <= BLOCK_FACE_XP; FaceInt++)
@@ -95,7 +103,7 @@ public:
}
- virtual bool CanBeAt(cChunkInterface & a_ChunkInterface,int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
+ virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
// TODO: Use AdjustCoordsByMeta(), then cChunk::UnboundedRelGetBlock() and finally some comparison
eBlockFace BlockFace = MetaDataToDirection(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
diff --git a/src/Blocks/BlockLeaves.h b/src/Blocks/BlockLeaves.h
index 495e849fa..972dd6232 100644
--- a/src/Blocks/BlockLeaves.h
+++ b/src/Blocks/BlockLeaves.h
@@ -11,7 +11,7 @@
// Leaves can be this many blocks that away (inclusive) from the log not to decay
#define LEAVES_CHECK_DISTANCE 6
-#define PROCESS_NEIGHBOR(x,y,z) \
+#define PROCESS_NEIGHBOR(x, y, z) \
switch (a_Area.GetBlockType(x, y, z)) \
{ \
case E_BLOCK_LEAVES: a_Area.SetBlockType(x, y, z, (BLOCKTYPE)(E_BLOCK_SPONGE + i + 1)); break; \
@@ -40,14 +40,20 @@ public:
{
cFastRandom rand;
- // Only the first 2 bits contain the display information, the others are for growing
+ // Old leaves - 3 bits contain display; new leaves - 1st bit, shifted left two for saplings to understand
if (rand.NextInt(6) == 0)
{
- a_Pickups.push_back(cItem(E_BLOCK_SAPLING, 1, a_BlockMeta & 3));
+ a_Pickups.push_back(
+ cItem(
+ E_BLOCK_SAPLING,
+ 1,
+ (m_BlockType == E_BLOCK_LEAVES) ? (a_BlockMeta & 0x03) : (2 << (a_BlockMeta & 0x01))
+ )
+ );
}
// 1 % chance of dropping an apple, if the leaves' type is Apple Leaves
- if ((a_BlockMeta & 3) == E_META_LEAVES_APPLE)
+ if ((m_BlockType == E_BLOCK_LEAVES) && ((a_BlockMeta & 0x03) == E_META_LEAVES_APPLE))
{
if (rand.NextInt(101) == 0)
{
@@ -55,28 +61,12 @@ public:
}
}
}
-
-
- void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
- {
- cBlockHandler::OnDestroyed(a_ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ);
-
- // 0.5% chance of dropping an apple, if the leaves' type is Apple Leaves:
- NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- cFastRandom rand;
- if (((Meta & 3) == E_META_LEAVES_APPLE) && (rand.NextInt(201) == 100))
- {
- cItems Drops;
- Drops.push_back(cItem(E_ITEM_RED_APPLE, 1, 0));
- a_WorldInterface.SpawnItemPickups(Drops, a_BlockX, a_BlockY, a_BlockZ);
- }
- }
virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
{
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x7); // Unset 0x8 bit so it gets checked for decay
+ a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x7); // Unset 0x8 bit so it gets checked for decay
}
@@ -100,10 +90,10 @@ public:
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
cBlockArea Area;
if (!Area.Read(
- a_Chunk.GetWorld(),
- BlockX - LEAVES_CHECK_DISTANCE, BlockX + LEAVES_CHECK_DISTANCE,
- a_RelY - LEAVES_CHECK_DISTANCE, a_RelY + LEAVES_CHECK_DISTANCE,
- BlockZ - LEAVES_CHECK_DISTANCE, BlockZ + LEAVES_CHECK_DISTANCE,
+ a_Chunk.GetWorld(),
+ BlockX - LEAVES_CHECK_DISTANCE, BlockX + LEAVES_CHECK_DISTANCE,
+ a_RelY - LEAVES_CHECK_DISTANCE, a_RelY + LEAVES_CHECK_DISTANCE,
+ BlockZ - LEAVES_CHECK_DISTANCE, BlockZ + LEAVES_CHECK_DISTANCE,
cBlockArea::baTypes)
)
{
diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h
index 4e745d413..4316fd06b 100644
--- a/src/Blocks/BlockLever.h
+++ b/src/Blocks/BlockLever.h
@@ -24,7 +24,7 @@ public:
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
a_WorldInterface.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
- a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
+ a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
}
@@ -43,7 +43,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Blocks/BlockLilypad.h b/src/Blocks/BlockLilypad.h
index 2dd4ec768..53277caa5 100644
--- a/src/Blocks/BlockLilypad.h
+++ b/src/Blocks/BlockLilypad.h
@@ -8,18 +8,14 @@
class cBlockLilypadHandler :
- public cBlockHandler
+ public cClearMetaOnDrop<cBlockHandler>
{
+ typedef cClearMetaOnDrop<cBlockHandler> super;
public:
- cBlockLilypadHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
- {
- }
-
- virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+
+ cBlockLilypadHandler(BLOCKTYPE a_BlockType) :
+ super(a_BlockType)
{
- // Reset meta to zero
- a_Pickups.push_back(cItem(E_BLOCK_LILY_PAD, 1, 0));
}
};
diff --git a/src/Blocks/BlockMelon.h b/src/Blocks/BlockMelon.h
index 2f7d9a461..60202d66e 100644
--- a/src/Blocks/BlockMelon.h
+++ b/src/Blocks/BlockMelon.h
@@ -19,8 +19,8 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- MTRand r1;
- a_Pickups.push_back(cItem(E_ITEM_MELON_SLICE, (char)(3 + r1.randInt(4)), 0));
+ cFastRandom Random;
+ a_Pickups.push_back(cItem(E_ITEM_MELON_SLICE, (char)(3 + Random.NextInt(5)), 0));
}
diff --git a/src/Blocks/BlockMobHead.h b/src/Blocks/BlockMobHead.h
index 301386568..ff1ef97bf 100644
--- a/src/Blocks/BlockMobHead.h
+++ b/src/Blocks/BlockMobHead.h
@@ -193,8 +193,8 @@ public:
}
virtual void OnPlacedByPlayer(
- cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
) override
diff --git a/src/Blocks/BlockNewLeaves.h b/src/Blocks/BlockNewLeaves.h
deleted file mode 100644
index 5a267e8c6..000000000
--- a/src/Blocks/BlockNewLeaves.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#pragma once
-#include "BlockHandler.h"
-#include "BlockLeaves.h"
-#include "../World.h"
-
-
-
-
-
-
-class cBlockNewLeavesHandler :
- public cBlockLeavesHandler
-{
-public:
- cBlockNewLeavesHandler(BLOCKTYPE a_BlockType)
- : cBlockLeavesHandler(a_BlockType)
- {
- }
-
-
- virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
- {
- MTRand rand;
-
- // Only the first 2 bits contain the display information, the others are for growing
- if (rand.randInt(5) == 0)
- {
- a_Pickups.push_back(cItem(E_BLOCK_SAPLING, 1, (a_BlockMeta & 3) + 4));
- }
- }
-
-
- void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
- {
- cBlockHandler::OnDestroyed(a_ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ);
- }
-} ;
-
-
-
-
-
diff --git a/src/Blocks/BlockNote.h b/src/Blocks/BlockNote.h
deleted file mode 100644
index fef38d845..000000000
--- a/src/Blocks/BlockNote.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "BlockHandler.h"
-#include "BlockEntity.h"
-
-class cBlockNoteHandler : public cBlockEntityHandler
-{
-public:
- cBlockNoteHandler(BLOCKTYPE a_BlockType)
- : cBlockEntityHandler(a_BlockType)
- {
- }
-
-};
diff --git a/src/Blocks/BlockOre.h b/src/Blocks/BlockOre.h
index 9684dbb19..0067d475f 100644
--- a/src/Blocks/BlockOre.h
+++ b/src/Blocks/BlockOre.h
@@ -2,7 +2,6 @@
#pragma once
#include "BlockHandler.h"
-#include "../MersenneTwister.h"
#include "../World.h"
@@ -20,58 +19,41 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- short ItemType = m_BlockType;
- char Count = 1;
- short Meta = 0;
-
- MTRand r1;
+ cFastRandom Random;
+
switch (m_BlockType)
{
case E_BLOCK_LAPIS_ORE:
{
- ItemType = E_ITEM_DYE;
- Count = 4 + (char)r1.randInt(4);
- Meta = 4;
+ a_Pickups.push_back(cItem(E_ITEM_DYE, (char)(4 + Random.NextInt(5)), 4));
break;
}
case E_BLOCK_REDSTONE_ORE:
case E_BLOCK_REDSTONE_ORE_GLOWING:
{
- Count = 4 + (char)r1.randInt(1);
- break;
- }
- default:
- {
- Count = 1;
+ a_Pickups.push_back(cItem(E_ITEM_REDSTONE_DUST, (char)(4 + Random.NextInt(2)), 0));
break;
}
- }
-
- switch (m_BlockType)
- {
case E_BLOCK_DIAMOND_ORE:
{
- ItemType = E_ITEM_DIAMOND;
- break;
- }
- case E_BLOCK_REDSTONE_ORE:
- case E_BLOCK_REDSTONE_ORE_GLOWING:
- {
- ItemType = E_ITEM_REDSTONE_DUST;
+ a_Pickups.push_back(cItem(E_ITEM_DIAMOND));
break;
}
case E_BLOCK_EMERALD_ORE:
{
- ItemType = E_ITEM_EMERALD;
+ a_Pickups.push_back(cItem(E_ITEM_EMERALD));
break;
}
case E_BLOCK_COAL_ORE:
{
- ItemType = E_ITEM_COAL;
+ a_Pickups.push_back(cItem(E_ITEM_COAL));
break;
}
+ default:
+ {
+ ASSERT(!"Unhandled ore!");
+ }
}
- a_Pickups.push_back(cItem(ItemType, Count, Meta));
}
} ;
diff --git a/src/Blocks/BlockPiston.cpp b/src/Blocks/BlockPiston.cpp
index faf639312..164967621 100644
--- a/src/Blocks/BlockPiston.cpp
+++ b/src/Blocks/BlockPiston.cpp
@@ -62,7 +62,7 @@ void cBlockPistonHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorld
bool cBlockPistonHandler::GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
)
@@ -85,7 +85,7 @@ int cBlockPistonHandler::FirstPassthroughBlock(int a_PistonX, int a_PistonY, int
NIBBLETYPE currMeta;
AddPistonDir(a_PistonX, a_PistonY, a_PistonZ, pistonmeta, 1);
a_World->GetBlockTypeMeta(a_PistonX, a_PistonY, a_PistonZ, currBlock, currMeta);
- if (CanBreakPush(currBlock))
+ if (cBlockInfo::IsPistonBreakable(currBlock))
{
// This block breaks when pushed, extend up to here
return ret;
@@ -124,7 +124,7 @@ void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ,
}
a_World->BroadcastBlockAction(a_BlockX, a_BlockY, a_BlockZ, 0, pistonMeta, pistonBlock);
- a_World->BroadcastSoundEffect("tile.piston.out", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.7f);
+ a_World->BroadcastSoundEffect("tile.piston.out", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 0.5f, 0.7f);
// Drop the breakable block in the line, if appropriate:
AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, dist + 1); // "a_Block" now at the breakable / empty block
@@ -198,7 +198,7 @@ void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ
AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta & ~(8));
a_World->BroadcastBlockAction(a_BlockX, a_BlockY, a_BlockZ, 1, pistonMeta & ~(8), pistonBlock);
- a_World->BroadcastSoundEffect("tile.piston.in", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.7f);
+ a_World->BroadcastSoundEffect("tile.piston.in", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 0.5f, 0.7f);
AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, 1);
// Retract the extension, pull block if appropriate
@@ -235,7 +235,7 @@ void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBlockPistonHeadHandler:
cBlockPistonHeadHandler::cBlockPistonHeadHandler(void) :
@@ -262,7 +262,7 @@ void cBlockPistonHeadHandler::OnDestroyedByPlayer(cChunkInterface & a_ChunkInter
a_ChunkInterface.DigBlock(a_WorldInterface, newX, newY, newZ);
if (a_Player->IsGameModeCreative())
{
- return; // No pickups if creative
+ return; // No pickups if creative
}
cItems Pickups;
diff --git a/src/Blocks/BlockPiston.h b/src/Blocks/BlockPiston.h
index e6fa48e54..0bec603e3 100644
--- a/src/Blocks/BlockPiston.h
+++ b/src/Blocks/BlockPiston.h
@@ -17,7 +17,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override;
@@ -75,7 +75,7 @@ public:
return BLOCK_FACE_NONE;
}
}
- }
+ }
static void ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
static void RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
@@ -94,7 +94,7 @@ private:
switch (a_BlockType)
{
case E_BLOCK_ANVIL:
- case E_BLOCK_BED:
+ case E_BLOCK_BEACON:
case E_BLOCK_BEDROCK:
case E_BLOCK_BREWING_STAND:
case E_BLOCK_CHEST:
@@ -104,6 +104,7 @@ private:
case E_BLOCK_ENCHANTMENT_TABLE:
case E_BLOCK_END_PORTAL:
case E_BLOCK_END_PORTAL_FRAME:
+ // Notice the lack of an E_BLOCK_ENDER_CHEST here; its because ender chests can totally be pushed/pulled in MCS :)
case E_BLOCK_FURNACE:
case E_BLOCK_LIT_FURNACE:
case E_BLOCK_HOPPER:
@@ -113,6 +114,7 @@ private:
case E_BLOCK_NOTE_BLOCK:
case E_BLOCK_OBSIDIAN:
case E_BLOCK_PISTON_EXTENSION:
+ case E_BLOCK_TRAPPED_CHEST:
{
return false;
}
@@ -126,26 +128,12 @@ private:
return true;
}
- /// Returns true if the specified block can be pushed by a piston and broken / replaced
- static inline bool CanBreakPush(BLOCKTYPE a_BlockType) { return cBlockInfo::IsPistonBreakable(a_BlockType); }
-
/// Returns true if the specified block can be pulled by a sticky piston
static inline bool CanPull(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
- switch (a_BlockType)
- {
- case E_BLOCK_LAVA:
- case E_BLOCK_STATIONARY_LAVA:
- case E_BLOCK_STATIONARY_WATER:
- case E_BLOCK_WATER:
- {
- return false;
- }
- }
-
- if (CanBreakPush(a_BlockType))
+ if (cBlockInfo::IsPistonBreakable(a_BlockType))
{
- return false; // CanBreakPush returns true, but we need false to prevent pulling
+ return false; // CanBreakPush returns true, but we need false to prevent pulling
}
return CanPush(a_BlockType, a_BlockMeta);
diff --git a/src/Blocks/BlockPlanks.h b/src/Blocks/BlockPlanks.h
index 2a99a455e..4c5bb4860 100644
--- a/src/Blocks/BlockPlanks.h
+++ b/src/Blocks/BlockPlanks.h
@@ -18,14 +18,13 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
a_BlockType = m_BlockType;
- NIBBLETYPE Meta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage);
- a_BlockMeta = Meta;
+ a_BlockMeta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage);
return true;
}
diff --git a/src/Blocks/BlockPortal.h b/src/Blocks/BlockPortal.h
index 3b8030028..8fac2a126 100644
--- a/src/Blocks/BlockPortal.h
+++ b/src/Blocks/BlockPortal.h
@@ -19,7 +19,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -36,7 +36,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- return; // No pickups
+ // No pickups
}
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
@@ -47,17 +47,17 @@ public:
return;
}
- int PosX = a_Chunk.GetPosX() * 16 + a_RelX;
- int PosZ = a_Chunk.GetPosZ() * 16 + a_RelZ;
+ int PosX = a_Chunk.GetPosX() * cChunkDef::Width + a_RelX;
+ int PosZ = a_Chunk.GetPosZ() * cChunkDef::Width + a_RelZ;
a_WorldInterface.SpawnMob(PosX, a_RelY, PosZ, cMonster::mtZombiePigman);
}
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- if ((a_RelY - 1 < 0) || (a_RelY + 1 > cChunkDef::Height))
+ if ((a_RelY <= 0) || (a_RelY >= cChunkDef::Height))
{
- return false; // In case someone places a portal with meta 1 or 2 at boundaries, and server tries to get invalid coords at Y - 1 or Y + 1
+ return false; // In case someone places a portal with meta 1 or 2 at boundaries, and server tries to get invalid coords at Y - 1 or Y + 1
}
switch (a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ))
@@ -70,7 +70,7 @@ public:
} PortalCheck[] =
{
{ 0, 1, 0},
- { 0,-1, 0},
+ { 0, -1, 0},
{ 1, 0, 0},
{-1, 0, 0},
} ;
@@ -95,7 +95,7 @@ public:
} PortalCheck[] =
{
{ 0, 1, 0},
- { 0,-1, 0},
+ { 0, -1, 0},
{ 0, 0, -1},
{ 0, 0, 1},
} ;
diff --git a/src/Blocks/BlockPressurePlate.h b/src/Blocks/BlockPressurePlate.h
index adec36eb6..a5c34a776 100644
--- a/src/Blocks/BlockPressurePlate.h
+++ b/src/Blocks/BlockPressurePlate.h
@@ -17,7 +17,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- // Reset meta to 0
+ // Reset meta to zero
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
@@ -29,7 +29,7 @@ public:
}
BLOCKTYPE BlockBelow = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ);
- return ((BlockBelow == E_BLOCK_FENCE_GATE) || (BlockBelow == E_BLOCK_FENCE) || cBlockInfo::IsSolid(BlockBelow));
+ return (cBlockInfo::IsSolid(BlockBelow));
}
} ;
diff --git a/src/Blocks/BlockPumpkin.h b/src/Blocks/BlockPumpkin.h
index ac2b9817a..15ac80fd7 100644
--- a/src/Blocks/BlockPumpkin.h
+++ b/src/Blocks/BlockPumpkin.h
@@ -6,13 +6,16 @@
class cBlockPumpkinHandler :
- public cMetaRotator<cBlockHandler, 0x07, 0x02, 0x03, 0x00, 0x01, false>
+ public cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x07, 0x02, 0x03, 0x00, 0x01, false> >
{
+ typedef cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x07, 0x02, 0x03, 0x00, 0x01, false> > super;
public:
- cBlockPumpkinHandler(BLOCKTYPE a_BlockType)
- : cMetaRotator<cBlockHandler, 0x07, 0x02, 0x03, 0x00, 0x01, false>(a_BlockType)
+
+ cBlockPumpkinHandler(BLOCKTYPE a_BlockType) :
+ super(a_BlockType)
{
}
+
virtual void OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
{
@@ -73,14 +76,14 @@ public:
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
// Spawn the golem:
- a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtIronGolem);
+ a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtIronGolem);
}
}
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Blocks/BlockQuartz.h b/src/Blocks/BlockQuartz.h
index 9cc51490f..edc4fb9c5 100644
--- a/src/Blocks/BlockQuartz.h
+++ b/src/Blocks/BlockQuartz.h
@@ -18,14 +18,15 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
a_BlockType = m_BlockType;
NIBBLETYPE Meta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage);
- if (Meta != E_META_QUARTZ_PILLAR) // Check if the block is a pillar block.
+
+ if (Meta != E_META_QUARTZ_PILLAR) // Check if the block is a pillar block.
{
a_BlockMeta = Meta;
return true;
@@ -42,25 +43,25 @@ public:
case BLOCK_FACE_YM:
case BLOCK_FACE_YP:
{
- return a_QuartzMeta; // Top or bottom, just return original
+ return a_QuartzMeta; // Top or bottom, just return original
}
case BLOCK_FACE_ZP:
case BLOCK_FACE_ZM:
{
- return 0x4; // North or south
+ return 0x4; // North or south
}
case BLOCK_FACE_XP:
case BLOCK_FACE_XM:
{
- return 0x3; // East or west
+ return 0x3; // East or west
}
default:
{
ASSERT(!"Unhandled block face!");
- return a_QuartzMeta; // No idea, give a special meta (all sides the same)
+ return a_QuartzMeta; // No idea, give a special meta (all sides the same)
}
}
}
diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h
index 358b5ca11..87ce069ab 100644
--- a/src/Blocks/BlockRail.h
+++ b/src/Blocks/BlockRail.h
@@ -31,7 +31,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -140,7 +140,7 @@ public:
{
NIBBLETYPE Meta = 0;
char RailsCnt = 0;
- bool Neighbors[8]; // 0 - EAST, 1 - WEST, 2 - NORTH, 3 - SOUTH, 4 - EAST UP, 5 - WEST UP, 6 - NORTH UP, 7 - SOUTH UP
+ bool Neighbors[8]; // 0 - EAST, 1 - WEST, 2 - NORTH, 3 - SOUTH, 4 - EAST UP, 5 - WEST UP, 6 - NORTH UP, 7 - SOUTH UP
memset(Neighbors, 0, sizeof(Neighbors));
Neighbors[0] = (IsUnstable(a_ChunkInterface, a_BlockX + 1, a_BlockY, a_BlockZ) || !IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST, E_PURE_DOWN));
Neighbors[1] = (IsUnstable(a_ChunkInterface, a_BlockX - 1, a_BlockY, a_BlockZ) || !IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST, E_PURE_DOWN));
@@ -223,7 +223,7 @@ public:
case E_META_RAIL_ZM_ZP:
{
if (
- IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH, E_PURE_DOWN) ||
+ IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH, E_PURE_DOWN) ||
IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH, E_PURE_DOWN)
)
{
@@ -235,7 +235,7 @@ public:
case E_META_RAIL_XM_XP:
{
if (
- IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST, E_PURE_DOWN) ||
+ IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST, E_PURE_DOWN) ||
IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST, E_PURE_DOWN)
)
{
@@ -247,7 +247,7 @@ public:
case E_META_RAIL_ASCEND_XP:
{
if (
- IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_EAST) ||
+ IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_EAST) ||
IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST)
)
{
@@ -259,7 +259,7 @@ public:
case E_META_RAIL_ASCEND_XM:
{
if (
- IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST) ||
+ IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST) ||
IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_WEST)
)
{
@@ -271,7 +271,7 @@ public:
case E_META_RAIL_ASCEND_ZM:
{
if (
- IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NORTH) ||
+ IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NORTH) ||
IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH)
)
{
@@ -283,7 +283,7 @@ public:
case E_META_RAIL_ASCEND_ZP:
{
if (
- IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH) ||
+ IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH) ||
IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_SOUTH)
)
{
@@ -295,7 +295,7 @@ public:
case E_META_RAIL_CURVED_ZP_XP:
{
if (
- IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH) ||
+ IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH) ||
IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST)
)
{
@@ -307,7 +307,7 @@ public:
case E_META_RAIL_CURVED_ZP_XM:
{
if (
- IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH) ||
+ IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH) ||
IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST)
)
{
@@ -319,7 +319,7 @@ public:
case E_META_RAIL_CURVED_ZM_XM:
{
if (
- IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH) ||
+ IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH) ||
IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST)
)
{
@@ -331,7 +331,7 @@ public:
case E_META_RAIL_CURVED_ZM_XP:
{
if (
- IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH) ||
+ IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH) ||
IsNotConnected(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST)
)
{
diff --git a/src/Blocks/BlockRedstone.h b/src/Blocks/BlockRedstone.h
index a898c9acb..37d61ed73 100644
--- a/src/Blocks/BlockRedstone.h
+++ b/src/Blocks/BlockRedstone.h
@@ -26,8 +26,8 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- // Reset meta to 0
- a_Pickups.push_back(cItem(E_ITEM_REDSTONE_DUST, 1));
+ // Reset meta to zero
+ a_Pickups.push_back(cItem(E_ITEM_REDSTONE_DUST, 1, 0));
}
} ;
diff --git a/src/Blocks/BlockRedstoneRepeater.h b/src/Blocks/BlockRedstoneRepeater.h
index fe6cd21b9..4b18add12 100644
--- a/src/Blocks/BlockRedstoneRepeater.h
+++ b/src/Blocks/BlockRedstoneRepeater.h
@@ -23,7 +23,7 @@ public:
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
- ) override
+ ) override
{
a_BlockType = m_BlockType;
a_BlockMeta = RepeaterRotationToMetaData(a_Player->GetYaw());
@@ -46,7 +46,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- // Reset meta to 0
+ // Reset meta to zero
a_Pickups.push_back(cItem(E_ITEM_REDSTONE_REPEATER, 1, 0));
}
@@ -59,7 +59,7 @@ public:
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR));
+ return ((a_RelY > 0) && cBlockInfo::IsSolid(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)));
}
@@ -71,7 +71,7 @@ public:
inline static NIBBLETYPE RepeaterRotationToMetaData(double a_Rotation)
{
- a_Rotation += 90 + 45; // So its not aligned with axis
+ a_Rotation += 90 + 45; // So its not aligned with axis
if (a_Rotation > 360)
{
a_Rotation -= 360;
diff --git a/src/Blocks/BlockSapling.h b/src/Blocks/BlockSapling.h
index 3d925029a..de28273d5 100644
--- a/src/Blocks/BlockSapling.h
+++ b/src/Blocks/BlockSapling.h
@@ -20,8 +20,8 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- // Only the first 2 bits contain the display information, the others are for growing
- a_Pickups.push_back(cItem(E_BLOCK_SAPLING, 1, a_BlockMeta & 3));
+ // Only the first 2 bits contain the display information and the 4th bit is for the growth indicator, but, we use 0x07 for forward compatibility
+ a_Pickups.push_back(cItem(E_BLOCK_SAPLING, 1, a_BlockMeta & 0x07));
}
diff --git a/src/Blocks/BlockSideways.h b/src/Blocks/BlockSideways.h
index d67c3aa24..f5f10899d 100644
--- a/src/Blocks/BlockSideways.h
+++ b/src/Blocks/BlockSideways.h
@@ -18,7 +18,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -32,36 +32,36 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- a_Pickups.Add(m_BlockType, 1, a_BlockMeta & 0x3);
+ a_Pickups.Add(m_BlockType, 1, a_BlockMeta & 0x3); // Reset meta
}
- inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace, NIBBLETYPE a_WoodMeta)
+ inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace, NIBBLETYPE a_Meta)
{
switch (a_BlockFace)
{
case BLOCK_FACE_YM:
case BLOCK_FACE_YP:
{
- return a_WoodMeta; // Top or bottom, just return original
+ return a_Meta; // Top or bottom, just return original
}
case BLOCK_FACE_ZP:
case BLOCK_FACE_ZM:
{
- return a_WoodMeta | 0x8; // North or south
+ return a_Meta | 0x8; // North or south
}
case BLOCK_FACE_XP:
case BLOCK_FACE_XM:
{
- return a_WoodMeta | 0x4; // East or west
+ return a_Meta | 0x4; // East or west
}
default:
{
ASSERT(!"Unhandled block face!");
- return a_WoodMeta | 0xC; // No idea, give a special meta (all sides bark)
+ return a_Meta | 0xC; // No idea, give a special meta
}
}
}
diff --git a/src/Blocks/BlockSign.h b/src/Blocks/BlockSignPost.h
index f5630bdb0..d0cc760b0 100644
--- a/src/Blocks/BlockSign.h
+++ b/src/Blocks/BlockSignPost.h
@@ -9,21 +9,23 @@
-class cBlockSignHandler :
+class cBlockSignPostHandler :
public cBlockHandler
{
+ typedef cBlockHandler super;
+
public:
- cBlockSignHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ cBlockSignPostHandler(BLOCKTYPE a_BlockType) :
+ super(a_BlockType)
{
}
-
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
a_Pickups.push_back(cItem(E_ITEM_SIGN, 1, 0));
}
-
+
virtual const char * GetStepSound(void) override
{
@@ -31,6 +33,18 @@ public:
}
+ virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
+ {
+ if (a_RelY <= 0)
+ {
+ return false;
+ }
+ BLOCKTYPE Type = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ);
+
+ return ((Type == E_BLOCK_SIGN_POST) || cBlockInfo::IsSolid(Type));
+ }
+
+
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
a_Rotation += 180 + (180 / 16); // So it's not aligned with axis
@@ -43,23 +57,6 @@ public:
return ((char)a_Rotation) % 16;
}
-
-
- static NIBBLETYPE DirectionToMetaData(eBlockFace a_Direction)
- {
- switch (a_Direction)
- {
- case 0x2: return 0x2;
- case 0x3: return 0x3;
- case 0x4: return 0x4;
- case 0x5: return 0x5;
- default:
- {
- break;
- }
- }
- return 0x2;
- }
virtual void OnPlacedByPlayer(
@@ -84,22 +81,23 @@ public:
return (a_Meta + 12) & 0x0f;
}
+
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
{
- // Mirrors signs over the XY plane (North-South Mirroring)
+ // Mirrors signs over the XY plane (North-South Mirroring)
- // There are 16 meta values which correspond to different directions.
- // These values are equated to angles on a circle; 0x08 = 180 degrees.
+ // There are 16 meta values which correspond to different directions.
+ // These values are equated to angles on a circle; 0x08 = 180 degrees.
return (a_Meta < 0x08) ? (0x08 + a_Meta) : (0x08 - a_Meta);
}
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
{
- // Mirrors signs over the YZ plane (East-West Mirroring)
+ // Mirrors signs over the YZ plane (East-West Mirroring)
- // There are 16 meta values which correspond to different directions.
- // These values are equated to angles on a circle; 0x10 = 360 degrees.
+ // There are 16 meta values which correspond to different directions.
+ // These values are equated to angles on a circle; 0x10 = 360 degrees.
return 0x10 - a_Meta;
}
} ;
diff --git a/src/Blocks/BlockSlab.h b/src/Blocks/BlockSlab.h
index 6c861be86..e67f0e8b3 100644
--- a/src/Blocks/BlockSlab.h
+++ b/src/Blocks/BlockSlab.h
@@ -33,7 +33,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -110,6 +110,18 @@ public:
{
return ((a_BlockType == E_BLOCK_WOODEN_SLAB) || (a_BlockType == E_BLOCK_STONE_SLAB));
}
+
+
+ virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
+ {
+ if ((a_BlockFace == BLOCK_FACE_NONE) || (a_Player->GetEquippedItem().m_ItemType != (short)m_BlockType))
+ {
+ return;
+ }
+
+ // Sends the slab back to the client. It's to refuse a doubleslab placement.
+ a_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, a_Player);
+ }
/// Converts the single-slab blocktype to its equivalent double-slab blocktype
diff --git a/src/Blocks/BlockSnow.h b/src/Blocks/BlockSnow.h
index b21995d3c..977f19a16 100644
--- a/src/Blocks/BlockSnow.h
+++ b/src/Blocks/BlockSnow.h
@@ -19,7 +19,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -33,8 +33,8 @@ public:
if ((BlockBeforePlacement == E_BLOCK_SNOW) && (MetaBeforePlacement < 7))
{
// Only increment if:
- // A snow block was already there (not first time placement) AND
- // Height is smaller than 7, the maximum possible height
+ // - A snow block was already there (not first time placement) AND
+ // - Height is smaller than 7, the maximum possible height
MetaBeforePlacement++;
}
@@ -47,12 +47,12 @@ public:
{
if ((a_Player->GetEquippedItem().m_ItemType == E_BLOCK_SNOW) && (a_Meta < 7))
{
- return true; // If a player is holding a (thin) snow block and it's size can be increased, return collision ignored
+ return true; // If a player is holding a (thin) snow block and it's size can be increased, return collision ignored
}
if (a_Meta == 0)
{
- return true; // If at normal snowfall height (lowest), we ignore collision
+ return true; // If at normal snowfall height (lowest), we ignore collision
}
return false;
diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h
index a49fda5ae..417969a82 100644
--- a/src/Blocks/BlockStairs.h
+++ b/src/Blocks/BlockStairs.h
@@ -16,11 +16,11 @@ public:
{
}
-
-
+
+
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -53,8 +53,8 @@ public:
}
return true;
}
-
-
+
+
virtual const char * GetStepSound(void) override
{
if (
@@ -64,7 +64,7 @@ public:
(m_BlockType == E_BLOCK_ACACIA_WOOD_STAIRS) ||
(m_BlockType == E_BLOCK_BIRCH_WOOD_STAIRS) ||
(m_BlockType == E_BLOCK_DARK_OAK_WOOD_STAIRS)
- )
+ )
{
return "step.wood";
}
@@ -72,20 +72,23 @@ public:
return "step.stone";
}
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- // Reset meta to 0
+ // Reset meta to zero
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
+
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
{
return true;
}
-
+
+
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
- a_Rotation += 90 + 45; // So its not aligned with axis
+ a_Rotation += 90 + 45; // So its not aligned with axis
if (a_Rotation > 360)
{
a_Rotation -= 360;
@@ -108,14 +111,11 @@ public:
}
}
-
virtual NIBBLETYPE MetaMirrorXZ(NIBBLETYPE a_Meta) override
{
// Toggle bit 3:
return (a_Meta & 0x0b) | ((~a_Meta) & 0x04);
}
-
-
} ;
diff --git a/src/Blocks/BlockSugarcane.h b/src/Blocks/BlockSugarcane.h
index 84d3b2e7d..5902c791b 100644
--- a/src/Blocks/BlockSugarcane.h
+++ b/src/Blocks/BlockSugarcane.h
@@ -29,6 +29,7 @@ public:
{
return false;
}
+
switch (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ))
{
case E_BLOCK_DIRT:
diff --git a/src/Blocks/BlockTallGrass.h b/src/Blocks/BlockTallGrass.h
index ba1f2e0f6..9c008f793 100644
--- a/src/Blocks/BlockTallGrass.h
+++ b/src/Blocks/BlockTallGrass.h
@@ -43,8 +43,9 @@ public:
cItems Pickups;
Pickups.Add(E_BLOCK_TALL_GRASS, 1, Meta);
a_WorldInterface.SpawnItemPickups(Pickups, a_BlockX, a_BlockY, a_BlockZ);
+
+ a_Player->UseEquippedItem();
}
- a_Player->UseEquippedItem();
}
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index 44c33c429..df5574d5d 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -19,7 +19,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -28,7 +28,7 @@ public:
if ((a_BlockFace == BLOCK_FACE_TOP) || (a_BlockFace == BLOCK_FACE_BOTTOM))
{
- a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); // Top or bottom faces clicked, find a suitable face
+ a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); // Top or bottom faces clicked, find a suitable face
if (a_BlockFace == BLOCK_FACE_NONE)
{
// Client wouldn't have sent anything anyway, but whatever
@@ -38,10 +38,10 @@ public:
else
{
// Not top or bottom faces, try to preserve whatever face was clicked
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); // Set to clicked block
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); // Set to clicked block
if (!CanBePlacedOn(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ), a_BlockFace))
{
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); // Reset to torch block
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); // Reset to torch block
// Torch couldn't be placed on whatever face was clicked, last ditch resort - find another face
a_BlockFace = FindSuitableFace(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
if (a_BlockFace == BLOCK_FACE_NONE)
@@ -99,7 +99,7 @@ public:
static bool CanBePlacedOn(BLOCKTYPE a_BlockType, eBlockFace a_BlockFace)
{
- if ( !cBlockInfo::FullyOccupiesVoxel(a_BlockType) )
+ if (!cBlockInfo::FullyOccupiesVoxel(a_BlockType))
{
return (a_BlockFace == BLOCK_FACE_TOP); // Allow placement only when torch upright (for glass, etc.); exceptions won't even be sent by client, no need to handle
}
@@ -113,19 +113,20 @@ public:
/// Finds a suitable face to place the torch, returning BLOCK_FACE_NONE on failure
static eBlockFace FindSuitableFace(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- for (int i = BLOCK_FACE_YM; i <= BLOCK_FACE_XP; i++) // Loop through all directions
+ for (int i = BLOCK_FACE_YM; i <= BLOCK_FACE_XP; i++) // Loop through all directions
{
eBlockFace Face = static_cast<eBlockFace>(i);
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, Face, true);
BLOCKTYPE BlockInQuestion = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- if ( // If on a block that can only hold a torch if torch is standing on it, return that face
+ // If on a block that can only hold a torch if torch is standing on it, return that face
+ if (
((BlockInQuestion == E_BLOCK_GLASS) ||
(BlockInQuestion == E_BLOCK_FENCE) ||
(BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
(BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)) &&
(Face == BLOCK_FACE_TOP)
- )
+ )
{
return Face;
}
@@ -158,16 +159,16 @@ public:
(BlockInQuestion == E_BLOCK_FENCE) ||
(BlockInQuestion == E_BLOCK_SOULSAND) ||
(BlockInQuestion == E_BLOCK_MOB_SPAWNER) ||
- (BlockInQuestion == E_BLOCK_END_PORTAL_FRAME) || // Actual vanilla behaviour
+ (BlockInQuestion == E_BLOCK_END_PORTAL_FRAME) || // Actual vanilla behaviour
(BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
(BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)
- )
+ )
{
// Torches can be placed on tops of glass and fences, despite them being 'untorcheable'
// No need to check for upright orientation, it was done when the torch was placed
return true;
}
- else if ( !cBlockInfo::FullyOccupiesVoxel(BlockInQuestion) )
+ else if (!cBlockInfo::FullyOccupiesVoxel(BlockInQuestion))
{
return false;
}
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index 6a36ab874..a6327b5c2 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -23,7 +23,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- // Reset meta to 0
+ // Reset meta to zero
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
@@ -53,7 +53,7 @@ public:
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
- ) override
+ ) override
{
a_BlockType = m_BlockType;
a_BlockMeta = BlockFaceToMetaData(a_BlockFace);
@@ -103,9 +103,10 @@ public:
a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta);
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
- BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
+ BLOCKTYPE BlockIsOn;
+ a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
- return (a_RelY > 0) && cBlockInfo::IsSolid(BlockIsOn);
+ return ((a_RelY > 0) && cBlockInfo::IsSolid(BlockIsOn));
}
};
diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h
index f849fb8ad..4f9d79483 100644
--- a/src/Blocks/BlockTripwireHook.h
+++ b/src/Blocks/BlockTripwireHook.h
@@ -21,10 +21,9 @@ public:
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
- ) override
+ ) override
{
a_BlockType = m_BlockType;
-
a_BlockMeta = DirectionToMetadata(a_BlockFace);
return true;
@@ -56,7 +55,7 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
- // Reset meta to 0
+ // Reset meta to zero
a_Pickups.push_back(cItem(E_BLOCK_TRIPWIRE_HOOK, 1, 0));
}
@@ -66,9 +65,10 @@ public:
a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta);
AddFaceDirection(a_RelX, a_RelY, a_RelZ, MetadataToDirection(Meta), true);
- BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
+ BLOCKTYPE BlockIsOn;
+ a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
- return (a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn);
+ return ((a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn));
}
virtual const char * GetStepSound(void) override
diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h
index 7bb9dc484..578224c61 100644
--- a/src/Blocks/BlockVine.h
+++ b/src/Blocks/BlockVine.h
@@ -18,7 +18,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -44,6 +44,13 @@ public:
}
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ // Reset meta to zero
+ a_Pickups.push_back(cItem(E_BLOCK_VINES, 1, 0));
+ }
+
+
static NIBBLETYPE DirectionToMetaData(char a_BlockFace)
{
switch (a_BlockFace)
@@ -59,7 +66,7 @@ public:
static char MetaDataToDirection(NIBBLETYPE a_MetaData)
{
- switch(a_MetaData)
+ switch (a_MetaData)
{
case 0x1: return BLOCK_FACE_NORTH;
case 0x4: return BLOCK_FACE_SOUTH;
@@ -73,7 +80,7 @@ public:
/// Returns true if the specified block type is good for vines to attach to
static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
{
- return (a_BlockType == E_BLOCK_LEAVES) || (a_BlockType == E_BLOCK_NEW_LEAVES) || cBlockInfo::IsSolid(a_BlockType);
+ return ((a_BlockType == E_BLOCK_LEAVES) || (a_BlockType == E_BLOCK_NEW_LEAVES) || cBlockInfo::IsSolid(a_BlockType));
}
@@ -175,7 +182,7 @@ public:
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY - 1, a_RelZ, Block);
if (Block == E_BLOCK_AIR)
{
- if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, a_RelX * cChunkDef::Width, a_RelY - 1, a_RelZ * cChunkDef::Width, ssVineSpread))
+ if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY - 1, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, ssVineSpread))
{
a_Chunk.UnboundedRelSetBlock(a_RelX, a_RelY - 1, a_RelZ, E_BLOCK_VINES, a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
}
diff --git a/src/Blocks/BlockWallSign.h b/src/Blocks/BlockWallSign.h
new file mode 100644
index 000000000..47649379e
--- /dev/null
+++ b/src/Blocks/BlockWallSign.h
@@ -0,0 +1,90 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+#include "../Entities/Player.h"
+#include "Chunk.h"
+
+
+
+
+
+class cBlockWallSignHandler :
+ public cBlockHandler
+{
+ typedef cBlockHandler super;
+
+public:
+ cBlockWallSignHandler(BLOCKTYPE a_BlockType) :
+ super(a_BlockType)
+ {
+ }
+
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ a_Pickups.push_back(cItem(E_ITEM_SIGN, 1, 0));
+ }
+
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+
+
+ virtual void OnPlacedByPlayer(
+ cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
+ ) override
+ {
+ a_Player->GetClientHandle()->SendEditSign(a_BlockX, a_BlockY, a_BlockZ);
+ }
+
+
+ virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
+ {
+ int BlockX = (a_Chunk.GetPosX() * cChunkDef::Width) + a_RelX;
+ int BlockZ = (a_Chunk.GetPosZ() * cChunkDef::Width) + a_RelZ;
+ GetBlockCoordsBehindTheSign(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ), BlockX, BlockZ);
+ BLOCKTYPE Type = a_ChunkInterface.GetBlock(BlockX, a_RelY, BlockZ);
+
+ return ((Type == E_BLOCK_WALLSIGN) || (Type == E_BLOCK_SIGN_POST) || cBlockInfo::IsSolid(Type));
+ }
+
+
+ static void GetBlockCoordsBehindTheSign(NIBBLETYPE a_BlockMeta, int & a_BlockX, int & a_BlockZ)
+ {
+ switch (a_BlockMeta)
+ {
+ case 2: a_BlockZ++; break;
+ case 3: a_BlockZ--; break;
+ case 4: a_BlockX++; break;
+ case 5: a_BlockX--; break;
+ default: break;
+ }
+ }
+
+
+ static NIBBLETYPE DirectionToMetaData(eBlockFace a_Direction)
+ {
+ switch (a_Direction)
+ {
+ case 0x2: return 0x2;
+ case 0x3: return 0x3;
+ case 0x4: return 0x4;
+ case 0x5: return 0x5;
+ default:
+ {
+ break;
+ }
+ }
+ return 0x2;
+ }
+} ;
+
+
+
+
diff --git a/src/Blocks/BroadcastInterface.h b/src/Blocks/BroadcastInterface.h
index b1b450690..cf332b153 100644
--- a/src/Blocks/BroadcastInterface.h
+++ b/src/Blocks/BroadcastInterface.h
@@ -1,12 +1,12 @@
#pragma once
-class cBroadcastInterface
+class cBroadcastInterface
{
public:
virtual ~cBroadcastInterface() {}
- virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) = 0;
- virtual void BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL) = 0;
+ virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
+ virtual void BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL) = 0;
virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) = 0;
};
diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt
index 4b8c745ad..9f971a8bd 100644
--- a/src/Blocks/CMakeLists.txt
+++ b/src/Blocks/CMakeLists.txt
@@ -4,9 +4,97 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ BlockBed.cpp
+ BlockDoor.cpp
+ BlockHandler.cpp
+ BlockPiston.cpp
+ ChunkInterface.cpp)
-add_library(Blocks ${SOURCE})
+SET (HDRS
+ BlockAnvil.h
+ BlockBed.h
+ BlockBigFlower.h
+ BlockBrewingStand.h
+ BlockButton.h
+ BlockCactus.h
+ BlockCake.h
+ BlockCarpet.h
+ BlockCauldron.h
+ BlockChest.h
+ BlockCloth.h
+ BlockCobWeb.h
+ BlockCommandBlock.h
+ BlockComparator.h
+ BlockCrops.h
+ BlockDeadBush.h
+ BlockDirt.h
+ BlockDoor.h
+ BlockDropSpenser.h
+ BlockEnchantmentTable.h
+ BlockEnderchest.h
+ BlockEntity.h
+ BlockFarmland.h
+ BlockFenceGate.h
+ BlockFire.h
+ BlockFlower.h
+ BlockFlowerPot.h
+ BlockFluid.h
+ BlockFurnace.h
+ BlockGlass.h
+ BlockGlowstone.h
+ BlockGravel.h
+ BlockHandler.h
+ BlockHayBale.h
+ BlockHopper.h
+ BlockIce.h
+ BlockLadder.h
+ BlockLeaves.h
+ BlockLever.h
+ BlockLilypad.h
+ BlockMelon.h
+ BlockMobHead.h
+ BlockMushroom.h
+ BlockMycelium.h
+ BlockNetherWart.h
+ BlockOre.h
+ BlockPiston.h
+ BlockPlanks.h
+ BlockPluginInterface.h
+ BlockPortal.h
+ BlockPressurePlate.h
+ BlockPumpkin.h
+ BlockQuartz.h
+ BlockRail.h
+ BlockRedstone.h
+ BlockRedstoneLamp.h
+ BlockRedstoneRepeater.h
+ BlockRedstoneTorch.h
+ BlockSand.h
+ BlockSapling.h
+ BlockSideways.h
+ BlockSignPost.h
+ BlockSlab.h
+ BlockSnow.h
+ BlockStairs.h
+ BlockStems.h
+ BlockStone.h
+ BlockSugarcane.h
+ BlockTNT.h
+ BlockTallGrass.h
+ BlockTorch.h
+ BlockTrapdoor.h
+ BlockTripwire.h
+ BlockTripwireHook.h
+ BlockVine.h
+ BlockWallSign.h
+ BlockWorkbench.h
+ BroadcastInterface.h
+ ChunkInterface.h
+ ClearMetaOnDrop.h
+ MetaRotator.h
+ WorldInterface.h)
+
+if(NOT MSVC)
+ add_library(Blocks ${SRCS} ${HDRS})
+endif()
diff --git a/src/Blocks/ChunkInterface.h b/src/Blocks/ChunkInterface.h
index be7c2e0e5..dea9d7c7e 100644
--- a/src/Blocks/ChunkInterface.h
+++ b/src/Blocks/ChunkInterface.h
@@ -18,10 +18,10 @@ public:
BLOCKTYPE GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
{
- return m_ChunkMap->GetBlock(a_BlockX,a_BlockY,a_BlockZ);
+ return m_ChunkMap->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
}
BLOCKTYPE GetBlock(const Vector3i & a_Pos)
- {
+ {
return GetBlock(a_Pos.x, a_Pos.y, a_Pos.z);
}
NIBBLETYPE GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ)
@@ -61,9 +61,9 @@ public:
m_ChunkMap->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
}
- void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta )
+ void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
- FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta );
+ FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta);
}
void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
diff --git a/src/Blocks/ClearMetaOnDrop.h b/src/Blocks/ClearMetaOnDrop.h
new file mode 100644
index 000000000..f2afbc6ea
--- /dev/null
+++ b/src/Blocks/ClearMetaOnDrop.h
@@ -0,0 +1,24 @@
+
+#pragma once
+
+// mixin for use to clear meta values when the block is converted to a pickup
+
+// Usage: inherit from this class, passing the parent class as the parameter Base
+// For example to use in class Foo which should inherit Bar use
+// class Foo : public cClearMetaOnDrop<Bar>;
+
+template<class Base>
+class cClearMetaOnDrop : public Base
+{
+public:
+
+ cClearMetaOnDrop(BLOCKTYPE a_BlockType) :
+ Base(a_BlockType)
+ {}
+
+ virtual ~cClearMetaOnDrop() {}
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ a_Pickups.push_back(cItem(this->m_BlockType));
+ }
+};
diff --git a/src/Blocks/MetaRotator.h b/src/Blocks/MetaRotator.h
index 899c583e1..599aa7ef9 100644
--- a/src/Blocks/MetaRotator.h
+++ b/src/Blocks/MetaRotator.h
@@ -6,7 +6,7 @@
// MSVC generates warnings for the templated AssertIfNotMatched parameter conditions, so disable it:
#ifdef _MSC_VER
- #pragma warning(disable: 4127) // Conditional expression is constant
+ #pragma warning(disable: 4127) // Conditional expression is constant
#endif
@@ -47,8 +47,8 @@ NIBBLETYPE cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatc
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
switch (a_Meta & BitMask)
{
- case South: return West | OtherMeta;
- case West: return North | OtherMeta;
+ case South: return West | OtherMeta;
+ case West: return North | OtherMeta;
case North: return East | OtherMeta;
case East: return South | OtherMeta;
}
@@ -69,7 +69,7 @@ NIBBLETYPE cMetaRotator<Base, BitMask, North, East, South, West, AssertIfNotMatc
NIBBLETYPE OtherMeta = a_Meta & (~BitMask);
switch (a_Meta & BitMask)
{
- case South: return East | OtherMeta;
+ case South: return East | OtherMeta;
case East: return North | OtherMeta;
case North: return West | OtherMeta;
case West: return South | OtherMeta;
diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h
index 251b28d03..d1c6f9bfc 100644
--- a/src/Blocks/WorldInterface.h
+++ b/src/Blocks/WorldInterface.h
@@ -24,7 +24,7 @@ public:
virtual cBroadcastInterface & GetBroadcastManager() = 0;
- virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) = 0;
+ virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void * a_SourceData) = 0;
/** Spawns item pickups for each item in the list. May compress pickups if too many entities: */
virtual void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed = 1.0, bool IsPlayerCreated = false) = 0;
@@ -46,6 +46,12 @@ public:
virtual void SetTimeOfDay(Int64 a_TimeOfDay) = 0;
+ /** Returns true if it is raining, stormy or snowing at the specified location. This takes into account biomes. */
+ virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) = 0;
+
+ /** Returns the world height at the specified coords; waits for the chunk to get loaded / generated */
+ virtual int GetHeight(int a_BlockX, int a_BlockZ) = 0;
+
/** Wakes up the simulators for the specified block */
virtual void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
diff --git a/src/BoundingBox.cpp b/src/BoundingBox.cpp
index ce831c200..6b163b01e 100644
--- a/src/BoundingBox.cpp
+++ b/src/BoundingBox.cpp
@@ -191,7 +191,7 @@ bool cBoundingBox::IsInside(const Vector3d & a_Point)
-bool cBoundingBox::IsInside(double a_X, double a_Y,double a_Z)
+bool cBoundingBox::IsInside(double a_X, double a_Y, double a_Z)
{
return IsInside(m_Min, m_Max, a_X, a_Y, a_Z);
}
diff --git a/src/BoundingBox.h b/src/BoundingBox.h
index a7c6c3eea..793466302 100644
--- a/src/BoundingBox.h
+++ b/src/BoundingBox.h
@@ -49,7 +49,7 @@ public:
bool IsInside(const Vector3d & a_Point);
/// Returns true if the point is inside the bounding box
- bool IsInside(double a_X, double a_Y,double a_Z);
+ bool IsInside(double a_X, double a_Y, double a_Z);
/// Returns true if a_Other is inside this bounding box
bool IsInside(cBoundingBox & a_Other);
diff --git a/src/ByteBuffer.cpp b/src/ByteBuffer.cpp
index 1a69c856f..64b31c60b 100644
--- a/src/ByteBuffer.cpp
+++ b/src/ByteBuffer.cpp
@@ -140,7 +140,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cByteBuffer:
cByteBuffer::cByteBuffer(size_t a_BufferSize) :
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5ff1c4e3c..6b5efbd1f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,195 +1,180 @@
cmake_minimum_required (VERSION 2.8.2)
project (MCServer)
+
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/jsoncpp/include")
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include")
-set(FOLDERS OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++)
-set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities Generating/Prefabs)
-
-set(BINDING_DEPENDECIES
- tolua
- ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua
- ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg
- Bindings/gen_LuaState_Call.lua
- Bindings/LuaFunctions.h
- Bindings/LuaWindow.h
- Bindings/Plugin.h
- Bindings/PluginLua.h
- Bindings/PluginManager.h
- Bindings/WebPlugin.h
+set(FOLDERS
+ OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++ Bindings
+ WorldStorage Mobs Entities Simulator UI BlockEntities Generating/Prefabs
+)
+
+SET (SRCS
+ BiomeDef.cpp
+ BlockArea.cpp
+ BlockID.cpp
+ BlockInfo.cpp
+ BoundingBox.cpp
+ ByteBuffer.cpp
+ ChatColor.cpp
+ Chunk.cpp
+ ChunkData.cpp
+ ChunkMap.cpp
+ ChunkSender.cpp
+ ChunkStay.cpp
+ ClientHandle.cpp
+ CommandOutput.cpp
+ CompositeChat.cpp
+ CraftingRecipes.cpp
+ Cuboid.cpp
+ DeadlockDetect.cpp
+ Enchantments.cpp
+ FastRandom.cpp
+ FurnaceRecipe.cpp
+ Globals.cpp
+ Group.cpp
+ GroupManager.cpp
+ Inventory.cpp
+ Item.cpp
+ ItemGrid.cpp
+ LightingThread.cpp
+ LineBlockTracer.cpp
+ LinearInterpolation.cpp
+ LoggerListeners.cpp
+ Logger.cpp
+ Map.cpp
+ MapManager.cpp
+ MobCensus.cpp
+ MobFamilyCollecter.cpp
+ MobProximityCounter.cpp
+ MobSpawner.cpp
+ MonsterConfig.cpp
+ Noise.cpp
+ ProbabDistrib.cpp
+ RCONServer.cpp
+ Root.cpp
+ Scoreboard.cpp
+ Server.cpp
+ SetChunkData.cpp
+ Statistics.cpp
+ StringCompression.cpp
+ StringUtils.cpp
+ Tracer.cpp
+ VoronoiMap.cpp
+ WebAdmin.cpp
+ World.cpp
+ main.cpp)
+
+SET (HDRS
+ AllocationPool.h
BiomeDef.h
BlockArea.h
- BlockEntities/BlockEntity.h
- BlockEntities/BlockEntityWithItems.h
- BlockEntities/ChestEntity.h
- BlockEntities/DispenserEntity.h
- BlockEntities/DropSpenserEntity.h
- BlockEntities/DropperEntity.h
- BlockEntities/FurnaceEntity.h
- BlockEntities/HopperEntity.h
- BlockEntities/JukeboxEntity.h
- BlockEntities/NoteEntity.h
- BlockEntities/SignEntity.h
- BlockEntities/MobHeadEntity.h
- BlockEntities/FlowerPotEntity.h
BlockID.h
+ BlockInServerPluginInterface.h
+ BlockInfo.h
+ BlockTracer.h
BoundingBox.h
+ ByteBuffer.h
ChatColor.h
+ Chunk.h
+ ChunkData.h
+ ChunkDataCallback.h
ChunkDef.h
+ ChunkMap.h
+ ChunkSender.h
+ ChunkStay.h
ClientHandle.h
+ CommandOutput.h
+ CompositeChat.h
CraftingRecipes.h
Cuboid.h
+ DeadlockDetect.h
Defines.h
Enchantments.h
- Entities/Effects.h
- Entities/Entity.h
- Entities/Floater.h
- Entities/Pawn.h
- Entities/Painting.h
- Entities/Pickup.h
- Entities/Player.h
- Entities/ProjectileEntity.h
- Entities/ArrowEntity.h
- Entities/ThrownEggEntity.h
- Entities/ThrownEnderPearlEntity.h
- Entities/ExpBottleEntity.h
- Entities/ThrownSnowballEntity.h
- Entities/FireChargeEntity.h
- Entities/FireworkEntity.h
- Entities/GhastFireballEntity.h
- Entities/TNTEntity.h
- Entities/ExpOrb.h
- Entities/HangingEntity.h
- Entities/ItemFrame.h
- Generating/ChunkDesc.h
+ Endianness.h
+ FastRandom.h
+ ForEachChunkProvider.h
+ FurnaceRecipe.h
+ Globals.h
Group.h
+ GroupManager.h
Inventory.h
Item.h
ItemGrid.h
- Mobs/Monster.h
- OSSupport/File.h
+ LeakFinder.h
+ LightingThread.h
+ LineBlockTracer.h
+ LinearInterpolation.h
+ LinearUpscale.h
+ Logger.h
+ LoggerListeners.h
+ Map.h
+ MapManager.h
+ Matrix4.h
+ MemoryLeak.h
+ MersenneTwister.h
+ MobCensus.h
+ MobFamilyCollecter.h
+ MobProximityCounter.h
+ MobSpawner.h
+ MonsterConfig.h
+ Noise.h
+ ProbabDistrib.h
+ RCONServer.h
Root.h
+ Scoreboard.h
Server.h
+ SetChunkData.h
+ StackWalker.h
+ Statistics.h
+ StringCompression.h
StringUtils.h
Tracer.h
- UI/Window.h
Vector3.h
+ VoronoiMap.h
WebAdmin.h
World.h
-)
-
-# List all the files that are generated as part of the Bindings build process
-set (BINDING_OUTPUTS
- ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.h
- ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/LuaState_Call.inc
-)
-
-include_directories(Bindings)
-include_directories(.)
-
-if (WIN32)
- ADD_CUSTOM_COMMAND(
- OUTPUT ${BINDING_OUTPUTS}
-
- # Copy the Lua DLL into the Bindings folder, so that tolua can run from there:
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ../../MCServer/lua51.dll ./lua51.dll
-
- # Regenerate bindings:
- COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/
-
- # add any new generation dependencies here
- DEPENDS ${BINDING_DEPENDECIES}
- )
-else ()
- ADD_CUSTOM_COMMAND(
- # add any new generated bindings here
- OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.h
+ XMLParser.h)
- # Regenerate bindings:
- COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/
-
- # add any new generation dependencies here
- DEPENDS ${BINDING_DEPENDECIES}
- )
-endif ()
-set_source_files_properties(Bindings/Bindings.cpp PROPERTIES GENERATED TRUE)
-set_source_files_properties(Bindings/Bindings.h PROPERTIES GENERATED TRUE)
+include_directories(".")
+include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/sqlite")
+include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/SQLiteCpp/include")
if (NOT MSVC)
-
# Bindings need to reference other folders, so they are done here instead
-
# lib dependencies are not included
-
include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include")
- #add cpp files here
- add_library(Bindings
- Bindings/Bindings
- Bindings/DeprecatedBindings
- Bindings/LuaChunkStay
- Bindings/LuaState
- Bindings/LuaWindow
- Bindings/ManualBindings
- Bindings/Plugin
- Bindings/PluginLua
- Bindings/PluginManager
- Bindings/WebPlugin
- )
+ foreach(folder ${FOLDERS})
+ add_subdirectory(${folder})
+ endforeach(folder)
- target_link_libraries(Bindings lua sqlite tolualib polarssl)
+ get_directory_property(BINDING_DEPENDENCIES DIRECTORY "Bindings" DEFINITION BINDING_DEPENDENCIES)
#clear file
- file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependecies.txt)
- foreach(dependecy ${BINDING_DEPENDECIES})
- #write each dependecy on a seperate line
- file(APPEND ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependecies.txt "${dependecy}\n")
+ file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependencies.txt)
+ foreach(dependency ${BINDING_DEPENDENCIES})
+ #write each dependency on a seperate line
+ file(APPEND ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependencies.txt "${dependency}\n")
endforeach()
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "Bindings.cpp Bindings.h")
- foreach(folder ${FOLDERS})
- add_subdirectory(${folder})
- endforeach(folder)
-
- file(GLOB SOURCE
- "*.cpp"
- "*.h"
- )
-
- list(REMOVE_ITEM SOURCE "${PROJECT_SOURCE_DIR}/StackWalker.cpp" "${PROJECT_SOURCE_DIR}/LeakFinder.cpp")
+ list(APPEND SOURCE "${SRCS}")
+ list(APPEND SOURCE "${HDRS}")
# If building a windows version, but not using MSVC, add the resources directly to the makefile:
if (WIN32)
- FILE(GLOB ResourceFiles
- "Resources/*.rc"
- )
- list(APPEND SOURCE "${ResourceFiles}")
+ list(APPEND SOURCE "Resources/MCServer.rc")
endif()
-
-
else ()
# MSVC-specific handling: Put all files into one project, separate by the folders:
- # Get all files in this folder:
- file(GLOB_RECURSE SOURCE
- "*.cpp"
- "*.h"
- "*.pkg"
- )
- source_group("" FILES ${SOURCE})
-
- LIST(APPEND SOURCE "Bindings/Bindings.cpp" "Bindings/Bindings.h")
source_group(Bindings FILES "Bindings/Bindings.cpp" "Bindings/Bindings.h")
# Add all subfolders as solution-folders:
- list(APPEND FOLDERS "Resources")
- list(APPEND FOLDERS "Bindings")
function(includefolder PATH)
FILE(GLOB FOLDER_FILES
"${PATH}/*.cpp"
@@ -202,9 +187,29 @@ else ()
endfunction(includefolder)
foreach(folder ${FOLDERS})
+ add_subdirectory(${folder})
includefolder(${folder})
+
+ # Get all source files in this folder:
+ get_directory_property(FOLDER_SRCS DIRECTORY ${folder} DEFINITION SRCS)
+ foreach (src ${FOLDER_SRCS})
+ list(APPEND SOURCE "${folder}/${src}")
+ endforeach(src)
+
+ # Get all headers in this folder:
+ get_directory_property(FOLDER_HDRS DIRECTORY ${folder} DEFINITION HDRS)
+ foreach (hdr ${FOLDER_HDRS})
+ list(APPEND SOURCE "${folder}/${hdr}")
+ endforeach(hdr)
endforeach(folder)
+ list(APPEND SOURCE "${SRCS}")
+ list(APPEND SOURCE "${HDRS}")
+ list(APPEND SOURCE "Bindings/AllToLua.pkg")
+
+ includefolder("Resources")
+ source_group("" FILES ${SOURCE})
+
include_directories("${PROJECT_SOURCE_DIR}")
# Precompiled headers (1st part)
@@ -228,8 +233,47 @@ else ()
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /DEBUG")
endif()
+
+# Generate a list of all source files:
+set(ALLFILES "${SRCS}" "${HDRS}")
+foreach(folder ${FOLDERS})
+ get_directory_property(FOLDER_SRCS DIRECTORY ${folder} DEFINITION SRCS)
+ foreach (src ${FOLDER_SRCS})
+ list(APPEND ALLFILES "${folder}/${src}")
+ endforeach(src)
+
+ get_directory_property(FOLDER_HDRS DIRECTORY ${folder} DEFINITION HDRS)
+ foreach (hdr ${FOLDER_HDRS})
+ list(APPEND ALLFILES "${folder}/${hdr}")
+ endforeach(hdr)
+endforeach(folder)
+foreach(arg ${ALLFILES})
+ set(ALLFILESLINES "${ALLFILESLINES}${arg}\n")
+endforeach()
+FILE(WRITE "AllFiles.lst" "${ALLFILESLINES}")
+
+
set(EXECUTABLE MCServer)
+if (MSVC)
+ get_directory_property(BINDING_OUTPUTS DIRECTORY "Bindings" DEFINITION BINDING_OUTPUTS)
+ get_directory_property(BINDING_DEPENDENCIES DIRECTORY "Bindings" DEFINITION BINDING_DEPENDENCIES)
+
+ ADD_CUSTOM_COMMAND(
+ OUTPUT ${BINDING_OUTPUTS}
+
+ # Copy the Lua DLL into the Bindings folder, so that tolua can run from there:
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/MCServer/lua51.dll ./lua51.dll
+
+ # Regenerate bindings:
+ COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/
+
+ # add any new generation dependencies here
+ DEPENDS ${BINDING_DEPENDENCIES}
+ )
+endif()
+
add_executable(${EXECUTABLE} ${SOURCE})
@@ -261,11 +305,13 @@ endif ()
if (NOT MSVC)
- target_link_libraries(${EXECUTABLE} OSSupport HTTPServer Bindings Items Blocks)
- target_link_libraries(${EXECUTABLE} Protocol Generating Generating_Prefabs WorldStorage)
- target_link_libraries(${EXECUTABLE} Mobs Entities Simulator UI BlockEntities PolarSSL++)
+ target_link_libraries(${EXECUTABLE}
+ OSSupport HTTPServer Bindings Items Blocks
+ Protocol Generating Generating_Prefabs WorldStorage
+ Mobs Entities Simulator UI BlockEntities PolarSSL++
+ )
endif ()
if (WIN32)
target_link_libraries(${EXECUTABLE} expat tolualib ws2_32.lib Psapi.lib)
endif()
-target_link_libraries(${EXECUTABLE} luaexpat iniFile jsoncpp polarssl zlib sqlite lua)
+target_link_libraries(${EXECUTABLE} luaexpat iniFile jsoncpp polarssl zlib sqlite lua SQLiteCpp)
diff --git a/src/ChatColor.cpp b/src/ChatColor.cpp
index 72a0a6928..e1317c287 100644
--- a/src/ChatColor.cpp
+++ b/src/ChatColor.cpp
@@ -2,31 +2,31 @@
#include "ChatColor.h"
-const std::string cChatColor::Color = "\xc2\xa7"; // or in other words: "§" in UTF-8
-const std::string cChatColor::Delimiter = "\xc2\xa7"; // or in other words: "§" in UTF-8
-const std::string cChatColor::Black = cChatColor::Color + "0";
-const std::string cChatColor::Navy = cChatColor::Color + "1";
-const std::string cChatColor::Green = cChatColor::Color + "2";
-const std::string cChatColor::Blue = cChatColor::Color + "3";
-const std::string cChatColor::Red = cChatColor::Color + "4";
-const std::string cChatColor::Purple = cChatColor::Color + "5";
-const std::string cChatColor::Gold = cChatColor::Color + "6";
-const std::string cChatColor::LightGray = cChatColor::Color + "7";
-const std::string cChatColor::Gray = cChatColor::Color + "8";
-const std::string cChatColor::DarkPurple = cChatColor::Color + "9";
-const std::string cChatColor::LightGreen = cChatColor::Color + "a";
-const std::string cChatColor::LightBlue = cChatColor::Color + "b";
-const std::string cChatColor::Rose = cChatColor::Color + "c";
-const std::string cChatColor::LightPurple = cChatColor::Color + "d";
-const std::string cChatColor::Yellow = cChatColor::Color + "e";
-const std::string cChatColor::White = cChatColor::Color + "f";
+const char * cChatColor::Color = "\xc2\xa7"; // or in other words: "§" in UTF-8
+const char * cChatColor::Delimiter = "\xc2\xa7"; // or in other words: "§" in UTF-8
+const char * cChatColor::Black = "\xc2\xa7""0";
+const char * cChatColor::Navy = "\xc2\xa7""1";
+const char * cChatColor::Green = "\xc2\xa7""2";
+const char * cChatColor::Blue = "\xc2\xa7""3";
+const char * cChatColor::Red = "\xc2\xa7""4";
+const char * cChatColor::Purple = "\xc2\xa7""5";
+const char * cChatColor::Gold = "\xc2\xa7""6";
+const char * cChatColor::LightGray = "\xc2\xa7""7";
+const char * cChatColor::Gray = "\xc2\xa7""8";
+const char * cChatColor::DarkPurple = "\xc2\xa7""9";
+const char * cChatColor::LightGreen = "\xc2\xa7""a";
+const char * cChatColor::LightBlue = "\xc2\xa7""b";
+const char * cChatColor::Rose = "\xc2\xa7""c";
+const char * cChatColor::LightPurple = "\xc2\xa7""d";
+const char * cChatColor::Yellow = "\xc2\xa7""e";
+const char * cChatColor::White = "\xc2\xa7""f";
-const std::string cChatColor::Random = cChatColor::Color + "k";
-const std::string cChatColor::Bold = cChatColor::Color + "l";
-const std::string cChatColor::Strikethrough = cChatColor::Color + "m";
-const std::string cChatColor::Underlined = cChatColor::Color + "n";
-const std::string cChatColor::Italic = cChatColor::Color + "o";
-const std::string cChatColor::Plain = cChatColor::Color + "r";
+const char * cChatColor::Random = "\xc2\xa7""k";
+const char * cChatColor::Bold = "\xc2\xa7""l";
+const char * cChatColor::Strikethrough = "\xc2\xa7""m";
+const char * cChatColor::Underlined = "\xc2\xa7""n";
+const char * cChatColor::Italic = "\xc2\xa7""o";
+const char * cChatColor::Plain = "\xc2\xa7""r";
diff --git a/src/ChatColor.h b/src/ChatColor.h
index 643c4d5d8..21377e27f 100644
--- a/src/ChatColor.h
+++ b/src/ChatColor.h
@@ -9,34 +9,36 @@
class cChatColor
{
public:
- static const std::string Color;
- static const std::string Delimiter;
-
- static const std::string Black;
- static const std::string Navy;
- static const std::string Green;
- static const std::string Blue;
- static const std::string Red;
- static const std::string Purple;
- static const std::string Gold;
- static const std::string LightGray;
- static const std::string Gray;
- static const std::string DarkPurple;
- static const std::string LightGreen;
- static const std::string LightBlue;
- static const std::string Rose;
- static const std::string LightPurple;
- static const std::string Yellow;
- static const std::string White;
-
- // Styles ( source: http://wiki.vg/Chat )
- static const std::string Random;
- static const std::string Bold;
- static const std::string Strikethrough;
- static const std::string Underlined;
- static const std::string Italic;
- static const std::string Plain;
-
+ static const char * Delimiter;
+
+ /** @deprecated use ChatColor::Delimiter instead */
+ static const char * Color;
+
+ static const char * Black;
+ static const char * Navy;
+ static const char * Green;
+ static const char * Blue;
+ static const char * Red;
+ static const char * Purple;
+ static const char * Gold;
+ static const char * LightGray;
+ static const char * Gray;
+ static const char * DarkPurple;
+ static const char * LightGreen;
+ static const char * LightBlue;
+ static const char * Rose;
+ static const char * LightPurple;
+ static const char * Yellow;
+ static const char * White;
+
+ // Styles
+ // source: http://wiki.vg/Chat
+ static const char * Random;
+ static const char * Bold;
+ static const char * Strikethrough;
+ static const char * Underlined;
+ static const char * Italic;
+ static const char * Plain;
};
// tolua_end
diff --git a/src/CheckBasicStyle.lua b/src/CheckBasicStyle.lua
new file mode 100644
index 000000000..bf81a7cd5
--- /dev/null
+++ b/src/CheckBasicStyle.lua
@@ -0,0 +1,243 @@
+#!/usr/bin/env lua
+
+-- CheckBasicStyle.lua
+
+--[[
+Checks that all source files (*.cpp, *.h) use the basic style requirements of the project:
+ - Tabs for indentation, spaces for alignment
+ - Trailing whitespace on non-empty lines
+ - Two spaces between code and line-end comment ("//")
+ - Spaces after comma, not before
+ - Opening braces not at the end of a code line
+ - Spaces after if, for, while
+ - Line dividers (////...) exactly 80 slashes
+ - Multi-level indent change
+ - (TODO) Spaces before *, /, &
+ - (TODO) Hex numbers with even digit length
+ - (TODO) Hex numbers in lowercase
+ - (TODO) Not using "* "-style doxy comment continuation lines
+
+Violations that cannot be checked easily:
+ - Spaces around "+" (there are things like "a++", "++a", "a += 1", "X+", "stack +1" and ascii-drawn tables)
+
+Reports all violations on stdout in a form that is readable by Visual Studio's parser, so that dblclicking
+the line brings the editor directly to the violation.
+
+Returns 0 on success, 1 on internal failure, 2 if any violations found
+
+--]]
+
+
+
+
+
+-- The list of file extensions that are processed:
+local g_ShouldProcessExt =
+{
+ ["h"] = true,
+ ["cpp"] = true,
+}
+
+--- The list of files not to be processed:
+local g_IgnoredFiles =
+{
+ "Bindings/Bindings.cpp",
+ "LeakFinder.cpp",
+ "LeakFinder.h",
+ "MersenneTwister.h",
+ "StackWalker.cpp",
+ "StackWalker.h",
+}
+
+--- The list of files not to be processed, as a dictionary (filename => true), built from g_IgnoredFiles
+local g_ShouldIgnoreFile = {}
+
+-- Initialize the g_ShouldIgnoreFile map:
+for _, fnam in ipairs(g_IgnoredFiles) do
+ g_ShouldIgnoreFile[fnam] = true
+end
+
+--- Keeps track of the number of violations for this folder
+local g_NumViolations = 0
+
+
+
+
+
+--- Reports one violation
+-- Pretty-prints the message
+-- Also increments g_NumViolations
+local function ReportViolation(a_FileName, a_LineNumber, a_PatStart, a_PatEnd, a_Message)
+ print(a_FileName .. "(" .. a_LineNumber .. "): " .. a_PatStart .. " .. " .. a_PatEnd .. ": " .. a_Message)
+ g_NumViolations = g_NumViolations + 1
+end
+
+
+
+
+
+--- Searches for the specified pattern, if found, reports it as a violation with the given message
+local function ReportViolationIfFound(a_Line, a_FileName, a_LineNum, a_Pattern, a_Message)
+ local patStart, patEnd = a_Line:find(a_Pattern)
+ if not(patStart) then
+ return
+ end
+ ReportViolation(a_FileName, a_LineNum, patStart, patEnd, a_Message)
+end
+
+
+
+
+
+local g_ViolationPatterns =
+{
+ -- Check against indenting using spaces:
+ {"^\t* +", "Indenting with a space"},
+
+ -- Check against alignment using tabs:
+ {"[^%s]\t+[^%s]", "Aligning with a tab"},
+
+ -- Check against trailing whitespace:
+ {"[^%s]%s+\n", "Trailing whitespace"},
+
+ -- Check that all "//"-style comments have at least two spaces in front (unless alone on line):
+ {"[^%s] //", "Needs at least two spaces in front of a \"//\"-style comment"},
+
+ -- Check that all "//"-style comments have at least one spaces after:
+ {"%s//[^%s/*<]", "Needs a space after a \"//\"-style comment"},
+
+ -- Check that all commas have spaces after them and not in front of them:
+ {" ,", "Extra space before a \",\""},
+ {",[^%s\"%%]", "Needs a space after a \",\""}, -- Report all except >> "," << needed for splitting and >>,%s<< needed for formatting
+
+ -- Check that opening braces are not at the end of a code line:
+ {"[^%s].-{\n?$", "Brace should be on a separate line"},
+
+ -- Space after keywords:
+ {"[^_]if%(", "Needs a space after \"if\""},
+ {"for%(", "Needs a space after \"for\""},
+ {"while%(", "Needs a space after \"while\""},
+ {"switch%(", "Needs a space after \"switch\""},
+ {"catch%(", "Needs a space after \"catch\""},
+
+ -- No space after keyword's parenthesis:
+ {"[^%a#]if %( ", "Remove the space after \"(\""},
+ {"for %( ", "Remove the space after \"(\""},
+ {"while %( ", "Remove the space after \"(\""},
+ {"catch %( ", "Remove the space after \"(\""},
+
+ -- No space before a closing parenthesis:
+ {" %)", "Remove the space before \")\""},
+}
+
+
+
+
+
+--- Processes one file
+local function ProcessFile(a_FileName)
+ assert(type(a_FileName) == "string")
+
+ -- Read the whole file:
+ local f, err = io.open(a_FileName, "r")
+ if (f == nil) then
+ print("Cannot open file \"" .. a_FileName .. "\": " .. err)
+ print("Aborting")
+ os.exit(1)
+ end
+ local all = f:read("*all")
+
+ -- Check that the last line is empty - otherwise processing won't work properly:
+ local lastChar = string.byte(all, string.len(all))
+ if ((lastChar ~= 13) and (lastChar ~= 10)) then
+ local numLines = 1
+ string.gsub(all, "\n", function() numLines = numLines + 1 end) -- Count the number of line-ends
+ ReportViolation(a_FileName, numLines, 1, 1, "Missing empty line at file end")
+ return
+ end
+
+ -- Process each line separately:
+ -- Ref.: http://stackoverflow.com/questions/10416869/iterate-over-possibly-empty-lines-in-a-way-that-matches-the-expectations-of-exis
+ local lineCounter = 1
+ local lastIndentLevel = 0
+ all:gsub("\r\n", "\n") -- normalize CRLF into LF-only
+ string.gsub(all .. "\n", "[^\n]*\n", -- Iterate over each line, while preserving empty lines
+ function(a_Line)
+ -- Check against each violation pattern:
+ for _, pat in ipairs(g_ViolationPatterns) do
+ ReportViolationIfFound(a_Line, a_FileName, lineCounter, pat[1], pat[2])
+ end
+
+ -- Check that divider comments are well formed - 80 slashes plus optional indent:
+ local dividerStart, dividerEnd = a_Line:find("/////*")
+ if (dividerStart) then
+ if (dividerEnd ~= dividerStart + 79) then
+ ReportViolation(a_FileName, lineCounter, 1, 80, "Divider comment should have exactly 80 slashes")
+ end
+ if (dividerStart > 1) then
+ if (
+ (a_Line:sub(1, dividerStart - 1) ~= string.rep("\t", dividerStart - 1)) or -- The divider should have only indent in front of it
+ (a_Line:len() > dividerEnd + 1) -- The divider should have no other text following it
+ ) then
+ ReportViolation(a_FileName, lineCounter, 1, 80, "Divider comment shouldn't have any extra text around it")
+ end
+ end
+ end
+
+ -- Check the indent level change from the last line, if it's too much, report:
+ local indentStart, indentEnd = a_Line:find("\t+")
+ local indentLevel = 0
+ if (indentStart) then
+ indentLevel = indentEnd - indentStart
+ end
+ if (indentLevel > 0) then
+ if ((lastIndentLevel - indentLevel >= 2) or (lastIndentLevel - indentLevel <= -2)) then
+ ReportViolation(a_FileName, lineCounter, 1, indentStart or 1, "Indent changed more than a single level between the previous line and this one: from " .. lastIndentLevel .. " to " .. indentLevel)
+ end
+ lastIndentLevel = indentLevel
+ end
+
+ lineCounter = lineCounter + 1
+ end
+ )
+end
+
+
+
+
+
+--- Processes one item - a file or a folder
+local function ProcessItem(a_ItemName)
+ assert(type(a_ItemName) == "string")
+
+ -- Skip files / folders that should be ignored
+ if (g_ShouldIgnoreFile[a_ItemName]) then
+ return
+ end
+
+ local ext = a_ItemName:match("%.([^/%.]-)$")
+ if (g_ShouldProcessExt[ext]) then
+ ProcessFile(a_ItemName)
+ end
+end
+
+
+
+
+
+-- Process all files in the AllFiles.lst file (generated by cmake):
+for fnam in io.lines("AllFiles.lst") do
+ ProcessItem(fnam)
+end
+
+-- Report final verdict:
+print("Number of violations found: " .. g_NumViolations)
+if (g_NumViolations > 0) then
+ os.exit(2)
+else
+ os.exit(0)
+end
+
+
+
+
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 3f5165b7b..116c0f3a0 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -1,3 +1,4 @@
+
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#ifndef _WIN32
@@ -11,6 +12,7 @@
#include "Server.h"
#include "zlib/zlib.h"
#include "Defines.h"
+#include "BlockEntities/BeaconEntity.h"
#include "BlockEntities/ChestEntity.h"
#include "BlockEntities/DispenserEntity.h"
#include "BlockEntities/DropperEntity.h"
@@ -34,6 +36,7 @@
#include "MobCensus.h"
#include "MobSpawner.h"
#include "BlockInServerPluginInterface.h"
+#include "SetChunkData.h"
#include "json/json.h"
@@ -41,15 +44,15 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// sSetBlock:
-sSetBlock::sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) // absolute block position
- : x( a_BlockX )
- , y( a_BlockY )
- , z( a_BlockZ )
- , BlockType( a_BlockType )
- , BlockMeta( a_BlockMeta )
+sSetBlock::sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) // absolute block position
+ : x( a_BlockX)
+ , y( a_BlockY)
+ , z( a_BlockZ)
+ , BlockType( a_BlockType)
+ , BlockMeta( a_BlockMeta)
{
cChunkDef::AbsoluteToRelative(x, y, z, ChunkX, ChunkZ);
}
@@ -58,11 +61,11 @@ sSetBlock::sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_Bloc
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cChunk:
cChunk::cChunk(
- int a_ChunkX, int a_ChunkY, int a_ChunkZ,
+ int a_ChunkX, int a_ChunkY, int a_ChunkZ,
cChunkMap * a_ChunkMap, cWorld * a_World,
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP,
cAllocationPool<cChunkData::sChunkSection> & a_Pool
@@ -116,7 +119,7 @@ cChunk::~cChunk()
{
cPluginManager::Get()->CallHookChunkUnloaded(m_World, m_PosX, m_PosZ);
- // LOGINFO("### delete cChunk() (%i, %i) from %p, thread 0x%x ###", m_PosX, m_PosZ, this, GetCurrentThreadId() );
+ // LOGINFO("### delete cChunk() (%i, %i) from %p, thread 0x%x ###", m_PosX, m_PosZ, this, GetCurrentThreadId());
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
{
@@ -265,41 +268,34 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback)
-void cChunk::SetAllData(
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const HeightMap * a_HeightMap,
- const BiomeMap & a_BiomeMap,
- cBlockEntityList & a_BlockEntities
-)
+void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
{
- memcpy(m_BiomeMap, a_BiomeMap, sizeof(m_BiomeMap));
+ ASSERT(a_SetChunkData.IsHeightMapValid());
+ ASSERT(a_SetChunkData.AreBiomesValid());
+
+ memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
+ memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
- if (a_HeightMap != NULL)
+ m_ChunkData.SetBlockTypes(a_SetChunkData.GetBlockTypes());
+ m_ChunkData.SetMetas(a_SetChunkData.GetBlockMetas());
+ if (a_SetChunkData.IsLightValid())
{
- memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap));
+ m_ChunkData.SetBlockLight(a_SetChunkData.GetBlockLight());
+ m_ChunkData.SetSkyLight(a_SetChunkData.GetSkyLight());
+ m_IsLightValid = true;
}
-
- if (a_HeightMap == NULL)
+ else
{
- CalculateHeightmap(a_BlockTypes);
+ m_IsLightValid = false;
}
- m_ChunkData.SetBlockTypes(a_BlockTypes);
- m_ChunkData.SetMetas(a_BlockMeta);
- m_ChunkData.SetBlockLight(a_BlockLight);
- m_ChunkData.SetSkyLight(a_BlockSkyLight);
-
- m_IsLightValid = (a_BlockLight != NULL) && (a_BlockSkyLight != NULL);
-
// Clear the block entities present - either the loader / saver has better, or we'll create empty ones:
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
{
delete *itr;
}
- std::swap(a_BlockEntities, m_BlockEntities);
+ m_BlockEntities.clear();
+ std::swap(a_SetChunkData.GetBlockEntities(), m_BlockEntities);
// Set all block entities' World variable:
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
@@ -443,19 +439,19 @@ void cChunk::CollectMobCensus(cMobCensus& toFill)
{
currentPlayer = (*itr)->GetPlayer();
playerPositions.push_back(&(currentPlayer->GetPosition()));
- }
+ }
Vector3d currentPosition;
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
{
- //LOGD("Counting entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
+ // LOGD("Counting entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
if ((*itr)->IsMob())
{
cMonster& Monster = (cMonster&)(**itr);
currentPosition = Monster.GetPosition();
for (std::list<const Vector3d*>::const_iterator itr2 = playerPositions.begin(); itr2 != playerPositions.end(); ++itr2)
{
- toFill.CollectMob(Monster,*this,(currentPosition-**itr2).SqrLength());
+ toFill.CollectMob(Monster, *this, (currentPosition - **itr2).SqrLength());
}
}
} // for itr - m_Entitites[]
@@ -464,7 +460,7 @@ void cChunk::CollectMobCensus(cMobCensus& toFill)
-void cChunk::getThreeRandomNumber(int& a_X, int& a_Y, int& a_Z,int a_MaxX, int a_MaxY, int a_MaxZ)
+void cChunk::GetThreeRandomNumbers(int & a_X, int & a_Y, int & a_Z, int a_MaxX, int a_MaxY, int a_MaxZ)
{
ASSERT(a_MaxX * a_MaxY * a_MaxZ * 8 < 0x00ffffff);
int Random = m_World->GetTickRandomNumber(0x00ffffff);
@@ -480,12 +476,12 @@ void cChunk::getThreeRandomNumber(int& a_X, int& a_Y, int& a_Z,int a_MaxX, int a
-void cChunk::getRandomBlockCoords(int& a_X, int& a_Y, int& a_Z)
+void cChunk::GetRandomBlockCoords(int & a_X, int & a_Y, int & a_Z)
{
// MG TODO : check if this kind of optimization (only one random call) is still needed
// MG TODO : if so propagate it
- getThreeRandomNumber(a_X, a_Y, a_Z, Width, Height-2, Width);
+ GetThreeRandomNumbers(a_X, a_Y, a_Z, Width, Height - 2, Width);
a_Y++;
}
@@ -495,65 +491,68 @@ void cChunk::getRandomBlockCoords(int& a_X, int& a_Y, int& a_Z)
void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner)
{
- int Center_X,Center_Y,Center_Z;
- getRandomBlockCoords(Center_X,Center_Y,Center_Z);
-
- BLOCKTYPE PackCenterBlock = GetBlock(Center_X, Center_Y, Center_Z);
- if (a_MobSpawner.CheckPackCenter(PackCenterBlock))
- {
- a_MobSpawner.NewPack();
- int NumberOfTries = 0;
- int NumberOfSuccess = 0;
- int MaxNbOfSuccess = 4; // this can be changed during the process for Wolves and Ghass
- while (NumberOfTries < 12 && NumberOfSuccess < MaxNbOfSuccess)
- {
- const int HorizontalRange = 20; // MG TODO : relocate
- const int VerticalRange = 0; // MG TODO : relocate
- int Try_X, Try_Y, Try_Z;
- getThreeRandomNumber(Try_X, Try_Y, Try_Z, 2*HorizontalRange+1 , 2*VerticalRange+1 , 2*HorizontalRange+1);
- Try_X -= HorizontalRange;
- Try_Y -= VerticalRange;
- Try_Z -= HorizontalRange;
- Try_X += Center_X;
- Try_Y += Center_Y;
- Try_Z += Center_Z;
-
- ASSERT(Try_Y > 0);
- ASSERT(Try_Y < cChunkDef::Height-1);
-
- EMCSBiome Biome = m_ChunkMap->GetBiomeAt (Try_X, Try_Z);
- // MG TODO :
- // Moon cycle (for slime)
- // check player and playerspawn presence < 24 blocks
- // check mobs presence on the block
-
- // MG TODO : check that "Level" really means Y
-
- /*
- NIBBLETYPE SkyLight = 0;
-
- NIBBLETYPE BlockLight = 0;
- */
+ int CenterX, CenterY, CenterZ;
+ GetRandomBlockCoords(CenterX, CenterY, CenterZ);
- if (IsLightValid())
- {
- cEntity* newMob = a_MobSpawner.TryToSpawnHere(this, Try_X, Try_Y, Try_Z, Biome, MaxNbOfSuccess);
- if (newMob)
- {
- int WorldX, WorldY, WorldZ;
- PositionToWorldPosition(Try_X, Try_Y, Try_Z, WorldX, WorldY, WorldZ);
- double ActualX = WorldX + 0.5;
- double ActualZ = WorldZ + 0.5;
- newMob->SetPosition(ActualX, WorldY, ActualZ);
- LOGD("Spawning %s #%i at %d,%d,%d",newMob->GetClass(),newMob->GetUniqueID(),WorldX, WorldY, WorldZ);
- NumberOfSuccess++;
- }
- }
-
- NumberOfTries++;
- }
+ BLOCKTYPE PackCenterBlock = GetBlock(CenterX, CenterY, CenterZ);
+ if (!a_MobSpawner.CheckPackCenter(PackCenterBlock))
+ {
+ return;
}
+
+ a_MobSpawner.NewPack();
+ int NumberOfTries = 0;
+ int NumberOfSuccess = 0;
+ int MaxNbOfSuccess = 4; // This can be changed during the process for Wolves and Ghasts
+ while ((NumberOfTries < 12) && (NumberOfSuccess < MaxNbOfSuccess))
+ {
+ const int HorizontalRange = 20; // MG TODO : relocate
+ const int VerticalRange = 0; // MG TODO : relocate
+ int TryX, TryY, TryZ;
+ GetThreeRandomNumbers(TryX, TryY, TryZ, 2 * HorizontalRange + 1, 2 * VerticalRange + 1, 2 * HorizontalRange + 1);
+ TryX -= HorizontalRange;
+ TryY -= VerticalRange;
+ TryZ -= HorizontalRange;
+ TryX += CenterX;
+ TryY += CenterY;
+ TryZ += CenterZ;
+
+ ASSERT(TryY > 0);
+ ASSERT(TryY < cChunkDef::Height - 1);
+
+ EMCSBiome Biome = m_ChunkMap->GetBiomeAt(TryX, TryZ);
+ // MG TODO :
+ // Moon cycle (for slime)
+ // check player and playerspawn presence < 24 blocks
+ // check mobs presence on the block
+
+ // MG TODO : check that "Level" really means Y
+
+ /*
+ NIBBLETYPE SkyLight = 0;
+
+ NIBBLETYPE BlockLight = 0;
+ */
+ NumberOfTries++;
+ if (!IsLightValid())
+ {
+ continue;
+ }
+
+ cEntity * newMob = a_MobSpawner.TryToSpawnHere(this, TryX, TryY, TryZ, Biome, MaxNbOfSuccess);
+ if (newMob == NULL)
+ {
+ continue;
+ }
+ int WorldX, WorldY, WorldZ;
+ PositionToWorldPosition(TryX, TryY, TryZ, WorldX, WorldY, WorldZ);
+ double ActualX = WorldX + 0.5;
+ double ActualZ = WorldZ + 0.5;
+ newMob->SetPosition(ActualX, WorldY, ActualZ);
+ LOGD("Spawning %s #%i at {%d, %d, %d}", newMob->GetClass(), newMob->GetUniqueID(), WorldX, WorldY, WorldZ);
+ NumberOfSuccess++;
+ } // while (retry)
}
@@ -580,39 +579,36 @@ void cChunk::Tick(float a_Dt)
m_IsDirty = (*itr)->Tick(a_Dt, *this) | m_IsDirty;
}
- // Tick all entities in this chunk (except mobs):
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
+ for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
{
- // Mobs are tickes inside MobTick (as we don't have to tick them if they are far away from players)
- if (!((*itr)->IsMob()))
+ if (!((*itr)->IsMob())) // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players)
{
+ // Tick all entities in this chunk (except mobs):
(*itr)->Tick(a_Dt, *this);
}
- } // for itr - m_Entitites[]
-
- // Remove all entities that were scheduled for removal:
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
- {
- if ((*itr)->IsDestroyed())
- {
- LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
- cEntity * ToDelete = *itr;
- itr = m_Entities.erase(itr);
- delete ToDelete;
- ToDelete = NULL;
- continue;
- }
- ++itr;
- } // for itr - m_Entitites[]
-
- // If any entity moved out of the chunk, move it to the neighbor:
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
- {
- if (
+
+ if ((*itr)->IsDestroyed()) // Remove all entities that were scheduled for removal:
+ {
+ LOGD("Destroying entity #%i (%s)", (*itr)->GetUniqueID(), (*itr)->GetClass());
+ MarkDirty();
+ cEntity * ToDelete = *itr;
+ itr = m_Entities.erase(itr);
+ delete ToDelete;
+ }
+ else if ((*itr)->IsWorldTravellingFrom(m_World))
+ {
+ // Remove all entities that are travelling to another world
+ MarkDirty();
+ (*itr)->SetWorldTravellingFrom(NULL);
+ itr = m_Entities.erase(itr);
+ }
+ else if (
((*itr)->GetChunkX() != m_PosX) ||
((*itr)->GetChunkZ() != m_PosZ)
)
{
+ // The entity moved out of the chunk, move it to the neighbor
+ MarkDirty();
MoveEntityToNewChunk(*itr);
itr = m_Entities.erase(itr);
}
@@ -620,7 +616,7 @@ void cChunk::Tick(float a_Dt)
{
++itr;
}
- }
+ } // for itr - m_Entitites[]
ApplyWeatherToTop();
}
@@ -635,7 +631,7 @@ void cChunk::TickBlock(int a_RelX, int a_RelY, int a_RelZ)
ASSERT(Handler != NULL); // Happenned on server restart, FS #243
cChunkInterface ChunkInterface(this->GetWorld()->GetChunkMap());
cBlockInServerPluginInterface PluginInterface(*this->GetWorld());
- Handler->OnUpdate(ChunkInterface, *this->GetWorld(), PluginInterface,*this, a_RelX, a_RelY, a_RelZ);
+ Handler->OnUpdate(ChunkInterface, *this->GetWorld(), PluginInterface, *this, a_RelX, a_RelY, a_RelZ);
}
@@ -695,13 +691,13 @@ void cChunk::ProcessQueuedSetBlocks(void)
{
if (itr->m_Tick <= CurrTick)
{
- if (itr->m_PreviousType != E_BLOCK_AIR) // PreviousType defaults to 0 if not specified
+ if (itr->m_PreviousType != E_BLOCK_AIR) // PreviousType defaults to 0 if not specified
{
if (GetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ) == itr->m_PreviousType)
{
// Current world age is bigger than/equal to target world age - delay time reached AND
// Previous block type was the same as current block type (to prevent duplication)
- SetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta); // SetMeta doesn't send to client
+ SetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta); // SetMeta doesn't send to client
itr = m_SetBlockQueue.erase(itr);
LOGD("Successfully set queued block - previous and current types matched");
}
@@ -778,7 +774,7 @@ void cChunk::CheckBlocks()
void cChunk::TickBlocks(void)
{
// Tick dem blocks
- // _X: We must limit the random number or else we get a nasty int overflow bug ( http://forum.mc-server.org/showthread.php?tid=457 )
+ // _X: We must limit the random number or else we get a nasty int overflow bug - http://forum.mc-server.org/showthread.php?tid=457
int RandomX = m_World->GetTickRandomNumber(0x00ffffff);
int RandomY = m_World->GetTickRandomNumber(0x00ffffff);
int RandomZ = m_World->GetTickRandomNumber(0x00ffffff);
@@ -807,7 +803,7 @@ void cChunk::TickBlocks(void)
if (m_BlockTickY > cChunkDef::GetHeight(m_HeightMap, m_BlockTickX, m_BlockTickZ))
{
- continue; // It's all air up here
+ continue; // It's all air up here
}
cBlockHandler * Handler = BlockHandler(GetBlock(m_BlockTickX, m_BlockTickY, m_BlockTickZ));
@@ -892,20 +888,19 @@ void cChunk::ApplyWeatherToTop()
SetBlock(X, Height, Z, E_BLOCK_ICE, 0);
}
else if (
- (m_World->IsDeepSnowEnabled()) &&
- (
- (TopBlock == E_BLOCK_RED_ROSE) ||
- (TopBlock == E_BLOCK_YELLOW_FLOWER) ||
- (TopBlock == E_BLOCK_RED_MUSHROOM) ||
- (TopBlock == E_BLOCK_BROWN_MUSHROOM)
- )
+ (m_World->IsDeepSnowEnabled()) &&
+ (
+ (TopBlock == E_BLOCK_RED_ROSE) ||
+ (TopBlock == E_BLOCK_YELLOW_FLOWER) ||
+ (TopBlock == E_BLOCK_RED_MUSHROOM) ||
+ (TopBlock == E_BLOCK_BROWN_MUSHROOM)
)
+ )
{
SetBlock(X, Height, Z, E_BLOCK_SNOW, 0);
}
break;
} // case (snowy biomes)
- // TODO: Rainy biomes should check for farmland and cauldrons
default:
{
break;
@@ -941,10 +936,10 @@ void cChunk::GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Bl
IsValid = IsValid && UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ + 1, BlockType[2], BlockMeta);
IsValid = IsValid && UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ - 1, BlockType[3], BlockMeta);
if (
- !IsValid ||
- (BlockType[0] == ProduceType) ||
- (BlockType[1] == ProduceType) ||
- (BlockType[2] == ProduceType) ||
+ !IsValid ||
+ (BlockType[0] == ProduceType) ||
+ (BlockType[1] == ProduceType) ||
+ (BlockType[2] == ProduceType) ||
(BlockType[3] == ProduceType)
)
{
@@ -1226,7 +1221,7 @@ bool cChunk::UnboundedRelSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE
}
Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
return true;
-}
+}
@@ -1298,6 +1293,7 @@ void cChunk::CreateBlockEntities(void)
switch (BlockType)
{
case E_BLOCK_BEACON:
+ case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_CHEST:
case E_BLOCK_COMMAND_BLOCK:
case E_BLOCK_DISPENSER:
@@ -1390,7 +1386,7 @@ void cChunk::CalculateHeightmap(const BLOCKTYPE * a_BlockTypes)
{
for (int y = Height - 1; y > -1; y--)
{
- int index = MakeIndex( x, y, z );
+ int index = MakeIndex( x, y, z);
if (a_BlockTypes[index] != E_BLOCK_AIR)
{
m_HeightMap[x + z * Width] = (HEIGHTTYPE)y;
@@ -1428,6 +1424,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
switch (a_BlockType)
{
case E_BLOCK_BEACON:
+ case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_CHEST:
case E_BLOCK_COMMAND_BLOCK:
case E_BLOCK_DISPENSER:
@@ -1525,11 +1522,12 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
m_ChunkData.SetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType);
- if ( // Queue block to be sent only if ...
- a_SendToClients && // ... we are told to do so AND ...
+ // Queue block to be sent only if ...
+ if (
+ a_SendToClients && // ... we are told to do so AND ...
(
- (OldBlockMeta != a_BlockMeta) || // ... the meta value is different OR ...
- !( // ... the old and new blocktypes AREN'T liquids (because client doesn't need to distinguish betwixt them); see below for specifics:
+ (OldBlockMeta != a_BlockMeta) || // ... the meta value is different OR ...
+ !( // ... the old and new blocktypes AREN'T liquids (because client doesn't need to distinguish betwixt them):
((OldBlockType == E_BLOCK_STATIONARY_WATER) && (a_BlockType == E_BLOCK_WATER)) || // Replacing stationary water with water
((OldBlockType == E_BLOCK_WATER) && (a_BlockType == E_BLOCK_STATIONARY_WATER)) || // Replacing water with stationary water
((OldBlockType == E_BLOCK_STATIONARY_LAVA) && (a_BlockType == E_BLOCK_LAVA)) || // Replacing stationary water with water
@@ -1722,11 +1720,11 @@ void cChunk::CollectPickupsByPlayer(cPlayer * a_Player)
{
if ((!(*itr)->IsPickup()) && (!(*itr)->IsProjectile()))
{
- continue; // Only pickups and projectiles
+ continue; // Only pickups and projectiles can be picked up
}
- float DiffX = (float)((*itr)->GetPosX() - PosX );
- float DiffY = (float)((*itr)->GetPosY() - PosY );
- float DiffZ = (float)((*itr)->GetPosZ() - PosZ );
+ float DiffX = (float)((*itr)->GetPosX() - PosX);
+ float DiffY = (float)((*itr)->GetPosY() - PosY);
+ float DiffZ = (float)((*itr)->GetPosZ() - PosZ);
float SqrDist = DiffX * DiffX + DiffY * DiffY + DiffZ * DiffZ;
if (SqrDist < 1.5f * 1.5f) // 1.5 block
{
@@ -1788,7 +1786,7 @@ bool cChunk::SetSignLines(int a_PosX, int a_PosY, int a_PosZ, const AString & a_
-void cChunk::RemoveBlockEntity( cBlockEntity* a_BlockEntity )
+void cChunk::RemoveBlockEntity( cBlockEntity* a_BlockEntity)
{
MarkDirty();
m_BlockEntities.remove(a_BlockEntity);
@@ -1798,7 +1796,7 @@ void cChunk::RemoveBlockEntity( cBlockEntity* a_BlockEntity )
-bool cChunk::AddClient(cClientHandle* a_Client)
+bool cChunk::AddClient(cClientHandle * a_Client)
{
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
@@ -1808,9 +1806,9 @@ bool cChunk::AddClient(cClientHandle* a_Client)
return false;
}
}
- m_LoadedByClient.push_back( a_Client );
+ m_LoadedByClient.push_back( a_Client);
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr )
+ for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
{
/*
// DEBUG:
@@ -1829,7 +1827,7 @@ bool cChunk::AddClient(cClientHandle* a_Client)
-void cChunk::RemoveClient( cClientHandle* a_Client )
+void cChunk::RemoveClient(cClientHandle * a_Client)
{
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
@@ -1837,12 +1835,12 @@ void cChunk::RemoveClient( cClientHandle* a_Client )
{
continue;
}
-
+
m_LoadedByClient.erase(itr);
if (!a_Client->IsDestroyed())
{
- for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr )
+ for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
{
/*
// DEBUG:
@@ -1862,7 +1860,7 @@ void cChunk::RemoveClient( cClientHandle* a_Client )
-bool cChunk::HasClient( cClientHandle* a_Client )
+bool cChunk::HasClient(cClientHandle * a_Client)
{
for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
@@ -1893,9 +1891,9 @@ void cChunk::AddEntity(cEntity * a_Entity)
{
MarkDirty();
}
-
+
ASSERT(std::find(m_Entities.begin(), m_Entities.end(), a_Entity) == m_Entities.end()); // Not there already
-
+
m_Entities.push_back(a_Entity);
}
@@ -1905,17 +1903,12 @@ void cChunk::AddEntity(cEntity * a_Entity)
void cChunk::RemoveEntity(cEntity * a_Entity)
{
- size_t SizeBefore = m_Entities.size();
m_Entities.remove(a_Entity);
- size_t SizeAfter = m_Entities.size();
-
- if (SizeBefore != SizeAfter)
+
+ // Mark as dirty if it was a server-generated entity:
+ if (!a_Entity->IsPlayer())
{
- // Mark as dirty if it was a server-generated entity:
- if (!a_Entity->IsPlayer())
- {
- MarkDirty();
- }
+ MarkDirty();
}
}
@@ -2137,6 +2130,77 @@ bool cChunk::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBloc
+bool cChunk::DoWithRedstonePoweredEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cRedstonePoweredCallback & a_Callback)
+{
+ // The blockentity list is locked by the parent chunkmap's CS
+ for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
+ {
+ ++itr2;
+ if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
+ {
+ continue;
+ }
+ switch ((*itr)->GetBlockType())
+ {
+ case E_BLOCK_DROPPER:
+ case E_BLOCK_DISPENSER:
+ case E_BLOCK_NOTE_BLOCK:
+ {
+ break;
+ }
+ default:
+ {
+ // There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
+ return false;
+ }
+ }
+
+ if (a_Callback.Item((cRedstonePoweredEntity *)*itr))
+ {
+ return false;
+ }
+ return true;
+ } // for itr - m_BlockEntitites[]
+
+ // Not found:
+ return false;
+}
+
+
+
+
+bool cChunk::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback)
+{
+ // The blockentity list is locked by the parent chunkmap's CS
+ for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), itr2 = itr; itr != m_BlockEntities.end(); itr = itr2)
+ {
+ ++itr2;
+ if (((*itr)->GetPosX() != a_BlockX) || ((*itr)->GetPosY() != a_BlockY) || ((*itr)->GetPosZ() != a_BlockZ))
+ {
+ continue;
+ }
+ if ((*itr)->GetBlockType() != E_BLOCK_BEACON)
+ {
+ // There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
+ return false;
+ }
+
+ // The correct block entity is here
+ if (a_Callback.Item((cBeaconEntity *)*itr))
+ {
+ return false;
+ }
+ return true;
+ } // for itr - m_BlockEntitites[]
+
+ // Not found:
+ return false;
+}
+
+
+
+
+
bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback)
{
// The blockentity list is locked by the parent chunkmap's CS
@@ -2147,7 +2211,7 @@ bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallb
{
continue;
}
- if ((*itr)->GetBlockType() != E_BLOCK_CHEST)
+ if (((*itr)->GetBlockType() != E_BLOCK_CHEST) && ((*itr)->GetBlockType() != E_BLOCK_TRAPPED_CHEST)) // Trapped chests use normal chests' handlers
{
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
return false;
@@ -2289,7 +2353,7 @@ bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC
}
} // switch (BlockType)
- // The correct block entity is here,
+ // The correct block entity is here,
if (a_Callback.Item((cFurnaceEntity *)*itr))
{
return false;
@@ -2321,7 +2385,7 @@ bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBl
return false;
}
- // The correct block entity is here,
+ // The correct block entity is here
if (a_Callback.Item((cNoteEntity *)*itr))
{
return false;
@@ -2353,7 +2417,7 @@ bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom
return false;
}
- // The correct block entity is here,
+ // The correct block entity is here,
if (a_Callback.Item((cCommandBlockEntity *)*itr))
{
return false;
@@ -2385,7 +2449,7 @@ bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadC
return false;
}
- // The correct block entity is here,
+ // The correct block entity is here,
if (a_Callback.Item((cMobHeadEntity *)*itr))
{
return false;
@@ -2417,7 +2481,7 @@ bool cChunk::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlower
return false;
}
- // The correct block entity is here,
+ // The correct block entity is here
if (a_Callback.Item((cFlowerPotEntity *)*itr))
{
return false;
@@ -2470,13 +2534,13 @@ bool cChunk::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_
BLOCKTYPE cChunk::GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
{
if (
- (a_RelX < 0) || (a_RelX >= Width) ||
+ (a_RelX < 0) || (a_RelX >= Width) ||
(a_RelY < 0) || (a_RelY >= Height) ||
(a_RelZ < 0) || (a_RelZ >= Width)
)
{
ASSERT(!"GetBlock(x, y, z) out of bounds!");
- return 0; // Clip
+ return 0; // Clip
}
return m_ChunkData.GetBlock(a_RelX, a_RelY, a_RelZ);
@@ -2527,8 +2591,8 @@ cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ)
{
int BlockX = m_PosX * cChunkDef::Width + a_RelX;
int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ;
- int BlockY, ChunkX, ChunkZ;
- AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
+ int ChunkX, ChunkZ;
+ BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
return m_ChunkMap->GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
}
@@ -2647,7 +2711,7 @@ cChunk * cChunk::GetRelNeighborChunkAdjustCoords(int & a_RelX, int & a_RelZ) con
void cChunk::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
(*itr)->SendAttachEntity(a_Entity, a_Vehicle);
} // for itr - LoadedByClient[]
@@ -2659,7 +2723,7 @@ void cChunk::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_V
void cChunk::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2675,7 +2739,7 @@ void cChunk::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char
void cChunk::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2697,7 +2761,7 @@ void cChunk::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cons
{
return;
}
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2713,7 +2777,7 @@ void cChunk::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cons
void cChunk::BroadcastChunkData(cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2729,7 +2793,7 @@ void cChunk::BroadcastChunkData(cChunkDataSerializer & a_Serializer, const cClie
void cChunk::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2745,7 +2809,7 @@ void cChunk::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_
void cChunk::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2761,7 +2825,7 @@ void cChunk::BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandl
void cChunk::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2777,7 +2841,7 @@ void cChunk::BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int
void cChunk::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2793,7 +2857,7 @@ void cChunk::BroadcastEntityEquipment(const cEntity & a_Entity, short a_SlotNum,
void cChunk::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2809,7 +2873,7 @@ void cChunk::BroadcastEntityHeadLook(const cEntity & a_Entity, const cClientHand
void cChunk::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2825,7 +2889,7 @@ void cChunk::BroadcastEntityLook(const cEntity & a_Entity, const cClientHandle *
void cChunk::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2841,7 +2905,7 @@ void cChunk::BroadcastEntityMetadata(const cEntity & a_Entity, const cClientHand
void cChunk::BroadcastEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2857,7 +2921,7 @@ void cChunk::BroadcastEntityRelMove(const cEntity & a_Entity, char a_RelX, char
void cChunk::BroadcastEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2873,7 +2937,7 @@ void cChunk::BroadcastEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, c
void cChunk::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2889,7 +2953,7 @@ void cChunk::BroadcastEntityStatus(const cEntity & a_Entity, char a_Status, cons
void cChunk::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2905,7 +2969,7 @@ void cChunk::BroadcastEntityVelocity(const cEntity & a_Entity, const cClientHand
void cChunk::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2921,7 +2985,7 @@ void cChunk::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation
void cChunk::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2937,7 +3001,7 @@ void cChunk::BroadcastParticleEffect(const AString & a_ParticleName, float a_Src
void cChunk::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2951,15 +3015,15 @@ void cChunk::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectI
-void cChunk::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
+void cChunk::BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
continue;
}
- (*itr)->SendSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch);
+ (*itr)->SendSoundEffect(a_SoundName, a_X, a_Y, a_Z, a_Volume, a_Pitch);
} // for itr - LoadedByClient[]
}
@@ -2969,7 +3033,7 @@ void cChunk::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a
void cChunk::BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -2985,7 +3049,7 @@ void cChunk::BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY
void cChunk::BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -3001,7 +3065,7 @@ void cChunk::BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Ex
void cChunk::BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
if (*itr == a_Exclude)
{
@@ -3015,9 +3079,9 @@ void cChunk::BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, cons
-void cChunk::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ )
+void cChunk::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
+ for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
(*itr)->SendUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ);
} // for itr - LoadedByClient[]
diff --git a/src/Chunk.h b/src/Chunk.h
index ededf62cd..72a1f6c95 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -28,6 +28,7 @@ class cServer;
class MTRand;
class cPlayer;
class cChunkMap;
+class cBeaconEntity;
class cChestEntity;
class cDispenserEntity;
class cFurnaceEntity;
@@ -42,9 +43,11 @@ class cBlockArea;
class cFluidSimulatorData;
class cMobCensus;
class cMobSpawner;
+class cRedstonePoweredEntity;
typedef std::list<cClientHandle *> cClientHandleList;
typedef cItemCallback<cEntity> cEntityCallback;
+typedef cItemCallback<cBeaconEntity> cBeaconCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
@@ -52,6 +55,7 @@ typedef cItemCallback<cNoteEntity> cNoteBlockCallback;
typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
typedef cItemCallback<cMobHeadEntity> cMobHeadCallback;
typedef cItemCallback<cFlowerPotEntity> cFlowerPotCallback;
+typedef cItemCallback<cRedstonePoweredEntity> cRedstonePoweredCallback;
@@ -82,12 +86,12 @@ public:
/*
To save a chunk, the WSSchema must:
- 1. Mark the chunk as being saved (MarkSaving() )
+ 1. Mark the chunk as being saved (MarkSaving())
2. Get the chunk's data using GetAllData()
- 3. Mark the chunk as saved (MarkSaved() )
+ 3. Mark the chunk as saved (MarkSaved())
If anywhere inside this sequence another thread mmodifies the chunk, the chunk will not get marked as saved in MarkSaved()
*/
- void MarkSaving(void); // Marks the chunk as being saved.
+ void MarkSaving(void); // Marks the chunk as being saved.
void MarkSaved(void); // Marks the chunk as saved, if it didn't change from the last call to MarkSaving()
void MarkLoaded(void); // Marks the chunk as freshly loaded. Fails if the chunk is already valid
void MarkLoadFailed(void); // Marks the chunk as failed to load. Ignored is the chunk is already valid
@@ -95,16 +99,10 @@ public:
/** Gets all chunk data, calls the a_Callback's methods for each data type */
void GetAllData(cChunkDataCallback & a_Callback);
- /** Sets all chunk data */
- void SetAllData(
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- const cChunkDef::BiomeMap & a_BiomeMap,
- cBlockEntityList & a_BlockEntities
- );
+ /** Sets all chunk data as either loaded from the storage or generated.
+ BlockLight and BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
+ Modifies the BlockEntity list in a_SetChunkData - moves the block entities into the chunk. */
+ void SetAllData(cSetChunkData & a_SetChunkData);
void SetLight(
const cChunkDef::BlockNibbles & a_BlockLight,
@@ -144,7 +142,7 @@ public:
void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients = true);
// SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense
- void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta ); }
+ void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta); }
/** Queues a block change till the specified world tick */
void QueueSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType = E_BLOCK_AIR);
@@ -195,7 +193,7 @@ public:
/** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */
bool SetSignLines(int a_RelX, int a_RelY, int a_RelZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
- int GetHeight( int a_X, int a_Z );
+ int GetHeight( int a_X, int a_Z);
void SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client);
@@ -241,6 +239,11 @@ public:
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
+
+ /** Calls the callback for the redstone powered entity at the specified coords; returns false if there's no redstone powered entity at those coords, true if found */
+ bool DoWithRedstonePoweredEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cRedstonePoweredCallback & a_Callback);
+ /** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
+ bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Lua-acessible
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible
@@ -274,7 +277,6 @@ public:
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z); // [x, y, z] in world block coords
- void CalculateLighting(); // Recalculate right now
void CalculateHeightmap(const BLOCKTYPE * a_BlockTypes);
// Broadcast various packets to all clients of this chunk:
@@ -298,11 +300,11 @@ public:
void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL);
void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL);
void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL);
- void BroadcastSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // a_Src coords are Block * 8
+ void BroadcastSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL);
void BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL);
void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL);
- void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ );
+ void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ);
void SendBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client);
@@ -312,7 +314,7 @@ public:
}
void PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ, int & a_BlockX, int & a_BlockY, int & a_BlockZ);
- Vector3i PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ );
+ Vector3i PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ);
inline void MarkDirty(void)
{
@@ -387,9 +389,9 @@ public:
cRedstoneSimulatorChunkData * GetRedstoneSimulatorData(void) { return &m_RedstoneSimulatorData; }
cRedstoneSimulatorChunkData * GetRedstoneSimulatorQueuedData(void) { return &m_RedstoneSimulatorQueuedData; }
cIncrementalRedstoneSimulator::PoweredBlocksList * GetRedstoneSimulatorPoweredBlocksList(void) { return &m_RedstoneSimulatorPoweredBlocksList; }
- cIncrementalRedstoneSimulator::LinkedBlocksList * GetRedstoneSimulatorLinkedBlocksList(void) { return &m_RedstoneSimulatorLinkedBlocksList; };
- cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList * GetRedstoneSimulatorSimulatedPlayerToggleableList(void) { return &m_RedstoneSimulatorSimulatedPlayerToggleableList; };
- cIncrementalRedstoneSimulator::RepeatersDelayList * GetRedstoneSimulatorRepeatersDelayList(void) { return &m_RedstoneSimulatorRepeatersDelayList; };
+ cIncrementalRedstoneSimulator::LinkedBlocksList * GetRedstoneSimulatorLinkedBlocksList(void) { return &m_RedstoneSimulatorLinkedBlocksList; }
+ cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList * GetRedstoneSimulatorSimulatedPlayerToggleableList(void) { return &m_RedstoneSimulatorSimulatedPlayerToggleableList; }
+ cIncrementalRedstoneSimulator::RepeatersDelayList * GetRedstoneSimulatorRepeatersDelayList(void) { return &m_RedstoneSimulatorRepeatersDelayList; }
bool IsRedstoneDirty(void) const { return m_IsRedstoneDirty; }
void SetIsRedstoneDirty(bool a_Flag) { m_IsRedstoneDirty = a_Flag; }
@@ -486,8 +488,8 @@ private:
// Pick up a random block of this chunk
- void getRandomBlockCoords(int& a_X, int& a_Y, int& a_Z);
- void getThreeRandomNumber(int& a_X, int& a_Y, int& a_Z,int a_MaxX, int a_MaxY, int a_MaxZ);
+ void GetRandomBlockCoords(int & a_X, int & a_Y, int & a_Z);
+ void GetThreeRandomNumbers(int & a_X, int & a_Y, int & a_Z, int a_MaxX, int a_MaxY, int a_MaxZ);
void RemoveBlockEntity(cBlockEntity * a_BlockEntity);
void AddBlockEntity (cBlockEntity * a_BlockEntity);
diff --git a/src/ChunkDataCallback.h b/src/ChunkDataCallback.h
index 0c8b1098f..804299816 100644
--- a/src/ChunkDataCallback.h
+++ b/src/ChunkDataCallback.h
@@ -25,29 +25,29 @@ public:
virtual ~cChunkDataCallback() {}
- /** Called before any other callbacks to inform of the current coords
- (only in processes where multiple chunks can be processed, such as cWorld::ForEachChunkInRect()).
+ /** Called before any other callbacks to inform of the current coords
+ (only in processes where multiple chunks can be processed, such as cWorld::ForEachChunkInRect()).
If false is returned, the chunk is skipped.
*/
- virtual bool Coords(int a_ChunkX, int a_ChunkZ) { UNUSED(a_ChunkX); UNUSED(a_ChunkZ); return true; };
+ virtual bool Coords(int a_ChunkX, int a_ChunkZ) { UNUSED(a_ChunkX); UNUSED(a_ChunkZ); return true; }
/// Called once to provide heightmap data
- virtual void HeightMap(const cChunkDef::HeightMap * a_HeightMap) {UNUSED(a_HeightMap); };
+ virtual void HeightMap(const cChunkDef::HeightMap * a_HeightMap) { UNUSED(a_HeightMap); }
/// Called once to provide biome data
- virtual void BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) {UNUSED(a_BiomeMap); };
+ virtual void BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) { UNUSED(a_BiomeMap); }
/// Called once to let know if the chunk lighting is valid. Return value is ignored
- virtual void LightIsValid(bool a_IsLightValid) {UNUSED(a_IsLightValid); };
+ virtual void LightIsValid(bool a_IsLightValid) { UNUSED(a_IsLightValid); }
/// Called once to export block info
- virtual void ChunkData(const cChunkData & a_Buffer) {UNUSED(a_Buffer); };
+ virtual void ChunkData(const cChunkData & a_Buffer) { UNUSED(a_Buffer); }
/// Called for each entity in the chunk
- virtual void Entity(cEntity * a_Entity) {UNUSED(a_Entity); };
+ virtual void Entity(cEntity * a_Entity) { UNUSED(a_Entity); }
/// Called for each blockentity in the chunk
- virtual void BlockEntity(cBlockEntity * a_Entity) {UNUSED(a_Entity); };
+ virtual void BlockEntity(cBlockEntity * a_Entity) { UNUSED(a_Entity); }
} ;
diff --git a/src/ChunkDef.h b/src/ChunkDef.h
index f89e16ed1..dbb782d26 100644
--- a/src/ChunkDef.h
+++ b/src/ChunkDef.h
@@ -22,8 +22,8 @@ It will help us when the new chunk format comes out and we need to patch everyth
#define ZERO_CHUNK_Y 0
// Used to smoothly convert to new axis ordering. One will be removed when deemed stable.
-#define AXIS_ORDER_YZX 1 // Original (1.1-)
-#define AXIS_ORDER_XZY 2 // New (1.2+)
+#define AXIS_ORDER_YZX 1 // Original (1.1-)
+#define AXIS_ORDER_XZY 2 // New (1.2+)
#define AXIS_ORDER AXIS_ORDER_XZY
@@ -72,7 +72,7 @@ public:
/// The type used for any heightmap operations and storage; idx = x + Width * z; Height points to the highest non-air block in the column
typedef HEIGHTTYPE HeightMap[Width * Width];
- /** The type used for any biomemap operations and storage inside MCServer,
+ /** The type used for any biomemap operations and storage inside MCServer,
using MCServer biomes (need not correspond to client representation!)
idx = x + Width * z // Need to verify this with the protocol spec, currently unknown!
*/
@@ -92,7 +92,7 @@ public:
/// Converts absolute block coords into relative (chunk + block) coords:
- inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ )
+ inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ)
{
UNUSED(a_Y);
BlockToChunk(a_X, a_Z, a_ChunkX, a_ChunkZ);
@@ -118,7 +118,7 @@ public:
}
- inline static int MakeIndex(int x, int y, int z )
+ inline static int MakeIndex(int x, int y, int z)
{
if (
(x < Width) && (x > -1) &&
@@ -138,27 +138,27 @@ public:
{
#if AXIS_ORDER == AXIS_ORDER_XZY
// For some reason, NOT using the Horner schema is faster. Weird.
- return x + (z * cChunkDef::Width) + (y * cChunkDef::Width * cChunkDef::Width); // 1.2 is XZY
+ return x + (z * cChunkDef::Width) + (y * cChunkDef::Width * cChunkDef::Width); // 1.2 uses XZY
#elif AXIS_ORDER == AXIS_ORDER_YZX
- return y + (z * cChunkDef::Width) + (x * cChunkDef::Height * cChunkDef::Width); // 1.1 is YZX
+ return y + (z * cChunkDef::Width) + (x * cChunkDef::Height * cChunkDef::Width); // 1.1 uses YZX
#endif
}
- inline static Vector3i IndexToCoordinate( unsigned int index )
+ inline static Vector3i IndexToCoordinate( unsigned int index)
{
#if AXIS_ORDER == AXIS_ORDER_XZY
- return Vector3i( // 1.2
- index % cChunkDef::Width, // X
- index / (cChunkDef::Width * cChunkDef::Width), // Y
- (index / cChunkDef::Width) % cChunkDef::Width // Z
- );
+ return Vector3i( // 1.2
+ index % cChunkDef::Width, // X
+ index / (cChunkDef::Width * cChunkDef::Width), // Y
+ (index / cChunkDef::Width) % cChunkDef::Width // Z
+ );
#elif AXIS_ORDER == AXIS_ORDER_YZX
- return Vector3i( // 1.1
- index / (cChunkDef::Height * cChunkDef::Width), // X
- index % cChunkDef::Height, // Y
- (index / cChunkDef::Height) % cChunkDef::Width // Z
- );
+ return Vector3i( // 1.1
+ index / (cChunkDef::Height * cChunkDef::Width), // X
+ index % cChunkDef::Height, // Y
+ (index / cChunkDef::Height) % cChunkDef::Width // Z
+ );
#endif
}
@@ -357,7 +357,7 @@ struct sSetBlock
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
- sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ); // absolute block position
+ sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // absolute block position
sSetBlock(int a_ChunkX, int a_ChunkZ, int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) :
x(a_X), y(a_Y), z(a_Z),
ChunkX(a_ChunkX), ChunkZ(a_ChunkZ),
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 687c0824f..dd8be0631 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -16,11 +16,12 @@
#include "MobCensus.h"
#include "MobSpawner.h"
#include "BoundingBox.h"
+#include "SetChunkData.h"
#include "Entities/Pickup.h"
#ifndef _WIN32
- #include <cstdlib> // abs
+ #include <cstdlib> // abs
#endif
#include "zlib/zlib.h"
@@ -33,14 +34,15 @@
////////////////////////////////////////////////////////////////////////////////
// cChunkMap:
-cChunkMap::cChunkMap(cWorld * a_World )
- : m_World( a_World ),
+cChunkMap::cChunkMap(cWorld * a_World) :
+ m_World(a_World),
m_Pool(
new cListAllocationPool<cChunkData::sChunkSection, 1600>(
std::auto_ptr<cAllocationPool<cChunkData::sChunkSection>::cStarvationCallbacks>(
- new cStarvationCallbacks())
+ new cStarvationCallbacks()
)
)
+ )
{
}
@@ -63,7 +65,7 @@ cChunkMap::~cChunkMap()
-void cChunkMap::RemoveLayer( cChunkLayer* a_Layer )
+void cChunkMap::RemoveLayer( cChunkLayer* a_Layer)
{
cCSLock Lock(m_CSLayers);
m_Layers.remove(a_Layer);
@@ -146,7 +148,7 @@ cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
// No need to lock m_CSLayers, since it's already locked by the operation that called us
ASSERT(m_CSLayers.IsLockedByCurrentThread());
- cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ );
+ cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
if (Layer == NULL)
{
// An error must have occurred, since layers are automatically created if they don't exist
@@ -169,10 +171,10 @@ cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
-cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ )
+cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
// No need to lock m_CSLayers, since it's already locked by the operation that called us
- cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ );
+ cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
if (Layer == NULL)
{
// An error must have occurred, since layers are automatically created if they don't exist
@@ -196,10 +198,10 @@ cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkY, int a_ChunkZ )
-cChunkPtr cChunkMap::GetChunkNoLoad( int a_ChunkX, int a_ChunkY, int a_ChunkZ )
+cChunkPtr cChunkMap::GetChunkNoLoad( int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
// No need to lock m_CSLayers, since it's already locked by the operation that called us
- cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ );
+ cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
if (Layer == NULL)
{
// An error must have occurred, since layers are automatically created if they don't exist
@@ -647,19 +649,19 @@ void cChunkMap::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_Effe
-void cChunkMap::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
+void cChunkMap::BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcZ / 8, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk((int)std::floor(a_X), (int)std::floor(a_Z), ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
return;
}
// It's perfectly legal to broadcast packets even to invalid chunks!
- Chunk->BroadcastSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch, a_Exclude);
+ Chunk->BroadcastSoundEffect(a_SoundName, a_X, a_Y, a_Z, a_Volume, a_Pitch, a_Exclude);
}
@@ -719,7 +721,7 @@ void cChunkMap::BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, c
-void cChunkMap::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ )
+void cChunkMap::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
@@ -847,7 +849,22 @@ void cChunkMap::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_M
-void cChunkMap::MarkChunkDirty (int a_ChunkX, int a_ChunkZ)
+void cChunkMap::MarkRedstoneDirty(int a_ChunkX, int a_ChunkZ)
+{
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
+ {
+ return;
+ }
+ Chunk->SetIsRedstoneDirty(true);
+}
+
+
+
+
+
+void cChunkMap::MarkChunkDirty(int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty)
{
cCSLock Lock(m_CSLayers);
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
@@ -856,6 +873,10 @@ void cChunkMap::MarkChunkDirty (int a_ChunkX, int a_ChunkZ)
return;
}
Chunk->MarkDirty();
+ if (a_MarkRedstoneDirty)
+ {
+ Chunk->SetIsRedstoneDirty(true);
+ }
}
@@ -892,28 +913,20 @@ void cChunkMap::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
-void cChunkMap::SetChunkData(
- int a_ChunkX, int a_ChunkZ,
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- const cChunkDef::BiomeMap & a_BiomeMap,
- cBlockEntityList & a_BlockEntities,
- bool a_MarkDirty
-)
+void cChunkMap::SetChunkData(cSetChunkData & a_SetChunkData)
{
+ int ChunkX = a_SetChunkData.GetChunkX();
+ int ChunkZ = a_SetChunkData.GetChunkZ();
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
if (Chunk == NULL)
{
return;
}
- Chunk->SetAllData(a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, a_HeightMap, a_BiomeMap, a_BlockEntities);
+ Chunk->SetAllData(a_SetChunkData);
- if (a_MarkDirty)
+ if (a_SetChunkData.ShouldMarkDirty())
{
Chunk->MarkDirty();
}
@@ -922,7 +935,7 @@ void cChunkMap::SetChunkData(
cChunkStays ToBeDisabled;
for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr)
{
- if ((*itr)->ChunkAvailable(a_ChunkX, a_ChunkZ))
+ if ((*itr)->ChunkAvailable(ChunkX, ChunkZ))
{
// The chunkstay wants to be disabled, add it to a list of to-be-disabled chunkstays for later processing:
ToBeDisabled.push_back(*itr);
@@ -937,7 +950,7 @@ void cChunkMap::SetChunkData(
}
// Notify plugins of the chunk becoming available
- cPluginManager::Get()->CallHookChunkAvailable(m_World, a_ChunkX, a_ChunkZ);
+ cPluginManager::Get()->CallHookChunkAvailable(m_World, ChunkX, ChunkZ);
}
@@ -1134,9 +1147,9 @@ void cChunkMap::CollectPickupsByPlayer(cPlayer * a_Player)
GetChunkNoLoad(ChunkX, ChunkY, ChunkZ)->CollectPickupsByPlayer(a_Player);
// Check the neighboring chunks as well:
- GetChunkNoLoad(OtherChunkX, ChunkY, ChunkZ )->CollectPickupsByPlayer(a_Player);
+ GetChunkNoLoad(OtherChunkX, ChunkY, ChunkZ)->CollectPickupsByPlayer (a_Player);
GetChunkNoLoad(OtherChunkX, ChunkY, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
- GetChunkNoLoad(ChunkX, ChunkY, ChunkZ )->CollectPickupsByPlayer(a_Player);
+ GetChunkNoLoad(ChunkX, ChunkY, ChunkZ)->CollectPickupsByPlayer (a_Player);
GetChunkNoLoad(ChunkX, ChunkY, OtherChunkZ)->CollectPickupsByPlayer(a_Player);
}
@@ -1161,7 +1174,7 @@ BLOCKTYPE cChunkMap::GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
} // for itr - m_FastSetBlockQueue[]
}
int ChunkX, ChunkZ;
- cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ );
+ cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
@@ -1190,11 +1203,11 @@ NIBBLETYPE cChunkMap::GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ)
} // for itr - m_FastSetBlockQueue[]
}
int ChunkX, ChunkZ;
- cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ );
+ cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
- if ((Chunk != NULL) && Chunk->IsValid() )
+ cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ if ((Chunk != NULL) && Chunk->IsValid())
{
return Chunk->GetMeta(a_BlockX, a_BlockY, a_BlockZ);
}
@@ -1208,11 +1221,11 @@ NIBBLETYPE cChunkMap::GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ)
NIBBLETYPE cChunkMap::GetBlockSkyLight(int a_BlockX, int a_BlockY, int a_BlockZ)
{
int ChunkX, ChunkZ;
- cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ );
+ cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
- if ((Chunk != NULL) && Chunk->IsValid() )
+ cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ if ((Chunk != NULL) && Chunk->IsValid())
{
return Chunk->GetSkyLight(a_BlockX, a_BlockY, a_BlockZ);
}
@@ -1226,11 +1239,11 @@ NIBBLETYPE cChunkMap::GetBlockSkyLight(int a_BlockX, int a_BlockY, int a_BlockZ)
NIBBLETYPE cChunkMap::GetBlockBlockLight(int a_BlockX, int a_BlockY, int a_BlockZ)
{
int ChunkX, ChunkZ;
- cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ );
+ cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
- if ((Chunk != NULL) && Chunk->IsValid() )
+ cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ if ((Chunk != NULL) && Chunk->IsValid())
{
return Chunk->GetBlockLight(a_BlockX, a_BlockY, a_BlockZ);
}
@@ -1259,7 +1272,7 @@ void cChunkMap::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYP
-void cChunkMap::SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, bool a_SendToClients)
+void cChunkMap::SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients)
{
cChunkInterface ChunkInterface(this);
if (a_BlockType == E_BLOCK_AIR)
@@ -1268,10 +1281,10 @@ void cChunkMap::SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a
}
int ChunkX, ChunkZ, X = a_BlockX, Y = a_BlockY, Z = a_BlockZ;
- cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ );
+ cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
+ cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->SetBlock(X, Y, Z, a_BlockType, a_BlockMeta, a_SendToClients);
@@ -1284,7 +1297,7 @@ void cChunkMap::SetBlock(cWorldInterface & a_WorldInterface, int a_BlockX, int a
-void cChunkMap::QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType)
+void cChunkMap::QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType)
{
int ChunkX, ChunkZ, X = a_BlockX, Y = a_BlockY, Z = a_BlockZ;
cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
@@ -1304,10 +1317,10 @@ void cChunkMap::QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYP
bool cChunkMap::GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
{
int ChunkX, ChunkZ, X = a_BlockX, Y = a_BlockY, Z = a_BlockZ;
- cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ );
+ cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
+ cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->GetBlockTypeMeta(X, Y, Z, a_BlockType, a_BlockMeta);
@@ -1323,10 +1336,10 @@ bool cChunkMap::GetBlockTypeMeta(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCK
bool cChunkMap::GetBlockInfo(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight)
{
int ChunkX, ChunkZ, X = a_BlockX, Y = a_BlockY, Z = a_BlockZ;
- cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ );
+ cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ);
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
+ cChunkPtr Chunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
if ((Chunk != NULL) && Chunk->IsValid())
{
Chunk->GetBlockInfo(X, Y, Z, a_BlockType, a_Meta, a_SkyLight, a_BlockLight);
@@ -1344,7 +1357,7 @@ void cChunkMap::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_Filt
cCSLock Lock(m_CSLayers);
for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
{
- cChunkPtr Chunk = GetChunk(itr->ChunkX, ZERO_CHUNK_Y, itr->ChunkZ );
+ cChunkPtr Chunk = GetChunk(itr->ChunkX, ZERO_CHUNK_Y, itr->ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
continue;
@@ -1365,7 +1378,7 @@ void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks)
cCSLock Lock(m_CSLayers);
for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
{
- cChunkPtr Chunk = GetChunk(itr->ChunkX, ZERO_CHUNK_Y, itr->ChunkZ );
+ cChunkPtr Chunk = GetChunk(itr->ChunkX, ZERO_CHUNK_Y, itr->ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
continue;
@@ -1478,7 +1491,7 @@ bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
cCSLock Lock(m_CSLayers);
for (sSetBlockVector::iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
{
- cChunkPtr Chunk = GetChunk(itr->ChunkX, ZERO_CHUNK_Y, itr->ChunkZ );
+ cChunkPtr Chunk = GetChunk(itr->ChunkX, ZERO_CHUNK_Y, itr->ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
if (!a_ContinueOnFailure)
@@ -1502,17 +1515,17 @@ bool cChunkMap::DigBlock(int a_X, int a_Y, int a_Z)
{
int PosX = a_X, PosY = a_Y, PosZ = a_Z, ChunkX, ChunkZ;
- cChunkDef::AbsoluteToRelative( PosX, PosY, PosZ, ChunkX, ChunkZ );
+ cChunkDef::AbsoluteToRelative( PosX, PosY, PosZ, ChunkX, ChunkZ);
{
cCSLock Lock(m_CSLayers);
- cChunkPtr DestChunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ );
+ cChunkPtr DestChunk = GetChunk( ChunkX, ZERO_CHUNK_Y, ChunkZ);
if ((DestChunk == NULL) || !DestChunk->IsValid())
{
return false;
}
- DestChunk->SetBlock(PosX, PosY, PosZ, E_BLOCK_AIR, 0 );
+ DestChunk->SetBlock(PosX, PosY, PosZ, E_BLOCK_AIR, 0);
m_World->GetSimulatorManager()->WakeUp(a_X, a_Y, a_Z, DestChunk);
}
@@ -1530,7 +1543,7 @@ void cChunkMap::SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player)
cCSLock Lock(m_CSLayers);
cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
- if (Chunk->IsValid())
+ if ((Chunk != NULL) && (Chunk->IsValid()))
{
Chunk->SendBlockTo(a_X, a_Y, a_Z, a_Player->GetClientHandle());
}
@@ -1717,7 +1730,9 @@ void cChunkMap::RemoveEntity(cEntity * a_Entity)
{
cCSLock Lock(m_CSLayers);
cChunkPtr Chunk = GetChunkNoGen(a_Entity->GetChunkX(), ZERO_CHUNK_Y, a_Entity->GetChunkZ());
- if ((Chunk == NULL) || !Chunk->IsValid())
+
+ // Even if a chunk is not valid, it may still contain entities such as players; make sure to remove them (#1190)
+ if (Chunk == NULL)
{
return;
}
@@ -1818,12 +1833,13 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
// Activate the TNT, with a random fuse between 10 to 30 game ticks
int FuseTime = 10 + m_World->GetTickRandomNumber(20);
m_World->SpawnPrimedTNT(a_BlockX + x + 0.5, a_BlockY + y + 0.5, a_BlockZ + z + 0.5, FuseTime);
- area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
+ area.SetBlockTypeMeta(bx + x, by + y, bz + z, E_BLOCK_AIR, 0);
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
break;
}
case E_BLOCK_OBSIDIAN:
+ case E_BLOCK_BEACON:
case E_BLOCK_BEDROCK:
case E_BLOCK_WATER:
case E_BLOCK_LAVA:
@@ -1854,15 +1870,15 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
default:
{
- if (m_World->GetTickRandomNumber(100) <= 25) // 25% chance of pickups
+ if (m_World->GetTickRandomNumber(100) <= 25) // 25% chance of pickups
{
cItems Drops;
cBlockHandler * Handler = BlockHandler(Block);
- Handler->ConvertToPickups(Drops, area.GetBlockMeta(bx + x, by + y, bz + z)); // Stone becomes cobblestone, coal ore becomes coal, etc.
+ Handler->ConvertToPickups(Drops, area.GetBlockMeta(bx + x, by + y, bz + z)); // Stone becomes cobblestone, coal ore becomes coal, etc.
m_World->SpawnItemPickups(Drops, bx + x, by + y, bz + z);
}
- else if ((m_World->GetTNTShrapnelLevel() > slNone) && (m_World->GetTickRandomNumber(100) < 20)) // 20% chance of flinging stuff around
+ else if ((m_World->GetTNTShrapnelLevel() > slNone) && (m_World->GetTickRandomNumber(100) < 20)) // 20% chance of flinging stuff around
{
if (!cBlockInfo::FullyOccupiesVoxel(Block))
{
@@ -1875,7 +1891,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
m_World->SpawnFallingBlock(bx + x, by + y + 5, bz + z, Block, area.GetBlockMeta(bx + x, by + y, bz + z));
}
- area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
+ area.SetBlockTypeMeta(bx + x, by + y, bz + z, E_BLOCK_AIR, 0);
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
break;
@@ -1902,7 +1918,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
{
if (a_Entity->IsPickup())
{
- if (((cPickup *)a_Entity)->GetAge() < 20) // If pickup age is smaller than one second, it is invincible (so we don't kill pickups that were just spawned)
+ if (((cPickup *)a_Entity)->GetAge() < 20) // If pickup age is smaller than one second, it is invincible (so we don't kill pickups that were just spawned)
{
return false;
}
@@ -1911,7 +1927,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
Vector3d EntityPos = a_Entity->GetPosition();
cBoundingBox bbEntity(EntityPos, a_Entity->GetWidth() / 2, a_Entity->GetHeight());
- if (!m_bbTNT.IsInside(bbEntity)) // IsInside actually acts like DoesSurround
+ if (!m_bbTNT.IsInside(bbEntity)) // IsInside actually acts like DoesSurround
{
return false;
}
@@ -1929,12 +1945,9 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
double FinalDamage = (((1 / AbsoluteEntityPos.x) + (1 / AbsoluteEntityPos.y) + (1 / AbsoluteEntityPos.z)) * 2) * m_ExplosionSize;
// Clip damage values
- if (FinalDamage > a_Entity->GetMaxHealth())
- FinalDamage = a_Entity->GetMaxHealth();
- else if (FinalDamage < 0)
- FinalDamage = 0;
+ FinalDamage = Clamp(FinalDamage, 0.0, (double)a_Entity->GetMaxHealth());
- if (!a_Entity->IsTNT() && !a_Entity->IsFallingBlock()) // Don't apply damage to other TNT entities and falling blocks, they should be invincible
+ if (!a_Entity->IsTNT() && !a_Entity->IsFallingBlock()) // Don't apply damage to other TNT entities and falling blocks, they should be invincible
{
a_Entity->TakeDamage(dtExplosion, NULL, (int)FinalDamage, 0);
}
@@ -2103,6 +2116,24 @@ bool cChunkMap::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cB
+bool cChunkMap::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback)
+{
+ int ChunkX, ChunkZ;
+ int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
+ cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
+ {
+ return false;
+ }
+ return Chunk->DoWithBeaconAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
+}
+
+
+
+
+
bool cChunkMap::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback)
{
int ChunkX, ChunkZ;
@@ -2692,14 +2723,14 @@ void cChunkMap::SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTi
// cChunkMap::cChunkLayer:
cChunkMap::cChunkLayer::cChunkLayer(
- int a_LayerX, int a_LayerZ,
+ int a_LayerX, int a_LayerZ,
cChunkMap * a_Parent,
cAllocationPool<cChunkData::sChunkSection> & a_Pool
)
- : m_LayerX( a_LayerX )
- , m_LayerZ( a_LayerZ )
- , m_Parent( a_Parent )
- , m_NumChunksLoaded( 0 )
+ : m_LayerX( a_LayerX)
+ , m_LayerZ( a_LayerZ)
+ , m_Parent( a_Parent)
+ , m_NumChunksLoaded( 0)
, m_Pool(a_Pool)
{
memset(m_Chunks, 0, sizeof(m_Chunks));
@@ -2714,7 +2745,7 @@ cChunkMap::cChunkLayer::~cChunkLayer()
for (size_t i = 0; i < ARRAYCOUNT(m_Chunks); ++i)
{
delete m_Chunks[i];
- m_Chunks[i] = NULL; // // Must zero out, because further chunk deletions query the chunkmap for entities and that would touch deleted data
+ m_Chunks[i] = NULL; // Must zero out, because further chunk deletions query the chunkmap for entities and that would touch deleted data
} // for i - m_Chunks[]
}
@@ -2722,7 +2753,7 @@ cChunkMap::cChunkLayer::~cChunkLayer()
-cChunkPtr cChunkMap::cChunkLayer::GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ )
+cChunkPtr cChunkMap::cChunkLayer::GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
// Always returns an assigned chunkptr, but the chunk needn't be valid (loaded / generated) - callers must check
@@ -2740,8 +2771,8 @@ cChunkPtr cChunkMap::cChunkLayer::GetChunk( int a_ChunkX, int a_ChunkY, int a_Ch
{
cChunk * neixm = (LocalX > 0) ? m_Chunks[Index - 1] : m_Parent->FindChunk(a_ChunkX - 1, a_ChunkZ);
cChunk * neixp = (LocalX < LAYER_SIZE - 1) ? m_Chunks[Index + 1] : m_Parent->FindChunk(a_ChunkX + 1, a_ChunkZ);
- cChunk * neizm = (LocalZ > 0) ? m_Chunks[Index - LAYER_SIZE] : m_Parent->FindChunk(a_ChunkX , a_ChunkZ - 1);
- cChunk * neizp = (LocalZ < LAYER_SIZE - 1) ? m_Chunks[Index + LAYER_SIZE] : m_Parent->FindChunk(a_ChunkX , a_ChunkZ + 1);
+ cChunk * neizm = (LocalZ > 0) ? m_Chunks[Index - LAYER_SIZE] : m_Parent->FindChunk(a_ChunkX, a_ChunkZ - 1);
+ cChunk * neizp = (LocalZ < LAYER_SIZE - 1) ? m_Chunks[Index + LAYER_SIZE] : m_Parent->FindChunk(a_ChunkX, a_ChunkZ + 1);
m_Chunks[Index] = new cChunk(a_ChunkX, 0, a_ChunkZ, m_Parent, m_Parent->GetWorld(), neixm, neixp, neizm, neizp, m_Pool);
}
return m_Chunks[Index];
@@ -2904,7 +2935,7 @@ int cChunkMap::cChunkLayer::GetNumChunksLoaded(void) const
NumChunks++;
}
} // for i - m_Chunks[]
- return NumChunks;
+ return NumChunks;
}
@@ -2975,7 +3006,7 @@ void cChunkMap::cChunkLayer::UnloadUnusedChunks(void)
void cChunkMap::FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
cCSLock Lock(m_CSFastSetBlock);
- m_FastSetBlockQueue.push_back(sSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta));
+ m_FastSetBlockQueue.push_back(sSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta));
}
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index b8870dfca..1e9a0f982 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -19,6 +19,7 @@ class MTRand;
class cChunkStay;
class cChunk;
class cPlayer;
+class cBeaconEntity;
class cChestEntity;
class cDispenserEntity;
class cDropperEntity;
@@ -34,11 +35,13 @@ class cChunkDataSerializer;
class cBlockArea;
class cMobCensus;
class cMobSpawner;
+class cSetChunkData;
typedef std::list<cClientHandle *> cClientHandleList;
typedef cChunk * cChunkPtr;
typedef cItemCallback<cEntity> cEntityCallback;
typedef cItemCallback<cBlockEntity> cBlockEntityCallback;
+typedef cItemCallback<cBeaconEntity> cBeaconCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cDropperEntity> cDropperCallback;
@@ -60,7 +63,7 @@ public:
static const int LAYER_SIZE = 32;
- cChunkMap(cWorld* a_World );
+ cChunkMap(cWorld* a_World);
~cChunkMap();
// Broadcast respective packets to all clients of the chunk where the event is taking place
@@ -85,11 +88,11 @@ public:
void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL);
void BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL);
void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL);
- void BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // a_Src coords are Block * 8
+ void BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL);
void BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL);
void BroadcastSpawnEntity(cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL);
- void BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ );
+ void BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ);
/** Sends the block entity, if it is at the coords specified, to a_Client */
void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client);
@@ -106,27 +109,17 @@ public:
/** Wakes up the simulators for the specified area of blocks */
void WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ);
- void MarkChunkDirty (int a_ChunkX, int a_ChunkZ);
+ void MarkRedstoneDirty (int a_ChunkX, int a_ChunkZ);
+ void MarkChunkDirty (int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty = false);
void MarkChunkSaving (int a_ChunkX, int a_ChunkZ);
void MarkChunkSaved (int a_ChunkX, int a_ChunkZ);
/** Sets the chunk data as either loaded from the storage or generated.
- a_BlockLight and a_BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
- a_BiomeMap is optional, if not present, biomes will be calculated by the generator
- a_HeightMap is optional, if not present, will be calculated.
- If a_MarkDirty is set, the chunk is set as dirty (used after generating)
+ BlockLight and BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
+ If MarkDirty is set, the chunk is set as dirty (used after generating)
+ Modifies the BlockEntity list in a_SetChunkData - moves the block entities into the chunk.
*/
- void SetChunkData(
- int a_ChunkX, int a_ChunkZ,
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- const cChunkDef::BiomeMap & a_BiomeMap,
- cBlockEntityList & a_BlockEntities,
- bool a_MarkDirty
- );
+ void SetChunkData(cSetChunkData & a_SetChunkData);
void ChunkLighted(
int a_ChunkX, int a_ChunkZ,
@@ -153,9 +146,9 @@ public:
NIBBLETYPE GetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ);
NIBBLETYPE GetBlockSkyLight (int a_BlockX, int a_BlockY, int a_BlockZ);
NIBBLETYPE GetBlockBlockLight(int a_BlockX, int a_BlockY, int a_BlockZ);
- void SetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockMeta);
- void SetBlock (cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, bool a_SendToClients = true);
- void QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType = E_BLOCK_AIR);
+ void SetBlockMeta (int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta);
+ void SetBlock (cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients = true);
+ void QueueSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType = E_BLOCK_AIR);
bool GetBlockTypeMeta (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
bool GetBlockInfo (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight);
@@ -243,6 +236,9 @@ public:
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
+ /** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
+ bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Lua-acessible
+
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Lua-acessible
@@ -288,7 +284,7 @@ public:
/** Sets the sign text. Returns true if sign text changed. */
bool SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
- /** Marks the chunk as being regenerated - all its clients want that chunk again (used by cWorld::RegenerateChunk() ) */
+ /** Marks the chunk as being regenerated - all its clients want that chunk again (used by cWorld::RegenerateChunk()) */
void MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ);
bool IsChunkLighted(int a_ChunkX, int a_ChunkZ);
@@ -360,14 +356,14 @@ private:
{
public:
cChunkLayer(
- int a_LayerX, int a_LayerZ,
+ int a_LayerX, int a_LayerZ,
cChunkMap * a_Parent,
cAllocationPool<cChunkData::sChunkSection> & a_Pool
);
~cChunkLayer();
/** Always returns an assigned chunkptr, but the chunk needn't be valid (loaded / generated) - callers must check */
- cChunkPtr GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ );
+ cChunkPtr GetChunk( int a_ChunkX, int a_ChunkY, int a_ChunkZ);
/** Returns the specified chunk, or NULL if not created yet */
cChunk * FindChunk(int a_ChunkX, int a_ChunkZ);
@@ -383,7 +379,7 @@ private:
void UnloadUnusedChunks(void);
/** Collect a mob census, of all mobs, their megatype, their chunk and their distance o closest player */
- void CollectMobCensus(cMobCensus& a_ToFill);
+ void CollectMobCensus(cMobCensus& a_ToFill);
/** Try to Spawn Monsters inside all Chunks */
void SpawnMobs(cMobSpawner& a_MobSpawner);
diff --git a/src/ChunkSender.cpp b/src/ChunkSender.cpp
index 2425adf18..ebcf0e272 100644
--- a/src/ChunkSender.cpp
+++ b/src/ChunkSender.cpp
@@ -17,7 +17,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cNotifyChunkSender:
void cNotifyChunkSender::Call(int a_ChunkX, int a_ChunkZ)
@@ -29,7 +29,7 @@ void cNotifyChunkSender::Call(int a_ChunkX, int a_ChunkZ)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cChunkSender:
cChunkSender::cChunkSender(void) :
diff --git a/src/ChunkSender.h b/src/ChunkSender.h
index 00565d7c3..624a3a0bd 100644
--- a/src/ChunkSender.h
+++ b/src/ChunkSender.h
@@ -6,17 +6,17 @@
/*
The whole thing is a thread that runs in a loop, waiting for either:
"finished chunks" (ChunkReady()), or
- "chunks to send" (QueueSendChunkTo() )
-to come to a queue.
+ "chunks to send" (QueueSendChunkTo())
+to come to a queue.
And once they do, it requests the chunk data and sends it all away, either
broadcasting (ChunkReady), or
sends to a specific client (QueueSendChunkTo)
Chunk data is queried using the cChunkDataCallback interface.
It is cached inside the ChunkSender object during the query and then processed after the query ends.
-Note that the data needs to be compressed only *after* the query finishes,
+Note that the data needs to be compressed only *after* the query finishes,
because the query callbacks run with ChunkMap's CS locked.
-A client may remove itself from all direct requests(QueueSendChunkTo()) by calling RemoveClient();
+A client may remove itself from all direct requests(QueueSendChunkTo()) by calling RemoveClient();
this ensures that the client's Send() won't be called anymore by ChunkSender.
Note that it may be called by world's BroadcastToChunk() if the client is still in the chunk.
*/
@@ -110,7 +110,7 @@ protected:
bool operator ==(const sSendChunk & a_Other)
{
return (
- (a_Other.m_ChunkX == m_ChunkX) &&
+ (a_Other.m_ChunkX == m_ChunkX) &&
(a_Other.m_ChunkY == m_ChunkY) &&
(a_Other.m_ChunkZ == m_ChunkZ) &&
(a_Other.m_Client == m_Client)
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index efa734b44..d386f3576 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -7,6 +7,7 @@
#include "Bindings/PluginManager.h"
#include "Entities/Player.h"
#include "Inventory.h"
+#include "BlockEntities/BeaconEntity.h"
#include "BlockEntities/ChestEntity.h"
#include "BlockEntities/CommandBlockEntity.h"
#include "BlockEntities/SignEntity.h"
@@ -40,9 +41,6 @@
/** Maximum number of block change interactions a player can perform per tick - exceeding this causes a kick */
#define MAX_BLOCK_CHANGE_INTERACTIONS 20
-/** How many ticks before the socket is closed after the client is destroyed (#31) */
-static const int TICKS_BEFORE_CLOSE = 20;
-
@@ -63,7 +61,7 @@ int cClientHandle::s_ClientCount = 0;
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cClientHandle:
cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) :
@@ -79,7 +77,6 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) :
m_PingID(1),
m_BlockDigAnimStage(-1),
m_HasStartedDigging(false),
- m_TicksSinceDestruction(0),
m_State(csConnected),
m_ShouldCheckDownloaded(false),
m_NumExplosionsThisTick(0),
@@ -89,7 +86,7 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) :
{
m_Protocol = new cProtocolRecognizer(this);
- s_ClientCount++; // Not protected by CS because clients are always constructed from the same thread
+ s_ClientCount++; // Not protected by CS because clients are always constructed from the same thread
m_UniqueID = s_ClientCount;
cTimer t1;
@@ -104,7 +101,7 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) :
cClientHandle::~cClientHandle()
{
- ASSERT(m_State >= csDestroyedWaiting); // Has Destroy() been called?
+ ASSERT(m_State == csDestroyed); // Has Destroy() been called?
LOGD("Deleting client \"%s\" at %p", GetUsername().c_str(), this);
@@ -124,7 +121,7 @@ cClientHandle::~cClientHandle()
}
if (World != NULL)
{
- World->RemovePlayer(m_Player);
+ World->RemovePlayer(m_Player, true); // Must be called before cPlayer::Destroy() as otherwise cChunk tries to delete the player, and then we do it again
m_Player->Destroy();
}
delete m_Player;
@@ -169,7 +166,7 @@ void cClientHandle::Destroy(void)
RemoveFromAllChunks();
m_Player->GetWorld()->RemoveClientFromChunkSender(this);
}
- m_State = csDestroyedWaiting;
+ m_State = csDestroyed;
}
@@ -214,11 +211,11 @@ AString cClientHandle::FormatMessageType(bool ShouldAppendChatPrefixes, eMessage
{
if (ShouldAppendChatPrefixes)
{
- return Printf("%s[MSG: %s] %s%s", cChatColor::LightBlue.c_str(), a_AdditionalData.c_str(), cChatColor::White.c_str(), cChatColor::Italic.c_str());
+ return Printf("%s[MSG: %s] %s%s", cChatColor::LightBlue, a_AdditionalData.c_str(), cChatColor::White, cChatColor::Italic);
}
else
{
- return Printf("%s: %s", a_AdditionalData.c_str(), cChatColor::LightBlue.c_str());
+ return Printf("%s: %s", a_AdditionalData.c_str(), cChatColor::LightBlue);
}
}
}
@@ -237,13 +234,14 @@ AString cClientHandle::GenerateOfflineUUID(const AString & a_Username)
// This guarantees that they will never collide with an online UUID and can be distinguished.
// Proper format for a version 3 UUID is:
// xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal digit and y is one of 8, 9, A, or B
+ // Note that we generate a short UUID (without the dashes)
// Generate an md5 checksum, and use it as base for the ID:
unsigned char MD5[16];
md5((const unsigned char *)a_Username.c_str(), a_Username.length(), MD5);
MD5[6] &= 0x0f; // Need to trim to 4 bits only...
MD5[8] &= 0x0f; // ... otherwise %01x overflows into two chars
- return Printf("%02x%02x%02x%02x-%02x%02x-3%01x%02x-8%01x%02x-%02x%02x%02x%02x%02x%02x",
+ return Printf("%02x%02x%02x%02x%02x%02x3%01x%02x8%01x%02x%02x%02x%02x%02x%02x%02x",
MD5[0], MD5[1], MD5[2], MD5[3],
MD5[4], MD5[5], MD5[6], MD5[7],
MD5[8], MD5[9], MD5[10], MD5[11],
@@ -294,17 +292,18 @@ void cClientHandle::Kick(const AString & a_Reason)
-void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID)
+void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID, const Json::Value & a_Properties)
{
if (m_State != csAuthenticating)
{
return;
}
- ASSERT( m_Player == NULL );
+ ASSERT(m_Player == NULL);
m_Username = a_Name;
m_UUID = a_UUID;
+ m_Properties = a_Properties;
// Send login success (if the protocol supports it):
m_Protocol->SendLoginSuccess();
@@ -328,7 +327,7 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID)
if (!cRoot::Get()->GetPluginManager()->CallHookPlayerJoined(*m_Player))
{
cRoot::Get()->BroadcastChatJoin(Printf("%s has joined the game", GetUsername().c_str()));
- LOGINFO("Player %s has joined the game.", m_Username.c_str());
+ LOGINFO("Player %s has joined the game", m_Username.c_str());
}
m_ConfirmPosition = m_Player->GetPosition();
@@ -342,8 +341,8 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID)
m_Protocol->SendWeather(World->GetWeather());
}
- // Send time
- m_Protocol->SendTimeUpdate(World->GetWorldAge(), World->GetTimeOfDay());
+ // Send time:
+ m_Protocol->SendTimeUpdate(World->GetWorldAge(), World->GetTimeOfDay(), World->IsDaylightCycleEnabled());
// Send contents of the inventory window
m_Protocol->SendWholeInventory(*m_Player->GetWindow());
@@ -534,11 +533,11 @@ void cClientHandle::HandlePing(void)
AString Reply;
const cServer & Server = *cRoot::Get()->GetServer();
- Printf(Reply, "%s%s%i%s%i",
+ Printf(Reply, "%s%s%i%s%i",
Server.GetDescription().c_str(),
- cChatColor::Delimiter.c_str(),
+ cChatColor::Delimiter,
Server.GetNumPlayers(),
- cChatColor::Delimiter.c_str(),
+ cChatColor::Delimiter,
Server.GetMaxPlayers()
);
Kick(Reply);
@@ -592,7 +591,7 @@ void cClientHandle::HandleCreativeInventory(short a_SlotNum, const cItem & a_Hel
void cClientHandle::HandlePlayerAbilities(bool a_CanFly, bool a_IsFlying, float FlyingSpeed, float WalkingSpeed)
{
- UNUSED(FlyingSpeed); // Ignore the client values for these
+ UNUSED(FlyingSpeed); // Ignore the client values for these
UNUSED(WalkingSpeed);
m_Player->SetCanFly(a_CanFly);
@@ -637,6 +636,7 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
if (!m_Player->IsSwimming())
{
+ m_Player->GetStatManager().AddValue(statJumps, 1);
m_Player->AddFoodExhaustion(m_Player->IsSprinting() ? 0.8 : 0.2);
}
}
@@ -662,6 +662,10 @@ void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString
// Client <-> Server branding exchange
SendPluginMessage("MC|Brand", "MCServer");
}
+ else if (a_Channel == "MC|Beacon")
+ {
+ HandleBeaconSelection(a_Message.c_str(), a_Message.size());
+ }
else if (a_Channel == "MC|ItemName")
{
HandleAnvilItemName(a_Message.c_str(), a_Message.size());
@@ -671,7 +675,7 @@ void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString
if (HasPluginChannel(a_Channel))
{
SendPluginMessage("UNREGISTER", a_Channel);
- return; // Can't register again if already taken - kinda defeats the point of plugin messaging!
+ return; // Can't register again if already taken - kinda defeats the point of plugin messaging!
}
RegisterPluginChannels(BreakApartPluginChannels(a_Message));
@@ -749,6 +753,70 @@ void cClientHandle::UnregisterPluginChannels(const AStringVector & a_ChannelList
+void cClientHandle::HandleBeaconSelection(const char * a_Data, size_t a_Length)
+{
+ if (a_Length < 14)
+ {
+ SendChat("Failure setting beacon selection; bad request", mtFailure);
+ LOGD("Malformed MC|Beacon packet.");
+ return;
+ }
+
+ cWindow * Window = m_Player->GetWindow();
+ if ((Window == NULL) || (Window->GetWindowType() != cWindow::wtBeacon))
+ {
+ return;
+ }
+ cBeaconWindow * BeaconWindow = (cBeaconWindow *) Window;
+
+ if (Window->GetSlot(*m_Player, 0)->IsEmpty())
+ {
+ return;
+ }
+
+ cByteBuffer Buffer(a_Length);
+ Buffer.Write(a_Data, a_Length);
+
+ int PrimaryEffectID, SecondaryEffectID;
+ Buffer.ReadBEInt(PrimaryEffectID);
+ Buffer.ReadBEInt(SecondaryEffectID);
+
+ cEntityEffect::eType PrimaryEffect = cEntityEffect::effNoEffect;
+ if ((PrimaryEffectID >= 0) && (PrimaryEffectID <= (int)cEntityEffect::effSaturation))
+ {
+ PrimaryEffect = (cEntityEffect::eType)PrimaryEffectID;
+ }
+
+ cEntityEffect::eType SecondaryEffect = cEntityEffect::effNoEffect;
+ if ((SecondaryEffectID >= 0) && (SecondaryEffectID <= (int)cEntityEffect::effSaturation))
+ {
+ SecondaryEffect = (cEntityEffect::eType)SecondaryEffectID;
+ }
+
+ Window->SetSlot(*m_Player, 0, cItem());
+ BeaconWindow->GetBeaconEntity()->SetPrimaryEffect(PrimaryEffect);
+
+ // Valid effect check. Vanilla don't check this, but we do it :)
+ if (
+ (SecondaryEffect == cEntityEffect::effNoEffect) ||
+ (SecondaryEffect == cEntityEffect::effRegeneration) ||
+ (SecondaryEffect == BeaconWindow->GetBeaconEntity()->GetPrimaryEffect())
+ )
+ {
+ BeaconWindow->GetBeaconEntity()->SetSecondaryEffect(SecondaryEffect);
+ }
+ else
+ {
+ BeaconWindow->GetBeaconEntity()->SetSecondaryEffect(cEntityEffect::effNoEffect);
+ }
+
+ m_Player->CloseWindow(true);
+}
+
+
+
+
+
void cClientHandle::HandleCommandBlockMessage(const char * a_Data, size_t a_Length)
{
if (a_Length < 14)
@@ -845,13 +913,17 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB
}
if (
- ((a_Status == DIG_STATUS_STARTED) || (a_Status == DIG_STATUS_FINISHED)) && // Only do a radius check for block destruction - things like pickup tossing send coordinates that are to be ignored
+ ((a_Status == DIG_STATUS_STARTED) || (a_Status == DIG_STATUS_FINISHED)) && // Only do a radius check for block destruction - things like pickup tossing send coordinates that are to be ignored
((Diff(m_Player->GetPosX(), (double)a_BlockX) > 6) ||
(Diff(m_Player->GetPosY(), (double)a_BlockY) > 6) ||
(Diff(m_Player->GetPosZ(), (double)a_BlockZ) > 6))
)
{
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
+ if (cBlockInfo::GetHandler(m_Player->GetWorld()->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ))->IsClickedThrough())
+ {
+ m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player);
+ }
return;
}
@@ -860,6 +932,10 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB
{
// A plugin doesn't agree with the action, replace the block on the client and quit:
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
+ if (cBlockInfo::GetHandler(m_Player->GetWorld()->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ))->IsClickedThrough())
+ {
+ m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player);
+ }
return;
}
@@ -880,7 +956,7 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB
case DIG_STATUS_SHOOT_EAT:
{
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(m_Player->GetEquippedItem());
- if (ItemHandler->IsFood())
+ if (ItemHandler->IsFood() || ItemHandler->IsDrinkable(m_Player->GetEquippedItem().m_ItemDamage))
{
m_Player->AbortEating();
return;
@@ -929,7 +1005,7 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB
// A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
return;
}
- m_Player->TossEquippedItem(64); // Toss entire slot - if there aren't enough items, the maximum will be ejected
+ m_Player->TossEquippedItem(64); // Toss entire slot - if there aren't enough items, the maximum will be ejected
return;
}
@@ -992,7 +1068,7 @@ void cClientHandle::HandleBlockDigStarted(int a_BlockX, int a_BlockY, int a_Bloc
int pY = a_BlockY;
int pZ = a_BlockZ;
- AddFaceDirection(pX, pY, pZ, a_BlockFace); // Get the block in front of the clicked coordinates (m_bInverse defaulted to false)
+ AddFaceDirection(pX, pY, pZ, a_BlockFace); // Get the block in front of the clicked coordinates (m_bInverse defaulted to false)
cBlockHandler * Handler = cBlockInfo::GetHandler(m_Player->GetWorld()->GetBlock(pX, pY, pZ));
if (Handler->IsClickedThrough())
@@ -1070,10 +1146,11 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo
return;
}
+ m_Player->AddFoodExhaustion(0.025);
ItemHandler->OnBlockDestroyed(World, m_Player, m_Player->GetEquippedItem(), a_BlockX, a_BlockY, a_BlockZ);
// The ItemHandler is also responsible for spawning the pickups
cChunkInterface ChunkInterface(World->GetChunkMap());
- BlockHandler(a_OldBlock)->OnDestroyedByPlayer(ChunkInterface,*World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
+ BlockHandler(a_OldBlock)->OnDestroyedByPlayer(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
World->BroadcastSoundParticleEffect(2001, a_BlockX, a_BlockY, a_BlockZ, a_OldBlock, this);
World->DigBlock(a_BlockX, a_BlockY, a_BlockZ);
@@ -1086,7 +1163,7 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo
void cClientHandle::FinishDigAnimation()
{
- if (!m_HasStartedDigging) // Hasn't received the DIG_STARTED packet
+ if (!m_HasStartedDigging) // Hasn't received the DIG_STARTED packet
{
return;
}
@@ -1172,8 +1249,8 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
if ((Equipped.m_ItemType != a_HeldItem.m_ItemType) && (a_HeldItem.m_ItemType != -1))
{
// Only compare ItemType, not meta (torches have different metas)
- // The -1 check is there because sometimes the client sends -1 instead of the held item
- // ( http://forum.mc-server.org/showthread.php?tid=549&pid=4502#pid4502 )
+ // The -1 check is there because sometimes the client sends -1 instead of the held item
+ // Ref.: http://forum.mc-server.org/showthread.php?tid=549&pid=4502#pid4502
LOGWARN("Player %s tried to place a block that was not equipped (exp %d, got %d)",
m_Username.c_str(), Equipped.m_ItemType, a_HeldItem.m_ItemType
);
@@ -1205,17 +1282,19 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
return;
}
+ short EquippedDamage = Equipped.m_ItemDamage;
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(Equipped.m_ItemType);
if (ItemHandler->IsPlaceable() && (a_BlockFace != BLOCK_FACE_NONE))
{
HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler);
}
- else if (ItemHandler->IsFood() && !m_Player->IsGameModeCreative())
+ else if ((ItemHandler->IsFood() || ItemHandler->IsDrinkable(EquippedDamage)))
{
- if (m_Player->IsSatiated())
+ if ((m_Player->IsSatiated() || m_Player->IsGameModeCreative()) &&
+ ItemHandler->IsFood() && (Equipped.m_ItemType != E_ITEM_GOLDEN_APPLE))
{
- // The player is satiated, they cannot eat
+ // The player is satiated or in creative, and trying to eat
return;
}
m_Player->StartEating();
@@ -1362,10 +1441,10 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, e
m_Player->GetInventory().RemoveOneEquippedItem();
}
cChunkInterface ChunkInterface(World->GetChunkMap());
- NewBlock->OnPlacedByPlayer(ChunkInterface,*World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
+ NewBlock->OnPlacedByPlayer(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
// Step sound with 0.8f pitch is used as block placement sound
- World->BroadcastSoundEffect(NewBlock->GetStepSound(), a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.8f);
+ World->BroadcastSoundEffect(NewBlock->GetStepSound(), (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0f, 0.8f);
cRoot::Get()->GetPluginManager()->CallHookPlayerPlacedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
}
@@ -1392,7 +1471,7 @@ void cClientHandle::HandleChat(const AString & a_Message)
Color = AString("@") + Color[2];
}
else
- {
+ {
Color.clear();
}
Msg.AddTextPart(AString("<") + m_Player->GetName() + "> ", Color);
@@ -1443,23 +1522,25 @@ void cClientHandle::HandleAnimation(char a_Animation)
// Because the animation ID sent to servers by clients are different to those sent back, we need this
switch (a_Animation)
{
- case 0: // No animation - wiki.vg doesn't say that client has something specific for it, so I suppose it will just become -1
+ case 0: // No animation - wiki.vg doesn't say that client has something specific for it, so I suppose it will just become -1
case 1:
case 2:
case 3:
{
- a_Animation--; // Offset by -1
+ a_Animation--; // Offset by -1
break;
}
- case 5:
+ case 5:
case 6:
case 7:
{
- a_Animation -= 2; // Offset by -2
+ a_Animation -= 2; // Offset by -2
break;
}
- default: // Anything else is the same
+ default: // Anything else is the same
+ {
break;
+ }
}
m_Player->GetWorld()->BroadcastEntityAnimation(*m_Player, a_Animation, this);
@@ -1519,8 +1600,8 @@ void cClientHandle::HandleWindowClick(char a_WindowID, short a_SlotNum, eClickAc
void cClientHandle::HandleUpdateSign(
- int a_BlockX, int a_BlockY, int a_BlockZ,
- const AString & a_Line1, const AString & a_Line2,
+ int a_BlockX, int a_BlockY, int a_BlockZ,
+ const AString & a_Line1, const AString & a_Line2,
const AString & a_Line3, const AString & a_Line4
)
{
@@ -1794,8 +1875,7 @@ void cClientHandle::RemoveFromWorld(void)
m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
} // for itr - Chunks[]
- // StreamChunks() called in cPlayer::MoveToWorld() after new world has been set
- // Meanwhile here, we set last streamed values to bogus ones so everything is resent
+ // Here, we set last streamed values to bogus ones so everything is resent
m_LastStreamedChunkX = 0x7fffffff;
m_LastStreamedChunkZ = 0x7fffffff;
m_HasSentPlayerChunk = false;
@@ -1824,17 +1904,6 @@ bool cClientHandle::CheckBlockInteractionsRate(void)
void cClientHandle::Tick(float a_Dt)
{
- // Handle clients that are waiting for final close while destroyed:
- if (m_State == csDestroyedWaiting)
- {
- m_TicksSinceDestruction += 1; // This field is misused for the timeout counting
- if (m_TicksSinceDestruction > TICKS_BEFORE_CLOSE)
- {
- m_State = csDestroyed;
- }
- return;
- }
-
// Process received network data:
AString IncomingData;
{
@@ -1901,14 +1970,6 @@ void cClientHandle::Tick(float a_Dt)
void cClientHandle::ServerTick(float a_Dt)
{
- // Handle clients that are waiting for final close while destroyed:
- if (m_State == csDestroyedWaiting)
- {
- // Do not wait while the client is not in the world, simply cut them off.
- m_State = csDestroyed;
- return;
- }
-
// Process received network data:
AString IncomingData;
{
@@ -1991,28 +2052,17 @@ void cClientHandle::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlock
void cClientHandle::SendChat(const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData)
{
- bool ShouldAppendChatPrefixes = true;
-
- if (GetPlayer()->GetWorld() == NULL)
+ cWorld * World = GetPlayer()->GetWorld();
+ if (World == NULL)
{
- cWorld * World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName());
+ World = cRoot::Get()->GetWorld(GetPlayer()->GetLoadedWorldName());
if (World == NULL)
{
World = cRoot::Get()->GetDefaultWorld();
}
-
- if (!World->ShouldUseChatPrefixes())
- {
- ShouldAppendChatPrefixes = false;
- }
- }
- else if (!GetPlayer()->GetWorld()->ShouldUseChatPrefixes())
- {
- ShouldAppendChatPrefixes = false;
}
- AString Message = FormatMessageType(ShouldAppendChatPrefixes, a_ChatPrefix, a_AdditionalData);
-
+ AString Message = FormatMessageType(World->ShouldUseChatPrefixes(), a_ChatPrefix, a_AdditionalData);
m_Protocol->SendChat(Message.append(a_Message));
}
@@ -2366,7 +2416,7 @@ void cClientHandle::SendPlayerSpawn(const cPlayer & a_Player)
return;
}
- LOGD("Spawning player \"%s\" on client \"%s\" @ %s",
+ LOGD("Spawning player \"%s\" on client \"%s\" @ %s",
a_Player.GetName().c_str(), GetPlayer()->GetName().c_str(), GetIPString().c_str()
);
@@ -2395,9 +2445,9 @@ void cClientHandle::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effec
-void cClientHandle::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
+void cClientHandle::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks)
{
- m_Protocol->SendRespawn(a_World, a_ShouldIgnoreDimensionChecks);
+ m_Protocol->SendRespawn(a_Dimension, a_ShouldIgnoreDimensionChecks);
}
@@ -2449,9 +2499,9 @@ void cClientHandle::SendDisplayObjective(const AString & a_Objective, cScoreboar
-void cClientHandle::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
+void cClientHandle::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch)
{
- m_Protocol->SendSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch);
+ m_Protocol->SendSoundEffect(a_SoundName, a_X, a_Y, a_Z, a_Volume, a_Pitch);
}
@@ -2494,7 +2544,7 @@ void cClientHandle::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType,
-void cClientHandle::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) // VehicleSubType is specific to Minecarts
+void cClientHandle::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) // VehicleSubType is specific to Minecarts
{
m_Protocol->SendSpawnVehicle(a_Vehicle, a_VehicleType, a_VehicleSubType);
}
@@ -2539,9 +2589,9 @@ void cClientHandle::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ)
-void cClientHandle::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay)
+void cClientHandle::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle)
{
- m_Protocol->SendTimeUpdate(a_WorldAge, a_TimeOfDay);
+ m_Protocol->SendTimeUpdate(a_WorldAge, a_TimeOfDay, a_DoDaylightCycle);
}
@@ -2580,7 +2630,7 @@ void cClientHandle::SendUpdateSign(
-void cClientHandle::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ )
+void cClientHandle::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
{
m_Protocol->SendUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ);
}
@@ -2642,7 +2692,7 @@ const AString & cClientHandle::GetUsername(void) const
-void cClientHandle::SetUsername( const AString & a_Username )
+void cClientHandle::SetUsername( const AString & a_Username)
{
m_Username = a_Username;
}
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 6f2c86b27..7ae70a07f 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -20,6 +20,7 @@
#include "Map.h"
#include "Enchantments.h"
#include "UI/SlotArea.h"
+#include "json/json.h"
@@ -47,7 +48,7 @@ class cStatManager;
class cClientHandle : // tolua_export
public cSocketThreads::cCallback
-{ // tolua_export
+{ // tolua_export
public:
#if defined(ANDROID_NDK)
@@ -55,18 +56,22 @@ public:
#else
static const int DEFAULT_VIEW_DISTANCE = 10;
#endif
- static const int MAX_VIEW_DISTANCE = 15;
- static const int MIN_VIEW_DISTANCE = 3;
+ static const int MAX_VIEW_DISTANCE = 32;
+ static const int MIN_VIEW_DISTANCE = 1;
cClientHandle(const cSocket * a_Socket, int a_ViewDistance);
virtual ~cClientHandle();
const AString & GetIPString(void) const { return m_IPString; }
- cPlayer * GetPlayer(void) { return m_Player; } // tolua_export
+ cPlayer * GetPlayer(void) { return m_Player; } // tolua_export
- const AString & GetUUID(void) const { return m_UUID; } // tolua_export
+ /** Returns the player's UUID, as used by the protocol, in the short form (no dashes) */
+ const AString & GetUUID(void) const { return m_UUID; } // tolua_export
+
void SetUUID(const AString & a_UUID) { m_UUID = a_UUID; }
+
+ const Json::Value & GetProperties(void) const { return m_Properties; }
/** Generates an UUID based on the username stored for this client, and stores it in the m_UUID member.
This is used for the offline (non-auth) mode, when there's no UUID source.
@@ -77,7 +82,7 @@ public:
/** Generates an UUID based on the player name provided.
This is used for the offline (non-auth) mode, when there's no UUID source.
Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same.
- Returns a 36-char UUID (with dashes). */
+ Returns a 32-char UUID (no dashes). */
static AString GenerateOfflineUUID(const AString & a_Username); // tolua_export
/** Returns true if the UUID is generated by online auth, false if it is an offline-generated UUID.
@@ -91,8 +96,10 @@ public:
static AString FormatChatPrefix(bool ShouldAppendChatPrefixes, AString a_ChatPrefixS, AString m_Color1, AString m_Color2);
- void Kick(const AString & a_Reason); // tolua_export
- void Authenticate(const AString & a_Name, const AString & a_UUID); // Called by cAuthenticator when the user passes authentication
+ void Kick(const AString & a_Reason); // tolua_export
+
+ /** Authenticates the specified user, called by cAuthenticator */
+ void Authenticate(const AString & a_Name, const AString & a_UUID, const Json::Value & a_Properties);
void StreamChunks(void);
@@ -118,7 +125,7 @@ public:
void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle);
void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType);
void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage);
- void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // tolua_export
+ void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // tolua_export
void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes);
void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = "");
void SendChat (const cCompositeChat & a_Message);
@@ -146,7 +153,7 @@ public:
void SendMapInfo (int a_ID, unsigned int a_Scale);
void SendPaintingSpawn (const cPainting & a_Painting);
void SendPickupSpawn (const cPickup & a_Pickup);
- void SendEntityAnimation (const cEntity & a_Entity, char a_Animation);
+ void SendEntityAnimation (const cEntity & a_Entity, char a_Animation); // tolua_export
void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount);
void SendPlayerAbilities (void);
void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline);
@@ -156,13 +163,13 @@ public:
void SendPlayerSpawn (const cPlayer & a_Player);
void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp
void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID);
- void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false);
+ void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks = false);
void SendExperience (void);
void SendExperienceOrb (const cExpOrb & a_ExpOrb);
void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode);
void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display);
- void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch); // a_Src coords are Block * 8
+ void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch); // tolua_export
void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data);
void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock);
void SendSpawnMob (const cMonster & a_Mob);
@@ -172,11 +179,11 @@ public:
void SendTabCompletionResults(const AStringVector & a_Results);
void SendTeleportEntity (const cEntity & a_Entity);
void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ);
- void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay);
+ void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle); // tolua_export
void SendUnloadChunk (int a_ChunkX, int a_ChunkZ);
void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity);
void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
- void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ );
+ void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ);
void SendWeather (eWeather a_Weather);
void SendWholeInventory (const cWindow & a_Window);
void SendWindowClose (const cWindow & a_Window);
@@ -185,7 +192,7 @@ public:
// tolua_begin
const AString & GetUsername(void) const;
- void SetUsername( const AString & a_Username );
+ void SetUsername( const AString & a_Username);
inline short GetPing(void) const { return m_Ping; }
@@ -241,8 +248,8 @@ public:
void HandleSteerVehicle (float Forward, float Sideways);
void HandleTabCompletion (const AString & a_Text);
void HandleUpdateSign (
- int a_BlockX, int a_BlockY, int a_BlockZ,
- const AString & a_Line1, const AString & a_Line2,
+ int a_BlockX, int a_BlockY, int a_BlockZ,
+ const AString & a_Line1, const AString & a_Line2,
const AString & a_Line3, const AString & a_Line4
);
void HandleUnmount (void);
@@ -266,20 +273,20 @@ public:
private:
- /** Handles the block placing packet when it is a real block placement (not block-using, item-using or eating) */
- void HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, cItemHandler & a_ItemHandler);
-
/** The type used for storing the names of registered plugin channels. */
typedef std::set<AString> cChannels;
- int m_ViewDistance; // Number of chunks the player can see in each direction; 4 is the minimum ( http://wiki.vg/Protocol_FAQ#.E2.80.A6all_connecting_clients_spasm_and_jerk_uncontrollably.21 )
+ /** Number of chunks the player can see in each direction */
+ int m_ViewDistance;
- static const int GENERATEDISTANCE = 2; // Server generates this many chunks AHEAD of player sight. 2 is the minimum, since foliage is generated 1 step behind chunk terrain generation
+ /** Server generates this many chunks AHEAD of player sight. */
+ static const int GENERATEDISTANCE = 2;
AString m_IPString;
AString m_Username;
AString m_Password;
+ Json::Value m_Properties;
cCriticalSection m_CSChunkLists;
cChunkCoordsList m_LoadedChunks; // Chunks that the player belongs to
@@ -311,7 +318,7 @@ private:
int m_PingID;
long long m_PingStartTime;
long long m_LastPingTime;
- static const unsigned short PING_TIME_MS = 1000; //minecraft sends 1 per 20 ticks (1 second or every 1000 ms)
+ static const unsigned short PING_TIME_MS = 1000; // Vanilla sends 1 per 20 ticks (1 second or every 1000 ms)
// Values required for block dig animation
int m_BlockDigAnimStage; // Current stage of the animation; -1 if not digging
@@ -325,9 +332,6 @@ private:
int m_LastDigBlockX;
int m_LastDigBlockY;
int m_LastDigBlockZ;
-
- /** Used while csDestroyedWaiting for counting the ticks until the connection is closed */
- int m_TicksSinceDestruction;
enum eState
{
@@ -335,10 +339,9 @@ private:
csAuthenticating, ///< The client has logged in, waiting for external authentication
csAuthenticated, ///< The client has been authenticated, will start streaming chunks in the next tick
csDownloadingWorld, ///< The client is waiting for chunks, we're waiting for the loader to provide and send them
- csConfirmingPos, ///< The client has been sent the position packet, waiting for them to repeat the position back
+ csConfirmingPos, ///< The client has been sent the position packet, waiting for them to repeat the position back
csPlaying, ///< Normal gameplay
csDestroying, ///< The client is being destroyed, don't queue any more packets / don't add to chunks
- csDestroyedWaiting, ///< The client has been destroyed, but is still kept so that the Kick packet is delivered (#31)
csDestroyed, ///< The client has been destroyed, the destructor is to be called from the owner thread
// TODO: Add Kicking here as well
@@ -359,7 +362,11 @@ private:
int m_NumBlockChangeInteractionsThisTick;
static int s_ClientCount;
+
+ /** ID used for identification during authenticating. Assigned sequentially for each new instance. */
int m_UniqueID;
+
+ /** Contains the UUID used by Mojang to identify the player's account. Short UUID stored here (without dashes) */
AString m_UUID;
/** Set to true when the chunk where the player is is sent to the client. Used for spawning the player */
@@ -372,6 +379,9 @@ private:
cChannels m_PluginChannels;
+ /** Handles the block placing packet when it is a real block placement (not block-using, item-using or eating) */
+ void HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, cItemHandler & a_ItemHandler);
+
/** Returns true if the rate block interactions is within a reasonable limit (bot protection) */
bool CheckBlockInteractionsRate(void);
@@ -395,7 +405,10 @@ private:
/** Removes all of the channels from the list of current plugin channels. Ignores channels that are not found. */
void UnregisterPluginChannels(const AStringVector & a_ChannelList);
-
+
+ /** Handles the "MC|Beacon" plugin message */
+ void HandleBeaconSelection(const char * a_Data, size_t a_Length);
+
/** Handles the "MC|AdvCdm" plugin message */
void HandleCommandBlockMessage(const char * a_Data, size_t a_Length);
@@ -406,7 +419,7 @@ private:
virtual bool DataReceived (const char * a_Data, size_t a_Size) override; // Data is received from the client
virtual void GetOutgoingData(AString & a_Data) override; // Data can be sent to client
virtual void SocketClosed (void) override; // The socket has been closed for any reason
-}; // tolua_export
+}; // tolua_export
diff --git a/src/CommandOutput.cpp b/src/CommandOutput.cpp
index 2c116b3d6..510461d81 100644
--- a/src/CommandOutput.cpp
+++ b/src/CommandOutput.cpp
@@ -10,7 +10,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCommandOutputCallback:
void cCommandOutputCallback::Out(const char * a_Fmt, ...)
@@ -28,7 +28,7 @@ void cCommandOutputCallback::Out(const char * a_Fmt, ...)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cLogCommandOutputCallback:
void cLogCommandOutputCallback::Out(const AString & a_Text)
diff --git a/src/CommandOutput.h b/src/CommandOutput.h
index 5682b4fd8..daa9430c0 100644
--- a/src/CommandOutput.h
+++ b/src/CommandOutput.h
@@ -14,16 +14,16 @@ Descendants override that function to provide specific processing of the output.
class cCommandOutputCallback
{
public:
- virtual ~cCommandOutputCallback() {}; // Force a virtual destructor in subclasses
+ virtual ~cCommandOutputCallback() {} // Force a virtual destructor in subclasses
- /// Syntax sugar function, calls Out() with Printf()-ed parameters; appends a "\n"
+ /// Syntax sugar function, calls Out() with Printf()-ed parameters; appends a newline"
void Out(const char * a_Fmt, ...) FORMATSTRING(2, 3);
/// Called when the command wants to output anything; may be called multiple times
virtual void Out(const AString & a_Text) = 0;
/// Called when the command processing has been finished
- virtual void Finished(void) {};
+ virtual void Finished(void) {}
} ;
diff --git a/src/CompositeChat.cpp b/src/CompositeChat.cpp
index a3612983a..0d339021e 100644
--- a/src/CompositeChat.cpp
+++ b/src/CompositeChat.cpp
@@ -100,7 +100,7 @@ public:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompositeChat:
cCompositeChat::cCompositeChat(void) :
@@ -353,23 +353,23 @@ AString cCompositeChat::ExtractText(void) const
-cMCLogger::eLogLevel cCompositeChat::MessageTypeToLogLevel(eMessageType a_MessageType)
+cLogger::eLogLevel cCompositeChat::MessageTypeToLogLevel(eMessageType a_MessageType)
{
switch (a_MessageType)
{
- case mtCustom: return cMCLogger::llRegular;
- case mtFailure: return cMCLogger::llWarning;
- case mtInformation: return cMCLogger::llInfo;
- case mtSuccess: return cMCLogger::llRegular;
- case mtWarning: return cMCLogger::llWarning;
- case mtFatal: return cMCLogger::llError;
- case mtDeath: return cMCLogger::llRegular;
- case mtPrivateMessage: return cMCLogger::llRegular;
- case mtJoin: return cMCLogger::llRegular;
- case mtLeave: return cMCLogger::llRegular;
+ case mtCustom: return cLogger::llRegular;
+ case mtFailure: return cLogger::llWarning;
+ case mtInformation: return cLogger::llInfo;
+ case mtSuccess: return cLogger::llRegular;
+ case mtWarning: return cLogger::llWarning;
+ case mtFatal: return cLogger::llError;
+ case mtDeath: return cLogger::llRegular;
+ case mtPrivateMessage: return cLogger::llRegular;
+ case mtJoin: return cLogger::llRegular;
+ case mtLeave: return cLogger::llRegular;
}
ASSERT(!"Unhandled MessageType");
- return cMCLogger::llError;
+ return cLogger::llError;
}
@@ -399,7 +399,7 @@ void cCompositeChat::AddStyle(AString & a_Style, const AString & a_AddStyle)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompositeChat::cBasePart:
cCompositeChat::cBasePart::cBasePart(cCompositeChat::ePartType a_PartType, const AString & a_Text, const AString & a_Style) :
@@ -413,7 +413,7 @@ cCompositeChat::cBasePart::cBasePart(cCompositeChat::ePartType a_PartType, const
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompositeChat::cTextPart:
cCompositeChat::cTextPart::cTextPart(const AString & a_Text, const AString &a_Style) :
@@ -425,7 +425,7 @@ cCompositeChat::cTextPart::cTextPart(const AString & a_Text, const AString &a_St
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompositeChat::cClientTranslatedPart:
cCompositeChat::cClientTranslatedPart::cClientTranslatedPart(const AString & a_TranslationID, const AStringVector & a_Parameters, const AString & a_Style) :
@@ -438,7 +438,7 @@ cCompositeChat::cClientTranslatedPart::cClientTranslatedPart(const AString & a_T
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompositeChat::cUrlPart:
cCompositeChat::cUrlPart::cUrlPart(const AString & a_Text, const AString & a_Url, const AString & a_Style) :
@@ -451,7 +451,7 @@ cCompositeChat::cUrlPart::cUrlPart(const AString & a_Text, const AString & a_Url
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompositeChat::cCommandPart:
cCompositeChat::cCommandPart::cCommandPart(ePartType a_PartType, const AString & a_Text, const AString & a_Command, const AString & a_Style) :
@@ -464,7 +464,7 @@ cCompositeChat::cCommandPart::cCommandPart(ePartType a_PartType, const AString &
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompositeChat::cRunCommandPart:
cCompositeChat::cRunCommandPart::cRunCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style) :
@@ -475,7 +475,7 @@ cCompositeChat::cRunCommandPart::cRunCommandPart(const AString & a_Text, const A
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompositeChat::cSuggestCommandPart:
cCompositeChat::cSuggestCommandPart::cSuggestCommandPart(const AString & a_Text, const AString & a_Command, const AString & a_Style) :
@@ -487,7 +487,7 @@ cCompositeChat::cSuggestCommandPart::cSuggestCommandPart(const AString & a_Text,
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompositeChat::cShowAchievementPart:
cCompositeChat::cShowAchievementPart::cShowAchievementPart(const AString & a_PlayerName, const AString & a_Achievement, const AString & a_Style) :
diff --git a/src/CompositeChat.h b/src/CompositeChat.h
index 1ad196f1d..2dc21b98f 100644
--- a/src/CompositeChat.h
+++ b/src/CompositeChat.h
@@ -196,7 +196,7 @@ public:
/** Converts the MessageType to a LogLevel value.
Used by the logging bindings when logging a cCompositeChat object. */
- static cMCLogger::eLogLevel MessageTypeToLogLevel(eMessageType a_MessageType);
+ static cLogger::eLogLevel MessageTypeToLogLevel(eMessageType a_MessageType);
protected:
/** All the parts that */
diff --git a/src/CraftingRecipes.cpp b/src/CraftingRecipes.cpp
index 0f1951351..1a31a6e90 100644
--- a/src/CraftingRecipes.cpp
+++ b/src/CraftingRecipes.cpp
@@ -12,7 +12,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCraftingGrid:
cCraftingGrid::cCraftingGrid(int a_Width, int a_Height) :
@@ -135,7 +135,7 @@ void cCraftingGrid::ConsumeGrid(const cCraftingGrid & a_Grid)
{
if ((a_Grid.m_Width != m_Width) || (a_Grid.m_Height != m_Height))
{
- LOGWARNING("Consuming a grid of different dimensions: (%d, %d) vs (%d, %d)",
+ LOGWARNING("Consuming a grid of different dimensions: (%d, %d) vs (%d, %d)",
a_Grid.m_Width, a_Grid.m_Height, m_Width, m_Height
);
}
@@ -196,7 +196,7 @@ void cCraftingGrid::Dump(void)
#ifdef _DEBUG
int idx = x + m_Width * y;
#endif
- LOGD("Slot (%d, %d): Type %d, health %d, count %d",
+ LOGD("Slot (%d, %d): Type %d, health %d, count %d",
x, y, m_Items[idx].m_ItemType, m_Items[idx].m_ItemDamage, m_Items[idx].m_ItemCount
);
}
@@ -206,7 +206,7 @@ void cCraftingGrid::Dump(void)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCraftingRecipe:
cCraftingRecipe::cCraftingRecipe(const cCraftingGrid & a_CraftingGrid) :
@@ -250,7 +250,7 @@ void cCraftingRecipe::Dump(void)
{
LOGD("Recipe ingredients:");
m_Ingredients.Dump();
- LOGD("Result: Type %d, health %d, count %d",
+ LOGD("Result: Type %d, health %d, count %d",
m_Result.m_ItemType, m_Result.m_ItemDamage, m_Result.m_ItemCount
);
}
@@ -259,7 +259,7 @@ void cCraftingRecipe::Dump(void)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCraftingRecipes:
cCraftingRecipes::cCraftingRecipes(void)
@@ -582,7 +582,7 @@ cCraftingRecipes::cRecipe * cCraftingRecipes::FindRecipe(const cItem * a_Craftin
// Get the real bounds of the crafting grid:
int GridLeft = MAX_GRID_WIDTH, GridTop = MAX_GRID_HEIGHT;
int GridRight = 0, GridBottom = 0;
- for (int y = 0; y < a_GridHeight; y++ ) for(int x = 0; x < a_GridWidth; x++)
+ for (int y = 0; y < a_GridHeight; y++) for (int x = 0; x < a_GridWidth; x++)
{
if (!a_CraftingGrid[x + y * a_GridWidth].IsEmpty())
{
@@ -665,7 +665,7 @@ cCraftingRecipes::cRecipe * cCraftingRecipes::MatchRecipe(const cItem * a_Crafti
const cItem & Item = itrS->m_Item;
if (
- (itrS->x >= a_GridWidth) ||
+ (itrS->x >= a_GridWidth) ||
(itrS->y >= a_GridHeight) ||
(Item.m_ItemType != a_CraftingGrid[GridID].m_ItemType) || // same item type?
(Item.m_ItemCount > a_CraftingGrid[GridID].m_ItemCount) || // not enough items
@@ -838,7 +838,7 @@ void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRe
case E_ITEM_GOLD_NUGGET: a_Recipe->m_Result.m_FireworkItem.m_Type = 2; break;
case E_ITEM_FEATHER: a_Recipe->m_Result.m_FireworkItem.m_Type = 4; break;
case E_ITEM_HEAD: a_Recipe->m_Result.m_FireworkItem.m_Type = 3; break;
- default: LOG("Unexpected item in firework star recipe, was the crafting file's fireworks section changed?"); break; // ermahgerd BARD ardmins
+ default: LOG("Unexpected item in firework star recipe, was the crafting file's fireworks section changed?"); break; // ermahgerd BARD ardmins
}
}
diff --git a/src/CraftingRecipes.h b/src/CraftingRecipes.h
index 90e41eddc..0250d2f68 100644
--- a/src/CraftingRecipes.h
+++ b/src/CraftingRecipes.h
@@ -127,7 +127,7 @@ protected:
typedef std::vector<cRecipeSlot> cRecipeSlots;
/** A single recipe, stored. Each recipe is normalized right after parsing (NormalizeIngredients())
- A normalized recipe starts at (0,0)
+ A normalized recipe starts at (0, 0)
*/
struct cRecipe
{
diff --git a/src/Cuboid.cpp b/src/Cuboid.cpp
index 3e5240248..8891cfcb1 100644
--- a/src/Cuboid.cpp
+++ b/src/Cuboid.cpp
@@ -21,9 +21,20 @@ static bool DoIntervalsIntersect(int a_Min1, int a_Max1, int a_Min2, int a_Max2)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCuboid:
+cCuboid & cCuboid::operator =(cCuboid a_Other)
+{
+ std::swap(p1, a_Other.p1);
+ std::swap(p2, a_Other.p2);
+ return *this;
+}
+
+
+
+
+
void cCuboid::Assign(int a_X1, int a_Y1, int a_Z1, int a_X2, int a_Y2, int a_Z2)
{
p1.x = a_X1;
diff --git a/src/Cuboid.h b/src/Cuboid.h
index 3239c54fc..c205156ec 100644
--- a/src/Cuboid.h
+++ b/src/Cuboid.h
@@ -15,10 +15,16 @@ public:
Vector3i p1, p2;
cCuboid(void) {}
- cCuboid(const cCuboid & a_Cuboid ) : p1(a_Cuboid.p1), p2(a_Cuboid.p2) {}
+ cCuboid(const cCuboid & a_Cuboid) : p1(a_Cuboid.p1), p2(a_Cuboid.p2) {}
cCuboid(const Vector3i & a_p1, const Vector3i & a_p2) : p1(a_p1), p2(a_p2) {}
cCuboid(int a_X1, int a_Y1, int a_Z1) : p1(a_X1, a_Y1, a_Z1), p2(a_X1, a_Y1, a_Z1) {}
cCuboid(int a_X1, int a_Y1, int a_Z1, int a_X2, int a_Y2, int a_Z2) : p1(a_X1, a_Y1, a_Z1), p2(a_X2, a_Y2, a_Z2) {}
+
+ // tolua_end
+
+ cCuboid & operator =(cCuboid a_Other);
+
+ // tolua_begin
void Assign(int a_X1, int a_Y1, int a_Z1, int a_X2, int a_Y2, int a_Z2);
void Assign(const cCuboid & a_SrcCuboid);
@@ -38,7 +44,7 @@ public:
Assumes both cuboids are sorted. */
bool DoesIntersect(const cCuboid & a_Other) const;
- bool IsInside(const Vector3i & v) const
+ bool IsInside(const Vector3i & v) const
{
return (
(v.x >= p1.x) && (v.x <= p2.x) &&
@@ -47,7 +53,7 @@ public:
);
}
- bool IsInside(int a_X, int a_Y, int a_Z) const
+ bool IsInside(int a_X, int a_Y, int a_Z) const
{
return (
(a_X >= p1.x) && (a_X <= p2.x) &&
@@ -56,7 +62,7 @@ public:
);
}
- bool IsInside( const Vector3d & v ) const
+ bool IsInside( const Vector3d & v) const
{
return (
(v.x >= p1.x) && (v.x <= p2.x) &&
diff --git a/src/Defines.h b/src/Defines.h
index ee91ee596..0981077c4 100644
--- a/src/Defines.h
+++ b/src/Defines.h
@@ -1,7 +1,6 @@
#pragma once
-#include "ChatColor.h"
#include <limits>
#include <cmath>
@@ -22,7 +21,7 @@ typedef std::vector<int> cSlotNums;
/// Experience Orb setup
enum
{
- //open to suggestion on naming convention here :)
+ // Open to suggestion on naming convention here :)
MAX_EXPERIENCE_ORB_SIZE = 2000
} ;
@@ -471,18 +470,7 @@ inline void AddFaceDirection(int & a_BlockX, unsigned char & a_BlockY, int & a_B
{
int Y = a_BlockY;
AddFaceDirection(a_BlockX, Y, a_BlockZ, a_BlockFace, a_bInverse);
- if (Y < 0)
- {
- a_BlockY = 0;
- }
- else if (Y > 255)
- {
- a_BlockY = 255;
- }
- else
- {
- a_BlockY = (unsigned char)Y;
- }
+ a_BlockY = Clamp<unsigned char>((unsigned char)Y, 0, 255);
}
@@ -491,9 +479,9 @@ inline void AddFaceDirection(int & a_BlockX, unsigned char & a_BlockY, int & a_B
inline void EulerToVector(double a_Pan, double a_Pitch, double & a_X, double & a_Y, double & a_Z)
{
- // a_X = sinf ( a_Pan / 180 * PI ) * cosf ( a_Pitch / 180 * PI );
- // a_Y = -sinf ( a_Pitch / 180 * PI );
- // a_Z = -cosf ( a_Pan / 180 * PI ) * cosf ( a_Pitch / 180 * PI );
+ // a_X = sinf ( a_Pan / 180 * PI) * cosf ( a_Pitch / 180 * PI);
+ // a_Y = -sinf ( a_Pitch / 180 * PI);
+ // a_Z = -cosf ( a_Pan / 180 * PI) * cosf ( a_Pitch / 180 * PI);
a_X = cos(a_Pan / 180 * PI) * cos(a_Pitch / 180 * PI);
a_Y = sin(a_Pan / 180 * PI) * cos(a_Pitch / 180 * PI);
a_Z = sin(a_Pitch / 180 * PI);
@@ -512,7 +500,7 @@ inline void VectorToEuler(double a_X, double a_Y, double a_Z, double & a_Pan, do
}
else
{
- a_Pan = atan2(a_Z, a_X) * 180 / PI - 90;
+ a_Pan = atan2(a_Z, a_X) * 180 / PI - 90;
}
a_Pitch = atan2(a_Y, r) * 180 / PI;
@@ -531,7 +519,7 @@ inline float GetSignf(float a_Val)
-inline float GetSpecialSignf( float a_Val )
+inline float GetSpecialSignf( float a_Val)
{
return (a_Val <= 0.f) ? -1.f : 1.f;
}
@@ -652,11 +640,11 @@ namespace ItemCategory
inline bool IsTool(short a_ItemID)
{
- return IsPickaxe( a_ItemID )
- || IsAxe ( a_ItemID )
- || IsSword ( a_ItemID )
- || IsHoe ( a_ItemID )
- || IsShovel ( a_ItemID );
+ return IsPickaxe( a_ItemID)
+ || IsAxe ( a_ItemID)
+ || IsSword ( a_ItemID)
+ || IsHoe ( a_ItemID)
+ || IsShovel ( a_ItemID);
}
@@ -727,14 +715,5 @@ namespace ItemCategory
// tolua_end
-inline bool BlockRequiresSpecialTool(BLOCKTYPE a_BlockType)
-{
- if(!IsValidBlock(a_BlockType)) return false;
- return cBlockInfo::RequiresSpecialTool(a_BlockType);
-}
-
-
-
-
diff --git a/src/Enchantments.h b/src/Enchantments.h
index 85a316414..824f6aa55 100644
--- a/src/Enchantments.h
+++ b/src/Enchantments.h
@@ -40,10 +40,10 @@ Serialization will never put zero-level enchantments into the stringspec and wil
class cEnchantments
{
public:
- /** Individual enchantment IDs, corresponding to their NBT IDs ( http://www.minecraftwiki.net/wiki/Data_Values#Enchantment_IDs )
+ /** Individual enchantment IDs, corresponding to their NBT IDs: http://www.minecraftwiki.net/wiki/Data_Values#Enchantment_IDs
*/
- enum
+ enum eEnchantment
{
enchProtection = 0,
enchFireProtection = 1,
diff --git a/src/Endianness.h b/src/Endianness.h
index 78f9a5d99..9aeb44986 100644
--- a/src/Endianness.h
+++ b/src/Endianness.h
@@ -1,6 +1,7 @@
#pragma once
+#undef ntohll
#define ntohll(x) ((((UInt64)ntohl((u_long)x)) << 32) + ntohl(x >> 32))
@@ -11,8 +12,8 @@
inline UInt64 HostToNetwork8(const void * a_Value)
{
unsigned long long __HostToNetwork8;
- memcpy( &__HostToNetwork8, a_Value, sizeof( __HostToNetwork8 ) );
- __HostToNetwork8 = (( ( (unsigned long long)htonl((u_long)__HostToNetwork8) ) << 32) + htonl(__HostToNetwork8 >> 32));
+ memcpy( &__HostToNetwork8, a_Value, sizeof( __HostToNetwork8));
+ __HostToNetwork8 = (( ( (unsigned long long)htonl((u_long)__HostToNetwork8)) << 32) + htonl(__HostToNetwork8 >> 32));
return __HostToNetwork8;
}
@@ -20,11 +21,11 @@ inline UInt64 HostToNetwork8(const void * a_Value)
-inline UInt32 HostToNetwork4(const void* a_Value )
+inline UInt32 HostToNetwork4(const void* a_Value)
{
unsigned int __HostToNetwork4;
- memcpy( &__HostToNetwork4, a_Value, sizeof( __HostToNetwork4 ) );
- __HostToNetwork4 = ntohl( __HostToNetwork4 );
+ memcpy( &__HostToNetwork4, a_Value, sizeof( __HostToNetwork4));
+ __HostToNetwork4 = ntohl( __HostToNetwork4);
return __HostToNetwork4;
}
diff --git a/src/Entities/ArrowEntity.cpp b/src/Entities/ArrowEntity.cpp
index d59088e72..913519c4c 100644
--- a/src/Entities/ArrowEntity.cpp
+++ b/src/Entities/ArrowEntity.cpp
@@ -72,15 +72,15 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
-{
+{
if (GetSpeed().EqualsEps(Vector3d(0, 0, 0), 0.0000001))
{
- SetSpeed(GetLookVector().NormalizeCopy() * 0.1); // Ensure that no division by zero happens later
+ SetSpeed(GetLookVector().NormalizeCopy() * 0.1); // Ensure that no division by zero happens later
}
Vector3d Hit = a_HitPos;
- Vector3d SinkMovement = (GetSpeed() / 800);
- Hit += (SinkMovement * 0.01) / SinkMovement.Length(); // Make arrow sink into block a centimetre so it lodges (but not to far so it goes black clientside)
+ Vector3d SinkMovement = (GetSpeed() / 1000);
+ Hit += SinkMovement * (0.0005 / SinkMovement.Length()); // Make arrow sink into block a centimetre so it lodges (but not to far so it goes black clientside)
super::OnHitSolidBlock(Hit, a_HitFace);
Vector3i BlockHit = Hit.Floor();
@@ -89,7 +89,7 @@ void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFa
m_HitBlockPos = Vector3i(X, Y, Z);
// Broadcast arrow hit sound
- m_World->BroadcastSoundEffect("random.bowhit", X * 8, Y * 8, Z * 8, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
+ m_World->BroadcastSoundEffect("random.bowhit", (double)X, (double)Y, (double)Z, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
}
@@ -97,7 +97,7 @@ void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFa
void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
-{
+{
int Damage = (int)(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5);
if (m_IsCritical)
{
@@ -106,7 +106,7 @@ void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1);
// Broadcast successful hit sound
- GetWorld()->BroadcastSoundEffect("random.successful_hit", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
+ GetWorld()->BroadcastSoundEffect("random.successful_hit", GetPosX(), GetPosY(), GetPosZ(), 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
Destroy();
}
@@ -131,7 +131,7 @@ void cArrowEntity::CollectedBy(cPlayer * a_Dest)
}
GetWorld()->BroadcastCollectEntity(*this, *a_Dest);
- GetWorld()->BroadcastSoundEffect("random.pop", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
+ GetWorld()->BroadcastSoundEffect("random.pop", GetPosX(), GetPosY(), GetPosZ(), 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
m_bIsCollected = true;
}
}
@@ -166,9 +166,9 @@ void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk)
// We can afford to do this because xoft's algorithm for trajectory is near perfect, so things are pretty close anyway without sync
// Besides, this seems to be what the vanilla server does, note how arrows teleport half a second after they hit to the server position
- if (!m_HasTeleported) // Sent a teleport already, don't do again
+ if (!m_HasTeleported) // Sent a teleport already, don't do again
{
- if (m_HitGroundTimer > 500.f) // Send after half a second, could be less, but just in case
+ if (m_HitGroundTimer > 500.f) // Send after half a second, could be less, but just in case
{
m_World->BroadcastTeleportEntity(*this);
m_HasTeleported = true;
@@ -189,9 +189,9 @@ void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk)
return;
}
- if (Chunk->GetBlock(RelPosX, m_HitBlockPos.y, RelPosZ) == E_BLOCK_AIR) // Block attached to was destroyed?
+ if (Chunk->GetBlock(RelPosX, m_HitBlockPos.y, RelPosZ) == E_BLOCK_AIR) // Block attached to was destroyed?
{
- m_IsInGround = false; // Yes, begin simulating physics again
+ m_IsInGround = false; // Yes, begin simulating physics again
}
}
}
diff --git a/src/Entities/ArrowEntity.h b/src/Entities/ArrowEntity.h
index 76cb24449..4bfcb1f6d 100644
--- a/src/Entities/ArrowEntity.h
+++ b/src/Entities/ArrowEntity.h
@@ -28,7 +28,7 @@ public:
// tolua_end
- CLASS_PROTODEF(cArrowEntity);
+ CLASS_PROTODEF(cArrowEntity)
/// Creates a new arrow with psNoPickup state and default damage modifier coeff
cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
@@ -99,4 +99,4 @@ protected:
virtual void CollectedBy(cPlayer * a_Player) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
-}; // tolua_export
+}; // tolua_export
diff --git a/src/Entities/Boat.cpp b/src/Entities/Boat.cpp
index 31bfe3dc3..8ff8866a1 100644
--- a/src/Entities/Boat.cpp
+++ b/src/Entities/Boat.cpp
@@ -94,7 +94,7 @@ void cBoat::Tick(float a_Dt, cChunk & a_Chunk)
super::Tick(a_Dt, a_Chunk);
BroadcastMovementUpdate();
- SetSpeed(GetSpeed() * 0.97); // Slowly decrease the speed
+ SetSpeed(GetSpeed() * 0.97); // Slowly decrease the speed
if ((POSY_TOINT < 0) || (POSY_TOINT > cChunkDef::Height))
{
@@ -104,7 +104,7 @@ void cBoat::Tick(float a_Dt, cChunk & a_Chunk)
if (IsBlockWater(m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT)))
{
if (GetSpeedY() < 2)
- {
+ {
AddSpeedY(0.2);
}
}
diff --git a/src/Entities/Boat.h b/src/Entities/Boat.h
index 0fcfbd602..8de88d165 100644
--- a/src/Entities/Boat.h
+++ b/src/Entities/Boat.h
@@ -21,7 +21,7 @@ class cBoat :
typedef cEntity super;
public:
- CLASS_PROTODEF(cBoat);
+ CLASS_PROTODEF(cBoat)
// cEntity overrides:
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
diff --git a/src/Entities/CMakeLists.txt b/src/Entities/CMakeLists.txt
index 205cb2cca..5d10e1680 100644
--- a/src/Entities/CMakeLists.txt
+++ b/src/Entities/CMakeLists.txt
@@ -4,11 +4,64 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ ArrowEntity.cpp
+ Boat.cpp
+ EnderCrystal.cpp
+ Entity.cpp
+ EntityEffect.cpp
+ ExpBottleEntity.cpp
+ ExpOrb.cpp
+ FallingBlock.cpp
+ FireChargeEntity.cpp
+ FireworkEntity.cpp
+ Floater.cpp
+ GhastFireballEntity.cpp
+ HangingEntity.cpp
+ ItemFrame.cpp
+ Minecart.cpp
+ Painting.cpp
+ Pawn.cpp
+ Pickup.cpp
+ Player.cpp
+ ProjectileEntity.cpp
+ SplashPotionEntity.cpp
+ TNTEntity.cpp
+ ThrownEggEntity.cpp
+ ThrownEnderPearlEntity.cpp
+ ThrownSnowballEntity.cpp
+ WitherSkullEntity.cpp)
-add_library(Entities ${SOURCE})
+SET (HDRS
+ ArrowEntity.h
+ Boat.h
+ EnderCrystal.h
+ Entity.h
+ EntityEffect.h
+ ExpBottleEntity.h
+ ExpOrb.h
+ FallingBlock.h
+ FireChargeEntity.h
+ FireworkEntity.h
+ Floater.h
+ GhastFireballEntity.h
+ HangingEntity.h
+ ItemFrame.h
+ Minecart.h
+ Painting.h
+ Pawn.h
+ Pickup.h
+ Player.h
+ ProjectileEntity.h
+ SplashPotionEntity.h
+ TNTEntity.h
+ ThrownEggEntity.h
+ ThrownEnderPearlEntity.h
+ ThrownSnowballEntity.h
+ WitherSkullEntity.h)
-target_link_libraries(Entities WorldStorage)
+if(NOT MSVC)
+ add_library(Entities ${SRCS} ${HDRS})
+
+ target_link_libraries(Entities WorldStorage)
+endif()
diff --git a/src/Entities/Effects.h b/src/Entities/Effects.h
deleted file mode 100644
index baf3302fb..000000000
--- a/src/Entities/Effects.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-// tolua_begin
-enum ENUM_ENTITY_EFFECT
-{
- E_EFFECT_SPEED = 1,
- E_EFFECT_SLOWNESS = 2,
- E_EFFECT_HASTE = 3,
- E_EFFECT_MINING_FATIGUE = 4,
- E_EFFECT_STENGTH = 5,
- E_EFFECT_INSTANT_HEALTH = 6,
- E_EFFECT_INSTANT_DAMAGE = 7,
- E_EFFECT_JUMP_BOOST = 8,
- E_EFFECT_NAUSEA = 9,
- E_EFFECT_REGENERATION = 10,
- E_EFFECT_RESISTANCE = 11,
- E_EFFECT_FIRE_RESISTANCE = 12,
- E_EFFECT_WATER_BREATHING = 13,
- E_EFFECT_INVISIBILITY = 14,
- E_EFFECT_BLINDNESS = 15,
- E_EFFECT_NIGHT_VISION = 16,
- E_EFFECT_HUNGER = 17,
- E_EFFECT_WEAKNESS = 18,
- E_EFFECT_POISON = 19,
- E_EFFECT_WITHER = 20,
- E_EFFECT_HEALTH_BOOST = 21,
- E_EFFECT_ABSORPTION = 22,
- E_EFFECT_SATURATION = 23,
-} ;
-// tolua_end
diff --git a/src/Entities/EnderCrystal.cpp b/src/Entities/EnderCrystal.cpp
index a640b236c..c17bb608e 100644
--- a/src/Entities/EnderCrystal.cpp
+++ b/src/Entities/EnderCrystal.cpp
@@ -32,9 +32,6 @@ void cEnderCrystal::SpawnOn(cClientHandle & a_ClientHandle)
void cEnderCrystal::Tick(float a_Dt, cChunk & a_Chunk)
{
UNUSED(a_Dt);
-
- a_Chunk.SetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT, E_BLOCK_FIRE, 0);
-
// No further processing (physics e.t.c.) is needed
}
@@ -42,13 +39,16 @@ void cEnderCrystal::Tick(float a_Dt, cChunk & a_Chunk)
-void cEnderCrystal::KilledBy(cEntity * a_Killer)
+void cEnderCrystal::KilledBy(TakeDamageInfo & a_TDI)
{
- super::KilledBy(a_Killer);
+ super::KilledBy(a_TDI);
m_World->DoExplosionAt(6.0, GetPosX(), GetPosY(), GetPosZ(), true, esEnderCrystal, this);
Destroy();
+
+ m_World->SetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT, E_BLOCK_BEDROCK, 0);
+ m_World->SetBlock(POSX_TOINT, POSY_TOINT + 1, POSZ_TOINT, E_BLOCK_FIRE, 0);
}
diff --git a/src/Entities/EnderCrystal.h b/src/Entities/EnderCrystal.h
index 5b86df987..c98c3b681 100644
--- a/src/Entities/EnderCrystal.h
+++ b/src/Entities/EnderCrystal.h
@@ -15,7 +15,7 @@ class cEnderCrystal :
typedef cEntity super;
public:
- CLASS_PROTODEF(cEnderCrystal);
+ CLASS_PROTODEF(cEnderCrystal)
cEnderCrystal(double a_X, double a_Y, double a_Z);
@@ -24,7 +24,7 @@ private:
// cEntity overrides:
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
- virtual void KilledBy(cEntity * a_Killer) override;
+ virtual void KilledBy(TakeDamageInfo & a_TDI) override;
}; // tolua_export
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 26823924f..32f220897 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -12,6 +12,7 @@
#include "../Bindings/PluginManager.h"
#include "../Tracer.h"
#include "Player.h"
+#include "Items/ItemHandler.h"
@@ -37,6 +38,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
, m_Gravity(-9.81f)
, m_LastPos(a_X, a_Y, a_Z)
, m_IsInitialized(false)
+ , m_WorldTravellingFrom(NULL)
, m_EntityType(a_EntityType)
, m_World(NULL)
, m_IsFireproof(false)
@@ -49,6 +51,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
, m_IsSubmerged(false)
, m_AirLevel(0)
, m_AirTickTimer(0)
+ , m_TicksAlive(0)
, m_HeadYaw(0.0)
, m_Rot(0.0, 0.0, 0.0)
, m_Pos(a_X, a_Y, a_Z)
@@ -74,7 +77,7 @@ cEntity::~cEntity()
/*
// DEBUG:
- LOGD("Deleting entity %d at pos {%.2f, %.2f, %.2f} ~ [%d, %d]; ptr %p",
+ LOGD("Deleting entity %d at pos {%.2f, %.2f, %.2f} ~ [%d, %d]; ptr %p",
m_UniqueID,
m_Pos.x, m_Pos.y, m_Pos.z,
(int)(m_Pos.x / cChunkDef::Width), (int)(m_Pos.z / cChunkDef::Width),
@@ -241,9 +244,9 @@ void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_R
Vector3d Heading(0, 0, 0);
if (a_Attacker != NULL)
{
- Heading = a_Attacker->GetLookVector() * (a_Attacker->IsSprinting() ? 10 : 8);
+ Heading = a_Attacker->GetLookVector() * (a_Attacker->IsSprinting() ? 16 : 11);
+ Heading.y = 1.6;
}
- Heading.y = 2;
TDI.Knockback = Heading * a_KnockbackAmount;
DoTakeDamage(TDI);
@@ -272,7 +275,7 @@ void cEntity::SetYawFromSpeed(void)
void cEntity::SetPitchFromSpeed(void)
{
const double EPS = 0.0000001;
- double xz = sqrt(m_Speed.x * m_Speed.x + m_Speed.z * m_Speed.z); // Speed XZ-plane component
+ double xz = sqrt(m_Speed.x * m_Speed.x + m_Speed.z * m_Speed.z); // Speed XZ-plane component
if ((abs(xz) < EPS) && (abs(m_Speed.y) < EPS))
{
// atan2() may overflow or is undefined, pick any number
@@ -288,11 +291,6 @@ void cEntity::SetPitchFromSpeed(void)
bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
{
- if (cRoot::Get()->GetPluginManager()->CallHookTakeDamage(*this, a_TDI))
- {
- return false;
- }
-
if (m_Health <= 0)
{
// Can't take damage if already dead
@@ -305,15 +303,26 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
return false;
}
+ if (cRoot::Get()->GetPluginManager()->CallHookTakeDamage(*this, a_TDI))
+ {
+ return false;
+ }
+
if ((a_TDI.Attacker != NULL) && (a_TDI.Attacker->IsPlayer()))
{
cPlayer * Player = (cPlayer *)a_TDI.Attacker;
+ Player->GetEquippedItem().GetHandler()->OnEntityAttack(Player, this);
+
// IsOnGround() only is false if the player is moving downwards
- if (!Player->IsOnGround()) // TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain)
+ // TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain)
+ if (!Player->IsOnGround())
{
- a_TDI.FinalDamage += 2;
- m_World->BroadcastEntityAnimation(*this, 4); // Critical hit
+ if ((a_TDI.DamageType == dtAttack) || (a_TDI.DamageType == dtArrowAttack))
+ {
+ a_TDI.FinalDamage += 2;
+ m_World->BroadcastEntityAnimation(*this, 4); // Critical hit
+ }
}
Player->GetStatManager().AddValue(statDamageDealt, (StatValue)floor(a_TDI.FinalDamage * 10 + 0.5));
@@ -323,43 +332,25 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
// TODO: Apply damage to armor
- if (m_Health < 0)
- {
- m_Health = 0;
- }
+ m_Health = std::max(m_Health, 0);
- if ((IsMob() || IsPlayer()) && (a_TDI.Attacker != NULL)) // Knockback for only players and mobs
+ if ((IsMob() || IsPlayer()) && (a_TDI.Attacker != NULL)) // Knockback for only players and mobs
{
- int KnockbackLevel = 0;
- if (a_TDI.Attacker->GetEquippedWeapon().m_ItemType == E_ITEM_BOW)
+ int KnockbackLevel = a_TDI.Attacker->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchKnockback); // More common enchantment
+ if (KnockbackLevel < 1)
{
+ // We support punch on swords and vice versa! :)
KnockbackLevel = a_TDI.Attacker->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchPunch);
}
- else
- {
- KnockbackLevel = a_TDI.Attacker->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchKnockback);
- }
- Vector3d additionalSpeed(0, 0, 0);
+ Vector3d AdditionalSpeed(0, 0, 0);
switch (KnockbackLevel)
{
- case 1:
- {
- additionalSpeed.Set(5, .3, 5);
- break;
- }
- case 2:
- {
- additionalSpeed.Set(8, .3, 8);
- break;
- }
- default:
- {
- additionalSpeed.Set(2, .3, 2);
- break;
- }
+ case 1: AdditionalSpeed.Set(5, 0.3, 5); break;
+ case 2: AdditionalSpeed.Set(8, 0.3, 8); break;
+ default: break;
}
- AddSpeed(a_TDI.Knockback * additionalSpeed);
+ AddSpeed(a_TDI.Knockback + AdditionalSpeed);
}
m_World->BroadcastEntityStatus(*this, esGenericHurt);
@@ -368,7 +359,7 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
if (m_Health <= 0)
{
- KilledBy(a_TDI.Attacker);
+ KilledBy(a_TDI);
if (a_TDI.Attacker != NULL)
{
@@ -431,6 +422,7 @@ bool cEntity::ArmorCoversAgainst(eDamageType a_DamageType)
case dtStarving:
case dtInVoid:
case dtPoisoning:
+ case dtWithering:
case dtPotionOfHarming:
case dtFalling:
case dtLightning:
@@ -524,11 +516,11 @@ double cEntity::GetKnockbackAmountAgainst(const cEntity & a_Receiver)
-void cEntity::KilledBy(cEntity * a_Killer)
+void cEntity::KilledBy(TakeDamageInfo & a_TDI)
{
m_Health = 0;
- cRoot::Get()->GetPluginManager()->CallHookKilling(*this, a_Killer);
+ cRoot::Get()->GetPluginManager()->CallHookKilling(*this, a_TDI.Attacker, a_TDI);
if (m_Health > 0)
{
@@ -538,7 +530,7 @@ void cEntity::KilledBy(cEntity * a_Killer)
// Drop loot:
cItems Drops;
- GetDrops(Drops, a_Killer);
+ GetDrops(Drops, a_TDI.Attacker);
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
m_World->BroadcastEntityStatus(*this, esGenericDead);
@@ -551,10 +543,7 @@ void cEntity::KilledBy(cEntity * a_Killer)
void cEntity::Heal(int a_HitPoints)
{
m_Health += a_HitPoints;
- if (m_Health > m_MaxHealth)
- {
- m_Health = m_MaxHealth;
- }
+ m_Health = std::min(m_Health, m_MaxHealth);
}
@@ -563,7 +552,7 @@ void cEntity::Heal(int a_HitPoints)
void cEntity::SetHealth(int a_Health)
{
- m_Health = std::max(0, std::min(m_MaxHealth, a_Health));
+ m_Health = Clamp(a_Health, 0, m_MaxHealth);
}
@@ -572,6 +561,8 @@ void cEntity::SetHealth(int a_Health)
void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
+ m_TicksAlive++;
+
if (m_InvulnerableTicks > 0)
{
m_InvulnerableTicks--;
@@ -624,9 +615,12 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
// Handle drowning
HandleAir();
}
-
- // None of the above functions change position, we remain in the chunk of NextChunk
- HandlePhysics(a_Dt, *NextChunk);
+
+ if (!DetectPortal()) // Our chunk is invalid if we have moved to another world
+ {
+ // None of the above functions changed position, we remain in the chunk of NextChunk
+ HandlePhysics(a_Dt, *NextChunk);
+ }
}
}
@@ -650,7 +644,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
{
- // Outside of the world
+ // Outside of the world
AddSpeedY(m_Gravity * a_Dt);
AddPosition(GetSpeed() * a_Dt);
return;
@@ -658,7 +652,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width);
- BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ );
+ BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ);
BLOCKTYPE BlockBelow = (BlockY > 0) ? NextChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block
{
@@ -737,21 +731,19 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
}
NextSpeed.y += fallspeed;
}
- else
+
+ // Friction
+ if (NextSpeed.SqrLength() > 0.0004f)
{
- // Friction
- if (NextSpeed.SqrLength() > 0.0004f)
+ NextSpeed.x *= 0.7f / (1 + a_Dt);
+ if (fabs(NextSpeed.x) < 0.05)
{
- NextSpeed.x *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.x) < 0.05)
- {
- NextSpeed.x = 0;
- }
- NextSpeed.z *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.z) < 0.05)
- {
- NextSpeed.z = 0;
- }
+ NextSpeed.x = 0;
+ }
+ NextSpeed.z *= 0.7f / (1 + a_Dt);
+ if (fabs(NextSpeed.z) < 0.05)
+ {
+ NextSpeed.z = 0;
}
}
@@ -762,13 +754,13 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
NextSpeed.x *= 0.25;
NextSpeed.z *= 0.25;
}
-
- //Get water direction
+
+ // Get water direction
Direction WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ);
- m_WaterSpeed *= 0.9f; //Reduce speed each tick
+ m_WaterSpeed *= 0.9f; // Reduce speed each tick
- switch(WaterDir)
+ switch (WaterDir)
{
case X_PLUS:
m_WaterSpeed.x = 0.2f;
@@ -823,7 +815,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
if (Tracer.HitNormal.y != 0.f) NextSpeed.y = 0.f;
if (Tracer.HitNormal.z != 0.f) NextSpeed.z = 0.f;
- if (Tracer.HitNormal.y == 1) // Hit BLOCK_FACE_YP, we are on the ground
+ if (Tracer.HitNormal.y == 1) // Hit BLOCK_FACE_YP, we are on the ground
{
m_bOnGround = true;
}
@@ -863,12 +855,12 @@ void cEntity::TickBurning(cChunk & a_Chunk)
// Remember the current burning state:
bool HasBeenBurning = (m_TicksLeftBurning > 0);
- if (m_World->IsWeatherWet())
+ if (GetWorld()->IsWeatherWetAt(POSX_TOINT, POSZ_TOINT))
{
if (POSY_TOINT > m_World->GetHeight(POSX_TOINT, POSZ_TOINT))
{
m_TicksLeftBurning = 0;
- }
+ }
}
// Do the burning damage:
@@ -1034,6 +1026,178 @@ void cEntity::DetectCacti(void)
+bool cEntity::DetectPortal()
+{
+ if (GetWorld()->GetDimension() == dimOverworld)
+ {
+ if (GetWorld()->GetNetherWorldName().empty() && GetWorld()->GetEndWorldName().empty())
+ {
+ // Teleportation to either dimension not enabled, don't bother proceeding
+ return false;
+ }
+ }
+ else if (GetWorld()->GetLinkedOverworldName().empty())
+ {
+ // Overworld teleportation disabled, abort
+ return false;
+ }
+
+ int X = POSX_TOINT, Y = POSY_TOINT, Z = POSZ_TOINT;
+ if ((Y > 0) && (Y < cChunkDef::Height))
+ {
+ switch (GetWorld()->GetBlock(X, Y, Z))
+ {
+ case E_BLOCK_NETHER_PORTAL:
+ {
+ if (m_PortalCooldownData.m_ShouldPreventTeleportation)
+ {
+ // Just exited a portal, don't teleport again
+ return false;
+ }
+
+ if (IsPlayer() && !((cPlayer *)this)->IsGameModeCreative() && m_PortalCooldownData.m_TicksDelayed != 80)
+ {
+ // Delay teleportation for four seconds if the entity is a non-creative player
+ m_PortalCooldownData.m_TicksDelayed++;
+ return false;
+ }
+ m_PortalCooldownData.m_TicksDelayed = 0;
+
+ if (GetWorld()->GetDimension() == dimNether)
+ {
+ if (GetWorld()->GetLinkedOverworldName().empty())
+ {
+ return false;
+ }
+
+ m_PortalCooldownData.m_ShouldPreventTeleportation = true; // Stop portals from working on respawn
+
+ if (IsPlayer())
+ {
+ ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimOverworld); // Send a respawn packet before world is loaded/generated so the client isn't left in limbo
+ }
+
+ return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false);
+ }
+ else
+ {
+ if (GetWorld()->GetNetherWorldName().empty())
+ {
+ return false;
+ }
+
+ m_PortalCooldownData.m_ShouldPreventTeleportation = true;
+
+ if (IsPlayer())
+ {
+ ((cPlayer *)this)->AwardAchievement(achEnterPortal);
+ ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimNether);
+ }
+
+ return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetNetherWorldName(), dimNether, GetWorld()->GetName()), false);
+ }
+ }
+ case E_BLOCK_END_PORTAL:
+ {
+ if (m_PortalCooldownData.m_ShouldPreventTeleportation)
+ {
+ return false;
+ }
+
+ if (GetWorld()->GetDimension() == dimEnd)
+ {
+
+ if (GetWorld()->GetLinkedOverworldName().empty())
+ {
+ return false;
+ }
+
+ m_PortalCooldownData.m_ShouldPreventTeleportation = true;
+
+ if (IsPlayer())
+ {
+ cPlayer * Player = (cPlayer *)this;
+ Player->TeleportToCoords(Player->GetLastBedPos().x, Player->GetLastBedPos().y, Player->GetLastBedPos().z);
+ Player->GetClientHandle()->SendRespawn(dimOverworld);
+ }
+
+ return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetLinkedOverworldName()), false);
+ }
+ else
+ {
+ if (GetWorld()->GetEndWorldName().empty())
+ {
+ return false;
+ }
+
+ m_PortalCooldownData.m_ShouldPreventTeleportation = true;
+
+ if (IsPlayer())
+ {
+ ((cPlayer *)this)->AwardAchievement(achEnterTheEnd);
+ ((cPlayer *)this)->GetClientHandle()->SendRespawn(dimEnd);
+ }
+
+ return MoveToWorld(cRoot::Get()->CreateAndInitializeWorld(GetWorld()->GetEndWorldName(), dimEnd, GetWorld()->GetName()), false);
+ }
+
+ }
+ default: break;
+ }
+ }
+
+ // Allow portals to work again
+ m_PortalCooldownData.m_ShouldPreventTeleportation = false;
+ m_PortalCooldownData.m_TicksDelayed = 0;
+ return false;
+}
+
+
+
+
+
+bool cEntity::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
+{
+ UNUSED(a_ShouldSendRespawn);
+ ASSERT(a_World != NULL);
+
+ if (GetWorld() == a_World)
+ {
+ // Don't move to same world
+ return false;
+ }
+
+ // Remove all links to the old world
+ SetWorldTravellingFrom(GetWorld()); // cChunk::Tick() handles entity removal
+ GetWorld()->BroadcastDestroyEntity(*this);
+
+ // Queue add to new world
+ a_World->AddEntity(this);
+ SetWorld(a_World);
+
+ return true;
+}
+
+
+
+
+
+bool cEntity::MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn)
+{
+ cWorld * World = cRoot::Get()->GetWorld(a_WorldName);
+ if (World == NULL)
+ {
+ LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName.c_str());
+ return false;
+ }
+
+ return DoMoveToWorld(World, a_ShouldSendRespawn);
+}
+
+
+
+
+
void cEntity::SetSwimState(cChunk & a_Chunk)
{
int RelY = (int)floor(GetPosY() + 0.1);
@@ -1090,17 +1254,17 @@ void cEntity::HandleAir(void)
if (IsSubmerged())
{
- if (!IsPlayer()) // Players control themselves
+ if (!IsPlayer()) // Players control themselves
{
- SetSpeedY(1); // Float in the water
+ SetSpeedY(1); // Float in the water
}
- // Either reduce air level or damage player
- if (m_AirLevel < 1)
+ if (m_AirLevel <= 0)
{
- if (m_AirTickTimer < 1)
+ // Runs the air tick timer to check whether the player should be damaged
+ if (m_AirTickTimer <= 0)
{
- // Damage player
+ // Damage player
TakeDamage(dtDrowning, NULL, 1, 1, 0);
// Reset timer
m_AirTickTimer = DROWNING_TICKS;
@@ -1156,10 +1320,7 @@ void cEntity::SetMaxHealth(int a_MaxHealth)
m_MaxHealth = a_MaxHealth;
// Reset health, if too high:
- if (m_Health > a_MaxHealth)
- {
- m_Health = a_MaxHealth;
- }
+ m_Health = std::min(m_Health, a_MaxHealth);
}
@@ -1261,9 +1422,9 @@ void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
int DiffY = (int)(floor(GetPosY() * 32.0) - floor(m_LastPos.y * 32.0));
int DiffZ = (int)(floor(GetPosZ() * 32.0) - floor(m_LastPos.z * 32.0));
- if ((DiffX != 0) || (DiffY != 0) || (DiffZ != 0)) // Have we moved?
+ if ((DiffX != 0) || (DiffY != 0) || (DiffZ != 0)) // Have we moved?
{
- if ((abs(DiffX) <= 127) && (abs(DiffY) <= 127) && (abs(DiffZ) <= 127)) // Limitations of a Byte
+ if ((abs(DiffX) <= 127) && (abs(DiffY) <= 127) && (abs(DiffZ) <= 127)) // Limitations of a Byte
{
// Difference within Byte limitations, use a relative move packet
if (m_bDirtyOrientation)
@@ -1283,7 +1444,7 @@ void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
{
// Too big a movement, do a teleport
m_World->BroadcastTeleportEntity(*this, a_Exclude);
- m_LastPos = GetPosition(); // See above
+ m_LastPos = GetPosition(); // See above
m_bDirtyOrientation = false;
}
}
@@ -1386,17 +1547,10 @@ void cEntity::SetHeight(double a_Height)
void cEntity::SetMass(double a_Mass)
{
- if (a_Mass > 0)
- {
- m_Mass = a_Mass;
- }
- else
- {
- // Make sure that mass is not zero. 1g is the default because we
- // have to choose a number. It's perfectly legal to have a mass
- // less than 1g as long as is NOT equal or less than zero.
- m_Mass = 0.001;
- }
+ // Make sure that mass is not zero. 1g is the default because we
+ // have to choose a number. It's perfectly legal to have a mass
+ // less than 1g as long as is NOT equal or less than zero.
+ m_Mass = std::max(a_Mass, 0.001);
}
@@ -1479,7 +1633,7 @@ void cEntity::SetWidth(double a_Width)
void cEntity::AddPosX(double a_AddPosX)
{
- m_Pos.x += a_AddPosX;
+ m_Pos.x += a_AddPosX;
}
@@ -1487,7 +1641,7 @@ void cEntity::AddPosX(double a_AddPosX)
void cEntity::AddPosY(double a_AddPosY)
{
- m_Pos.y += a_AddPosY;
+ m_Pos.y += a_AddPosY;
}
@@ -1495,7 +1649,7 @@ void cEntity::AddPosY(double a_AddPosY)
void cEntity::AddPosZ(double a_AddPosZ)
{
- m_Pos.z += a_AddPosZ;
+ m_Pos.z += a_AddPosZ;
}
@@ -1505,7 +1659,7 @@ void cEntity::AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ)
{
m_Pos.x += a_AddPosX;
m_Pos.y += a_AddPosY;
- m_Pos.z += a_AddPosZ;
+ m_Pos.z += a_AddPosZ;
}
@@ -1515,7 +1669,7 @@ void cEntity::AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeed
{
m_Speed.x += a_AddSpeedX;
m_Speed.y += a_AddSpeedY;
- m_Speed.z += a_AddSpeedZ;
+ m_Speed.z += a_AddSpeedZ;
WrapSpeed();
}
@@ -1525,7 +1679,7 @@ void cEntity::AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeed
void cEntity::AddSpeedX(double a_AddSpeedX)
{
- m_Speed.x += a_AddSpeedX;
+ m_Speed.x += a_AddSpeedX;
WrapSpeed();
}
@@ -1535,7 +1689,7 @@ void cEntity::AddSpeedX(double a_AddSpeedX)
void cEntity::AddSpeedY(double a_AddSpeedY)
{
- m_Speed.y += a_AddSpeedY;
+ m_Speed.y += a_AddSpeedY;
WrapSpeed();
}
@@ -1545,7 +1699,7 @@ void cEntity::AddSpeedY(double a_AddSpeedY)
void cEntity::AddSpeedZ(double a_AddSpeedZ)
{
- m_Speed.z += a_AddSpeedZ;
+ m_Speed.z += a_AddSpeedZ;
WrapSpeed();
}
@@ -1582,7 +1736,7 @@ void cEntity::SteerVehicle(float a_Forward, float a_Sideways)
-//////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Get look vector (this is NOT a rotation!)
Vector3d cEntity::GetLookVector(void) const
{
@@ -1596,11 +1750,11 @@ Vector3d cEntity::GetLookVector(void) const
-//////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Set position
void cEntity::SetPosition(double a_PosX, double a_PosY, double a_PosZ)
{
- m_Pos.Set(a_PosX, a_PosY, a_PosZ);
+ m_Pos.Set(a_PosX, a_PosY, a_PosZ);
}
@@ -1609,7 +1763,7 @@ void cEntity::SetPosition(double a_PosX, double a_PosY, double a_PosZ)
void cEntity::SetPosX(double a_PosX)
{
- m_Pos.x = a_PosX;
+ m_Pos.x = a_PosX;
}
@@ -1618,7 +1772,7 @@ void cEntity::SetPosX(double a_PosX)
void cEntity::SetPosY(double a_PosY)
{
- m_Pos.y = a_PosY;
+ m_Pos.y = a_PosY;
}
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index f4080f8aa..b9c280b6b 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -128,20 +128,20 @@ public:
esFireworkExploding = 17,
} ;
- enum
- {
- FIRE_TICKS_PER_DAMAGE = 10, ///< How many ticks to wait between damaging an entity when it stands in fire
- FIRE_DAMAGE = 1, ///< How much damage to deal when standing in fire
- LAVA_TICKS_PER_DAMAGE = 10, ///< How many ticks to wait between damaging an entity when it stands in lava
- LAVA_DAMAGE = 5, ///< How much damage to deal when standing in lava
- BURN_TICKS_PER_DAMAGE = 20, ///< How many ticks to wait between damaging an entity when it is burning
- BURN_DAMAGE = 1, ///< How much damage to deal when the entity is burning
- BURN_TICKS = 200, ///< How long to keep an entity burning after it has stood in lava / fire
- MAX_AIR_LEVEL = 300, ///< Maximum air an entity can have
- DROWNING_TICKS = 20, ///< Number of ticks per heart of damage
- VOID_BOUNDARY = -46, ///< At what position Y to begin applying void damage
- FALL_DAMAGE_HEIGHT = 4 ///< At what position Y fall damage is applied
- } ;
+ static const int FIRE_TICKS_PER_DAMAGE = 10; ///< Ticks to wait between damaging an entity when it stands in fire
+ static const int FIRE_DAMAGE = 1; ///< Damage to deal when standing in fire
+ static const int LAVA_TICKS_PER_DAMAGE = 10; ///< Ticks to wait between damaging an entity when it stands in lava
+ static const int LAVA_DAMAGE = 5; ///< Damage to deal when standing in lava
+ static const int BURN_TICKS_PER_DAMAGE = 20; ///< Ticks to wait between damaging an entity when it is burning
+ static const int BURN_DAMAGE = 1; ///< Damage to deal when the entity is burning
+
+ static const int BURN_TICKS = 200; ///< Ticks to keep an entity burning after it has stood in lava / fire
+
+ static const int MAX_AIR_LEVEL = 300; ///< Maximum air an entity can have
+ static const int DROWNING_TICKS = 20; ///< Number of ticks per heart of damage
+
+ static const int VOID_BOUNDARY = -46; ///< Y position to begin applying void damage
+ static const int FALL_DAMAGE_HEIGHT = 4; ///< Y difference after which fall damage is applied
cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
virtual ~cEntity();
@@ -158,6 +158,7 @@ public:
bool IsPlayer (void) const { return (m_EntityType == etPlayer); }
bool IsPickup (void) const { return (m_EntityType == etPickup); }
bool IsMob (void) const { return (m_EntityType == etMonster); }
+ bool IsPawn (void) const { return (IsMob() || IsPlayer()); }
bool IsFallingBlock(void) const { return (m_EntityType == etFallingBlock); }
bool IsMinecart (void) const { return (m_EntityType == etMinecart); }
bool IsBoat (void) const { return (m_EntityType == etBoat); }
@@ -309,13 +310,13 @@ public:
virtual cItem GetEquippedBoots(void) const { return cItem(); }
/// Called when the health drops below zero. a_Killer may be NULL (environmental damage)
- virtual void KilledBy(cEntity * a_Killer);
+ virtual void KilledBy(TakeDamageInfo & a_TDI);
/// Called when the entity kills another entity
virtual void Killed(cEntity * a_Victim) {}
/// Heals the specified amount of HPs
- void Heal(int a_HitPoints);
+ virtual void Heal(int a_HitPoints);
/// Returns the health of this entity
int GetHealth(void) const { return m_Health; }
@@ -335,6 +336,11 @@ public:
/** Detects the time for application of cacti damage */
virtual void DetectCacti(void);
+
+ /** Detects whether we are in a portal block and begins teleportation procedures if so
+ Returns true if MoveToWorld() was called, false if not
+ */
+ virtual bool DetectPortal(void);
/// Handles when the entity is in the void
virtual void TickInVoid(cChunk & a_Chunk);
@@ -377,8 +383,22 @@ public:
/// Teleports to the coordinates specified
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ);
+
+ /** Moves entity to specified world, taking a world pointer */
+ bool MoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn = true) { return DoMoveToWorld(a_World, a_ShouldSendRespawn); }
+
+ /** Moves entity to specified world, taking a world name */
+ bool MoveToWorld(const AString & a_WorldName, bool a_ShouldSendRespawn = true);
// tolua_end
+
+ virtual bool DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn);
+
+ /** Returns if the entity is travelling away from a specified world */
+ bool IsWorldTravellingFrom(cWorld * a_World) const { return (m_WorldTravellingFrom == a_World); }
+
+ /** Sets the world the entity will be leaving */
+ void SetWorldTravellingFrom(cWorld * a_World) { m_WorldTravellingFrom = a_World; }
/// Updates clients of changes in the entity.
virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = NULL);
@@ -415,6 +435,9 @@ public:
/** Gets remaining air of a monster */
int GetAirLevel(void) const { return m_AirLevel; }
+ /** Gets number of ticks this entity has existed for */
+ long int GetTicksAlive(void) const { return m_TicksAlive; }
+
/** Gets the invulnerable ticks from the entity */
int GetInvulnerableTicks(void) const { return m_InvulnerableTicks; }
@@ -424,10 +447,10 @@ public:
// tolua_end
/// Called when the specified player right-clicks this entity
- virtual void OnRightClicked(cPlayer &) {};
+ virtual void OnRightClicked(cPlayer &) {}
/// Returns the list of drops for this pawn when it is killed. May check a_Killer for special handling (sword of looting etc.). Called from KilledBy().
- virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL)
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL)
{
UNUSED(a_Drops);
UNUSED(a_Killer);
@@ -478,13 +501,19 @@ protected:
/** True when entity is initialised (Initialize()) and false when destroyed pending deletion (Destroy()) */
bool m_IsInitialized;
+ /** World entity is travelling from
+ Set to a valid world pointer by MoveToWorld; reset to NULL when the entity is removed from the old world
+ Can't be a simple boolean as context switches between worlds may leave the new chunk processing (and therefore immediately removing) the entity before the old chunk could remove it
+ */
+ cWorld * m_WorldTravellingFrom;
+
eEntityType m_EntityType;
cWorld * m_World;
/// Whether the entity is capable of taking fire or lava damage.
bool m_IsFireproof;
-
+
/// Time, in ticks, since the last damage dealt by being on fire. Valid only if on fire (IsOnFire())
int m_TicksSinceLastBurnDamage;
@@ -499,13 +528,12 @@ protected:
/// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void.
int m_TicksSinceLastVoidDamage;
-
/** Does the actual speed-setting. The default implementation just sets the member variable value;
overrides can provide further processing, such as forcing players to move at the given speed. */
virtual void DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ);
- virtual void Destroyed(void) {} // Called after the entity has been destroyed
+ virtual void Destroyed(void) {} // Called after the entity has been destroyed
/** Called in each tick to handle air-related processing i.e. drowning */
virtual void HandleAir(void);
@@ -519,6 +547,24 @@ protected:
/** Air level of a mobile */
int m_AirLevel;
int m_AirTickTimer;
+
+ /** Structure storing the portal delay timer and cooldown boolean */
+ struct sPortalCooldownData
+ {
+ /** Ticks since entry of portal, used to delay teleportation */
+ unsigned short m_TicksDelayed;
+
+ /** Whether the entity has just exited the portal, and should therefore not be teleported again
+ This prevents teleportation loops, and is reset when the entity has moved out of the portal
+ */
+ bool m_ShouldPreventTeleportation;
+ };
+
+ /** Portal delay timer and cooldown boolean data */
+ sPortalCooldownData m_PortalCooldownData;
+
+ /** The number of ticks this entity has been alive for */
+ long int m_TicksAlive;
private:
/** Measured in degrees, [-180, +180) */
diff --git a/src/Entities/EntityEffect.cpp b/src/Entities/EntityEffect.cpp
new file mode 100644
index 000000000..3e28392f4
--- /dev/null
+++ b/src/Entities/EntityEffect.cpp
@@ -0,0 +1,411 @@
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "EntityEffect.h"
+#include "../Mobs/Monster.h"
+#include "Player.h"
+
+
+
+
+
+int cEntityEffect::GetPotionColor(short a_ItemDamage)
+{
+ // Lowest six bits
+ return (a_ItemDamage & 0x3f);
+}
+
+
+
+
+
+cEntityEffect::eType cEntityEffect::GetPotionEffectType(short a_ItemDamage)
+{
+ // Lowest four bits
+ // Potion effect bits are different from entity effect values
+ // For reference: http://minecraft.gamepedia.com/Data_values#.22Potion_effect.22_bits
+ switch (a_ItemDamage & 0x0f)
+ {
+ case 0x01: return cEntityEffect::effRegeneration;
+ case 0x02: return cEntityEffect::effSpeed;
+ case 0x03: return cEntityEffect::effFireResistance;
+ case 0x04: return cEntityEffect::effPoison;
+ case 0x05: return cEntityEffect::effInstantHealth;
+ case 0x06: return cEntityEffect::effNightVision;
+ case 0x08: return cEntityEffect::effWeakness;
+ case 0x09: return cEntityEffect::effStrength;
+ case 0x0a: return cEntityEffect::effSlowness;
+ case 0x0c: return cEntityEffect::effInstantDamage;
+ case 0x0d: return cEntityEffect::effWaterBreathing;
+ case 0x0e: return cEntityEffect::effInvisibility;
+
+ // No effect potions
+ case 0x00:
+ case 0x07:
+ case 0x0b: // Will be potion of leaping in 1.8
+ case 0x0f:
+ {
+ break;
+ }
+ }
+ return cEntityEffect::effNoEffect;
+}
+
+
+
+
+
+short cEntityEffect::GetPotionEffectIntensity(short a_ItemDamage)
+{
+ // Level II potion if the fifth lowest bit is set
+ return ((a_ItemDamage & 0x20) != 0) ? 1 : 0;
+}
+
+
+
+
+
+int cEntityEffect::GetPotionEffectDuration(short a_ItemDamage)
+{
+ // Base duration in ticks
+ int base = 0;
+ double TierCoeff = 1, ExtCoeff = 1, SplashCoeff = 1;
+
+ switch (GetPotionEffectType(a_ItemDamage))
+ {
+ case cEntityEffect::effRegeneration:
+ case cEntityEffect::effPoison:
+ {
+ base = 900;
+ break;
+ }
+
+ case cEntityEffect::effSpeed:
+ case cEntityEffect::effFireResistance:
+ case cEntityEffect::effNightVision:
+ case cEntityEffect::effStrength:
+ case cEntityEffect::effWaterBreathing:
+ case cEntityEffect::effInvisibility:
+ {
+ base = 3600;
+ break;
+ }
+
+ case cEntityEffect::effWeakness:
+ case cEntityEffect::effSlowness:
+ {
+ base = 1800;
+ break;
+ }
+ }
+
+ // If potion is level II, half the duration. If not, stays the same
+ TierCoeff = (GetPotionEffectIntensity(a_ItemDamage) > 0) ? 0.5 : 1;
+
+ // If potion is extended, multiply duration by 8/3. If not, stays the same
+ // Extended potion if sixth lowest bit is set
+ ExtCoeff = (a_ItemDamage & 0x40) ? (8.0 / 3.0) : 1;
+
+ // If potion is splash potion, multiply duration by 3/4. If not, stays the same
+ SplashCoeff = IsPotionDrinkable(a_ItemDamage) ? 1 : 0.75;
+
+ // Ref.:
+ // http://minecraft.gamepedia.com/Data_values#.22Tier.22_bit
+ // http://minecraft.gamepedia.com/Data_values#.22Extended_duration.22_bit
+ // http://minecraft.gamepedia.com/Data_values#.22Splash_potion.22_bit
+
+ return (int)(base * TierCoeff * ExtCoeff * SplashCoeff);
+}
+
+
+
+
+
+bool cEntityEffect::IsPotionDrinkable(short a_ItemDamage)
+{
+ // Drinkable potion if 13th lowest bit is set
+ // Ref.: http://minecraft.gamepedia.com/Potions#Data_value_table
+ return ((a_ItemDamage & 0x2000) != 0);
+}
+
+
+
+
+
+cEntityEffect::cEntityEffect():
+ m_Ticks(0),
+ m_Duration(0),
+ m_Intensity(0),
+ m_DistanceModifier(1)
+{
+
+}
+
+
+
+
+
+cEntityEffect::cEntityEffect(int a_Duration, short a_Intensity, double a_DistanceModifier):
+ m_Ticks(0),
+ m_Duration(a_Duration),
+ m_Intensity(a_Intensity),
+ m_DistanceModifier(a_DistanceModifier)
+{
+
+}
+
+
+
+
+
+cEntityEffect::cEntityEffect(const cEntityEffect & a_OtherEffect):
+ m_Ticks(a_OtherEffect.m_Ticks),
+ m_Duration(a_OtherEffect.m_Duration),
+ m_Intensity(a_OtherEffect.m_Intensity),
+ m_DistanceModifier(a_OtherEffect.m_DistanceModifier)
+{
+
+}
+
+
+
+
+
+cEntityEffect & cEntityEffect::operator =(cEntityEffect a_OtherEffect)
+{
+ std::swap(m_Ticks, a_OtherEffect.m_Ticks);
+ std::swap(m_Duration, a_OtherEffect.m_Duration);
+ std::swap(m_Intensity, a_OtherEffect.m_Intensity);
+ std::swap(m_DistanceModifier, a_OtherEffect.m_DistanceModifier);
+ return *this;
+}
+
+
+
+
+
+cEntityEffect * cEntityEffect::CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier)
+{
+ switch (a_EffectType)
+ {
+ case cEntityEffect::effNoEffect: return new cEntityEffect (a_Duration, a_Intensity, a_DistanceModifier);
+
+ case cEntityEffect::effAbsorption: return new cEntityEffectAbsorption (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effBlindness: return new cEntityEffectBlindness (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effFireResistance: return new cEntityEffectFireResistance(a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effHaste: return new cEntityEffectHaste (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effHealthBoost: return new cEntityEffectHealthBoost (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effHunger: return new cEntityEffectHunger (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effInstantDamage: return new cEntityEffectInstantDamage (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effInstantHealth: return new cEntityEffectInstantHealth (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effInvisibility: return new cEntityEffectInvisibility (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effJumpBoost: return new cEntityEffectJumpBoost (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effMiningFatigue: return new cEntityEffectMiningFatigue (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effNausea: return new cEntityEffectNausea (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effNightVision: return new cEntityEffectNightVision (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effPoison: return new cEntityEffectPoison (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effRegeneration: return new cEntityEffectRegeneration (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effResistance: return new cEntityEffectResistance (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effSaturation: return new cEntityEffectSaturation (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effSlowness: return new cEntityEffectSlowness (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effSpeed: return new cEntityEffectSpeed (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effStrength: return new cEntityEffectStrength (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effWaterBreathing: return new cEntityEffectWaterBreathing(a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effWeakness: return new cEntityEffectWeakness (a_Duration, a_Intensity, a_DistanceModifier);
+ case cEntityEffect::effWither: return new cEntityEffectWither (a_Duration, a_Intensity, a_DistanceModifier);
+ }
+
+ ASSERT(!"Unhandled entity effect type!");
+ return NULL;
+}
+
+
+
+
+
+void cEntityEffect::OnTick(cPawn & a_Target)
+{
+ // Reduce the effect's duration
+ ++m_Ticks;
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cEntityEffectInstantHealth:
+
+void cEntityEffectInstantHealth::OnActivate(cPawn & a_Target)
+{
+ // Base amount = 6, doubles for every increase in intensity
+ int amount = (int)(6 * (1 << m_Intensity) * m_DistanceModifier);
+
+ if (a_Target.IsMob() && ((cMonster &) a_Target).IsUndead())
+ {
+ a_Target.TakeDamage(dtPotionOfHarming, NULL, amount, 0); // TODO: Store attacker in a pointer-safe way, pass to TakeDamage
+ return;
+ }
+ a_Target.Heal(amount);
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cEntityEffectInstantDamage:
+
+void cEntityEffectInstantDamage::OnActivate(cPawn & a_Target)
+{
+ // Base amount = 6, doubles for every increase in intensity
+ int amount = (int)(6 * (1 << m_Intensity) * m_DistanceModifier);
+
+ if (a_Target.IsMob() && ((cMonster &) a_Target).IsUndead())
+ {
+ a_Target.Heal(amount);
+ return;
+ }
+ a_Target.TakeDamage(dtPotionOfHarming, NULL, amount, 0); // TODO: Store attacker in a pointer-safe way, pass to TakeDamage
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cEntityEffectRegeneration:
+
+void cEntityEffectRegeneration::OnTick(cPawn & a_Target)
+{
+ super::OnTick(a_Target);
+
+ if (a_Target.IsMob() && ((cMonster &) a_Target).IsUndead())
+ {
+ return;
+ }
+
+ // Regen frequency = 50 ticks, divided by potion level (Regen II = 25 ticks)
+ int frequency = (int) std::floor(50.0 / (double)(m_Intensity + 1));
+
+ if ((m_Ticks % frequency) != 0)
+ {
+ return;
+ }
+
+ a_Target.Heal(1);
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cEntityEffectHunger:
+
+void cEntityEffectHunger::OnTick(cPawn & a_Target)
+{
+ super::OnTick(a_Target);
+
+ if (a_Target.IsPlayer())
+ {
+ cPlayer & Target = (cPlayer &) a_Target;
+ Target.AddFoodExhaustion(0.025 * ((double)GetIntensity() + 1.0)); // 0.5 per second = 0.025 per tick
+ }
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cEntityEffectWeakness:
+
+void cEntityEffectWeakness::OnTick(cPawn & a_Target)
+{
+ super::OnTick(a_Target);
+
+ // Damage reduction = 0.5 damage, multiplied by potion level (Weakness II = 1 damage)
+ // double dmg_reduc = 0.5 * (a_Effect.GetIntensity() + 1);
+
+ // TODO: Implement me!
+ // TODO: Weakened villager zombies can be turned back to villagers with the god apple
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cEntityEffectPoison:
+
+void cEntityEffectPoison::OnTick(cPawn & a_Target)
+{
+ super::OnTick(a_Target);
+
+ if (a_Target.IsMob())
+ {
+ cMonster & Target = (cMonster &) a_Target;
+
+ // Doesn't effect undead mobs, spiders
+ if (
+ Target.IsUndead() ||
+ (Target.GetMobType() == cMonster::mtSpider) ||
+ (Target.GetMobType() == cMonster::mtCaveSpider)
+ )
+ {
+ return;
+ }
+ }
+
+ // Poison frequency = 25 ticks, divided by potion level (Poison II = 12 ticks)
+ int frequency = (int) std::floor(25.0 / (double)(m_Intensity + 1));
+
+ if ((m_Ticks % frequency) == 0)
+ {
+ // Cannot take poison damage when health is at 1
+ if (a_Target.GetHealth() > 1)
+ {
+ a_Target.TakeDamage(dtPoisoning, NULL, 1, 0);
+ }
+ }
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cEntityEffectWither:
+
+void cEntityEffectWither::OnTick(cPawn & a_Target)
+{
+ super::OnTick(a_Target);
+
+ // Damage frequency = 40 ticks, divided by effect level (Wither II = 20 ticks)
+ int frequency = (int) std::floor(25.0 / (double)(m_Intensity + 1));
+
+ if ((m_Ticks % frequency) == 0)
+ {
+ a_Target.TakeDamage(dtWither, NULL, 1, 0);
+ }
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cEntityEffectSaturation:
+
+void cEntityEffectSaturation::OnTick(cPawn & a_Target)
+{
+ if (a_Target.IsPlayer())
+ {
+ cPlayer & Target = (cPlayer &) a_Target;
+ Target.SetFoodSaturationLevel(Target.GetFoodSaturationLevel() + (1 + m_Intensity)); // Increase saturation 1 per tick, adds 1 for every increase in level
+ }
+}
+
+
+
+
diff --git a/src/Entities/EntityEffect.h b/src/Entities/EntityEffect.h
new file mode 100644
index 000000000..47c298f57
--- /dev/null
+++ b/src/Entities/EntityEffect.h
@@ -0,0 +1,494 @@
+#pragma once
+
+class cPawn;
+
+// tolua_begin
+class cEntityEffect
+{
+public:
+
+ /** All types of entity effects (numbers correspond to protocol / storage types) */
+ enum eType
+ {
+ effNoEffect = 0,
+ effSpeed = 1,
+ effSlowness = 2,
+ effHaste = 3,
+ effMiningFatigue = 4,
+ effStrength = 5,
+ effInstantHealth = 6,
+ effInstantDamage = 7,
+ effJumpBoost = 8,
+ effNausea = 9,
+ effRegeneration = 10,
+ effResistance = 11,
+ effFireResistance = 12,
+ effWaterBreathing = 13,
+ effInvisibility = 14,
+ effBlindness = 15,
+ effNightVision = 16,
+ effHunger = 17,
+ effWeakness = 18,
+ effPoison = 19,
+ effWither = 20,
+ effHealthBoost = 21,
+ effAbsorption = 22,
+ effSaturation = 23,
+ } ;
+
+ /** Returns the potion color (used by the client for visuals), based on the potion's damage value */
+ static int GetPotionColor(short a_ItemDamage);
+
+
+ /** Translates the potion's damage value into the entity effect that the potion gives */
+ static cEntityEffect::eType GetPotionEffectType(short a_ItemDamage);
+
+
+ /** Retrieves the intensity level from the potion's damage value. Returns 0 for level I potions, 1 for level II potions. */
+ static short GetPotionEffectIntensity(short a_ItemDamage);
+
+
+ /** Returns the effect duration, in ticks, based on the potion's damage value */
+ static int GetPotionEffectDuration(short a_ItemDamage);
+
+ /** Returns true if the potion with the given damage is drinkable */
+ static bool IsPotionDrinkable(short a_ItemDamage);
+
+ // tolua_end
+
+ /** Creates an empty entity effect */
+ cEntityEffect(void);
+
+ /** Creates an entity effect of the specified type
+ @param a_Duration How long this effect will last, in ticks
+ @param a_Intensity How strong the effect will be applied
+ @param a_DistanceModifier The distance modifier for affecting potency, defaults to 1 */
+ cEntityEffect(int a_Duration, short a_Intensity, double a_DistanceModifier = 1);
+
+ /** Creates an entity effect by copying another
+ @param a_OtherEffect The other effect to copy */
+ cEntityEffect(const cEntityEffect & a_OtherEffect);
+
+ /** Creates an entity effect by copying another
+ @param a_OtherEffect The other effect to copy */
+ cEntityEffect & operator =(cEntityEffect a_OtherEffect);
+
+ virtual ~cEntityEffect(void) {}
+
+ /** Creates a pointer to the proper entity effect from the effect type
+ @warning This function creates raw pointers that must be manually managed.
+ @param a_EffectType The effect type to create the effect from
+ @param a_Duration How long this effect will last, in ticks
+ @param a_Intensity How strong the effect will be applied
+ @param a_DistanceModifier The distance modifier for affecting potency, defaults to 1 */
+ static cEntityEffect * CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier);
+
+ /** Returns how many ticks this effect has been active for */
+ int GetTicks(void) const { return m_Ticks; }
+
+ /** Returns the duration of the effect */
+ int GetDuration(void) const { return m_Duration; }
+
+ /** Returns how strong the effect will be applied */
+ short GetIntensity(void) const { return m_Intensity; }
+
+ /** Returns the distance modifier for affecting potency */
+ double GetDistanceModifier(void) const { return m_DistanceModifier; }
+
+ void SetTicks(int a_Ticks) { m_Ticks = a_Ticks; }
+ void SetDuration(int a_Duration) { m_Duration = a_Duration; }
+ void SetIntensity(short a_Intensity) { m_Intensity = a_Intensity; }
+ void SetDistanceModifier(double a_DistanceModifier) { m_DistanceModifier = a_DistanceModifier; }
+
+ /** Called on each tick.
+ By default increases the m_Ticks, descendants may override to provide additional processing. */
+ virtual void OnTick(cPawn & a_Target);
+
+ /** Called when the effect is first added to an entity */
+ virtual void OnActivate(cPawn & a_Target) { }
+
+ /** Called when the effect is removed from an entity */
+ virtual void OnDeactivate(cPawn & a_Target) { }
+
+protected:
+ /** How many ticks this effect has been active for */
+ int m_Ticks;
+
+ /** How long this effect will last, in ticks */
+ int m_Duration;
+
+ /** How strong the effect will be applied */
+ short m_Intensity;
+
+ /** The distance modifier for affecting potency */
+ double m_DistanceModifier;
+}; // tolua_export
+
+
+
+
+
+class cEntityEffectSpeed:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectSpeed(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectSlowness:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectSlowness(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectHaste:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectHaste(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectMiningFatigue:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectMiningFatigue(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectStrength:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectStrength(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectInstantHealth:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectInstantHealth(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+
+ virtual void OnActivate(cPawn & a_Target) override;
+};
+
+
+
+
+
+class cEntityEffectInstantDamage:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectInstantDamage(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+
+ virtual void OnActivate(cPawn & a_Target) override;
+};
+
+
+
+
+
+class cEntityEffectJumpBoost:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectJumpBoost(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectNausea:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectNausea(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectRegeneration:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectRegeneration(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+
+ virtual void OnTick(cPawn & a_Target) override;
+};
+
+
+
+
+
+class cEntityEffectResistance:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectResistance(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectFireResistance:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectFireResistance(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectWaterBreathing:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectWaterBreathing(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectInvisibility:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectInvisibility(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectBlindness:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectBlindness(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectNightVision:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectNightVision(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectHunger:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectHunger(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+
+ // cEntityEffect overrides:
+ virtual void OnTick(cPawn & a_Target) override;
+};
+
+
+
+
+
+class cEntityEffectWeakness:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectWeakness(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+
+ // cEntityEffect overrides:
+ virtual void OnTick(cPawn & a_Target) override;
+};
+
+
+
+
+
+class cEntityEffectPoison:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectPoison(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+
+ // cEntityEffect overrides:
+ virtual void OnTick(cPawn & a_Target) override;
+};
+
+
+
+
+
+class cEntityEffectWither:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectWither(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+
+ // cEntityEffect overrides:
+ virtual void OnTick(cPawn & a_Target) override;
+};
+
+
+
+
+
+class cEntityEffectHealthBoost:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectHealthBoost(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectAbsorption:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectAbsorption(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+};
+
+
+
+
+
+class cEntityEffectSaturation:
+ public cEntityEffect
+{
+ typedef cEntityEffect super;
+public:
+ cEntityEffectSaturation(int a_Duration, short a_Intensity, double a_DistanceModifier = 1):
+ super(a_Duration, a_Intensity, a_DistanceModifier)
+ {
+ }
+
+ virtual void OnTick(cPawn & a_Target) override;
+};
+
+
+
+
diff --git a/src/Entities/ExpBottleEntity.h b/src/Entities/ExpBottleEntity.h
index b2043d8f1..d62a84469 100644
--- a/src/Entities/ExpBottleEntity.h
+++ b/src/Entities/ExpBottleEntity.h
@@ -21,7 +21,7 @@ public:
// tolua_end
- CLASS_PROTODEF(cExpBottleEntity);
+ CLASS_PROTODEF(cExpBottleEntity)
cExpBottleEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
@@ -30,4 +30,4 @@ protected:
// cProjectileEntity overrides:
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
-}; // tolua_export
+}; // tolua_export
diff --git a/src/Entities/ExpOrb.cpp b/src/Entities/ExpOrb.cpp
index 10f79aedc..73d5cbfed 100644
--- a/src/Entities/ExpOrb.cpp
+++ b/src/Entities/ExpOrb.cpp
@@ -6,7 +6,7 @@
cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward)
- : cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98)
+ : cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98)
, m_Reward(a_Reward)
, m_Timer(0.f)
{
@@ -19,7 +19,7 @@ cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward)
cExpOrb::cExpOrb(const Vector3d & a_Pos, int a_Reward)
- : cEntity(etExpOrb, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98)
+ : cEntity(etExpOrb, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98)
, m_Reward(a_Reward)
, m_Timer(0.f)
{
@@ -56,15 +56,15 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk)
LOGD("Player %s picked up an ExpOrb. His reward is %i", a_ClosestPlayer->GetName().c_str(), m_Reward);
a_ClosestPlayer->DeltaExperience(m_Reward);
- m_World->BroadcastSoundEffect("random.orb", (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
+ m_World->BroadcastSoundEffect("random.orb", GetPosX(), GetPosY(), GetPosZ(), 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
Destroy();
}
a_Distance.Normalize();
a_Distance *= ((float) (5.5 - Distance));
- SetSpeedX( a_Distance.x );
- SetSpeedY( a_Distance.y );
- SetSpeedZ( a_Distance.z );
+ SetSpeedX( a_Distance.x);
+ SetSpeedY( a_Distance.y);
+ SetSpeedZ( a_Distance.z);
BroadcastMovementUpdate();
}
HandlePhysics(a_Dt, a_Chunk);
diff --git a/src/Entities/ExpOrb.h b/src/Entities/ExpOrb.h
index e76274ac9..bdb9a5b19 100644
--- a/src/Entities/ExpOrb.h
+++ b/src/Entities/ExpOrb.h
@@ -11,12 +11,12 @@
class cExpOrb :
public cEntity
{
- typedef cExpOrb super;
+ typedef cEntity super;
public:
// tolua_end
- CLASS_PROTODEF(cExpOrb);
+ CLASS_PROTODEF(cExpOrb)
cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward);
cExpOrb(const Vector3d & a_Pos, int a_Reward);
diff --git a/src/Entities/FallingBlock.h b/src/Entities/FallingBlock.h
index 5ba9909bb..c20fe8eb9 100644
--- a/src/Entities/FallingBlock.h
+++ b/src/Entities/FallingBlock.h
@@ -20,7 +20,7 @@ class cFallingBlock :
typedef cEntity super;
public:
- CLASS_PROTODEF(cFallingBlock);
+ CLASS_PROTODEF(cFallingBlock)
/// Creates a new falling block. a_BlockPosition is expected in world coords
cFallingBlock(const Vector3i & a_BlockPosition, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
diff --git a/src/Entities/FireChargeEntity.h b/src/Entities/FireChargeEntity.h
index 3924c337c..5df55bec4 100644
--- a/src/Entities/FireChargeEntity.h
+++ b/src/Entities/FireChargeEntity.h
@@ -21,7 +21,7 @@ public:
// tolua_end
- CLASS_PROTODEF(cFireChargeEntity);
+ CLASS_PROTODEF(cFireChargeEntity)
cFireChargeEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
@@ -33,4 +33,4 @@ protected:
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
-} ; // tolua_export
+} ; // tolua_export
diff --git a/src/Entities/FireworkEntity.h b/src/Entities/FireworkEntity.h
index c62ca9402..20f18b6dc 100644
--- a/src/Entities/FireworkEntity.h
+++ b/src/Entities/FireworkEntity.h
@@ -21,7 +21,7 @@ public:
// tolua_end
- CLASS_PROTODEF(cFireworkEntity);
+ CLASS_PROTODEF(cFireworkEntity)
cFireworkEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem & a_Item);
const cItem & GetItem(void) const { return m_FireworkItem; }
@@ -37,4 +37,4 @@ private:
int m_ExplodeTimer;
cItem m_FireworkItem;
-}; // tolua_export
+}; // tolua_export
diff --git a/src/Entities/Floater.cpp b/src/Entities/Floater.cpp
index b910c3769..159429147 100644
--- a/src/Entities/Floater.cpp
+++ b/src/Entities/Floater.cpp
@@ -11,7 +11,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFloaterEntityCollisionCallback
class cFloaterEntityCollisionCallback :
public cEntityCallback
@@ -75,7 +75,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFloaterCheckEntityExist
class cFloaterCheckEntityExist :
public cEntityCallback
@@ -130,18 +130,18 @@ void cFloater::Tick(float a_Dt, cChunk & a_Chunk)
HandlePhysics(a_Dt, a_Chunk);
if (IsBlockWater(m_World->GetBlock((int) GetPosX(), (int) GetPosY(), (int) GetPosZ())) && m_World->GetBlockMeta((int) GetPosX(), (int) GetPosY(), (int) GetPosZ()) == 0)
{
- if ((!m_CanPickupItem) && (m_AttachedMobID == -1)) // Check if you can't already pickup a fish and if the floater isn't attached to a mob.
+ if ((!m_CanPickupItem) && (m_AttachedMobID == -1)) // Check if you can't already pickup a fish and if the floater isn't attached to a mob.
{
if (m_CountDownTime <= 0)
{
- m_World->BroadcastSoundEffect("random.splash", (int) floor(GetPosX() * 8), (int) floor(GetPosY() * 8), (int) floor(GetPosZ() * 8), 1, 1);
+ m_World->BroadcastSoundEffect("random.splash", GetPosX(), GetPosY(), GetPosZ(), 1, 1);
SetPosY(GetPosY() - 1);
m_CanPickupItem = true;
m_PickupCountDown = 20;
m_CountDownTime = 100 + m_World->GetTickRandomNumber(800);
LOGD("Floater %i can be picked up", GetUniqueID());
}
- else if (m_CountDownTime == 20) // Calculate the position where the particles should spawn and start producing them.
+ else if (m_CountDownTime == 20) // Calculate the position where the particles should spawn and start producing them.
{
LOGD("Started producing particles for floater %i", GetUniqueID());
m_ParticlePos.Set(GetPosX() + (-4 + m_World->GetTickRandomNumber(8)), GetPosY(), GetPosZ() + (-4 + m_World->GetTickRandomNumber(8)));
@@ -156,12 +156,12 @@ void cFloater::Tick(float a_Dt, cChunk & a_Chunk)
m_CountDownTime--;
if (m_World->GetHeight((int) GetPosX(), (int) GetPosZ()) == (int) GetPosY())
{
- if (m_World->IsWeatherWet() && m_World->GetTickRandomNumber(3) == 0) // 25% chance of an extra countdown when being rained on.
+ if (m_World->IsWeatherWet() && m_World->GetTickRandomNumber(3) == 0) // 25% chance of an extra countdown when being rained on.
{
m_CountDownTime--;
}
}
- else // if the floater is underground it has a 50% chance of not decreasing the countdown.
+ else // if the floater is underground it has a 50% chance of not decreasing the countdown.
{
if (m_World->GetTickRandomNumber(1) == 0)
{
@@ -190,21 +190,21 @@ void cFloater::Tick(float a_Dt, cChunk & a_Chunk)
if (Callback.HasHit())
{
AttachTo(Callback.GetHitEntity());
- Callback.GetHitEntity()->TakeDamage(*this); // TODO: the player attacked the mob not the floater.
+ Callback.GetHitEntity()->TakeDamage(*this); // TODO: the player attacked the mob not the floater.
m_AttachedMobID = Callback.GetHitEntity()->GetUniqueID();
}
}
cFloaterCheckEntityExist EntityCallback;
m_World->DoWithEntityByID(m_PlayerID, EntityCallback);
- if (!EntityCallback.DoesExist()) // The owner doesn't exist anymore. Destroy the floater entity.
+ if (!EntityCallback.DoesExist()) // The owner doesn't exist anymore. Destroy the floater entity.
{
Destroy(true);
}
if (m_AttachedMobID != -1)
{
- m_World->DoWithEntityByID(m_AttachedMobID, EntityCallback); // The mob the floater was attached to doesn't exist anymore.
+ m_World->DoWithEntityByID(m_AttachedMobID, EntityCallback); // The mob the floater was attached to doesn't exist anymore.
if (!EntityCallback.DoesExist())
{
m_AttachedMobID = -1;
diff --git a/src/Entities/Floater.h b/src/Entities/Floater.h
index 547d503f1..96d77ac82 100644
--- a/src/Entities/Floater.h
+++ b/src/Entities/Floater.h
@@ -14,9 +14,9 @@ class cFloater :
typedef cEntity super;
public:
- //tolua_end
+ // tolua_end
- CLASS_PROTODEF(cFloater);
+ CLASS_PROTODEF(cFloater)
cFloater(double a_X, double a_Y, double a_Z, Vector3d a_Speed, int a_PlayerID, int a_CountDownTime);
@@ -43,4 +43,4 @@ protected:
// Entity IDs
int m_PlayerID;
int m_AttachedMobID;
-} ; // tolua_export
+} ; // tolua_export
diff --git a/src/Entities/GhastFireballEntity.h b/src/Entities/GhastFireballEntity.h
index 9e4572c78..3ed72d9ef 100644
--- a/src/Entities/GhastFireballEntity.h
+++ b/src/Entities/GhastFireballEntity.h
@@ -21,7 +21,7 @@ public:
// tolua_end
- CLASS_PROTODEF(cGhastFireballEntity);
+ CLASS_PROTODEF(cGhastFireballEntity)
cGhastFireballEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
@@ -35,4 +35,4 @@ protected:
// TODO: Deflecting the fireballs by arrow- or sword- hits
-} ; // tolua_export
+} ; // tolua_export
diff --git a/src/Entities/HangingEntity.cpp b/src/Entities/HangingEntity.cpp
index 41ac86268..8c70c606e 100644
--- a/src/Entities/HangingEntity.cpp
+++ b/src/Entities/HangingEntity.cpp
@@ -10,7 +10,7 @@
cHangingEntity::cHangingEntity(eEntityType a_EntityType, eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z)
- : cEntity(a_EntityType, a_X, a_Y, a_Z, 0.8, 0.8)
+ : cEntity(a_EntityType, a_X, a_Y, a_Z, 0.8, 0.8)
, m_BlockFace(a_BlockFace)
{
SetMaxHealth(1);
@@ -24,18 +24,18 @@ cHangingEntity::cHangingEntity(eEntityType a_EntityType, eBlockFace a_BlockFace,
void cHangingEntity::SpawnOn(cClientHandle & a_ClientHandle)
{
int Dir = 0;
-
+
// The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces
switch (m_BlockFace)
{
- case BLOCK_FACE_ZP: break; // Initialised to zero
+ case BLOCK_FACE_ZP: break; // Initialised to zero
case BLOCK_FACE_ZM: Dir = 2; break;
case BLOCK_FACE_XM: Dir = 1; break;
case BLOCK_FACE_XP: Dir = 3; break;
default: ASSERT(!"Unhandled block face when trying to spawn item frame!"); return;
}
- if ((Dir == 0) || (Dir == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180
+ if ((Dir == 0) || (Dir == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180
{
SetYaw((Dir * 90) - 180);
}
diff --git a/src/Entities/HangingEntity.h b/src/Entities/HangingEntity.h
index 6498e4b5b..3593f9ede 100644
--- a/src/Entities/HangingEntity.h
+++ b/src/Entities/HangingEntity.h
@@ -16,7 +16,7 @@ class cHangingEntity :
public:
- CLASS_PROTODEF(cHangingEntity);
+ CLASS_PROTODEF(cHangingEntity)
cHangingEntity(eEntityType a_EntityType, eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z);
@@ -38,7 +38,7 @@ public:
private:
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
- virtual void Tick(float a_Dt, cChunk & a_Chunk) override {};
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override {}
eBlockFace m_BlockFace;
diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp
index 7bc7bda8d..f0b0c8c65 100644
--- a/src/Entities/ItemFrame.cpp
+++ b/src/Entities/ItemFrame.cpp
@@ -10,7 +10,7 @@
cItemFrame::cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z)
- : cHangingEntity(etItemFrame, a_BlockFace, a_X, a_Y, a_Z)
+ : cHangingEntity(etItemFrame, a_BlockFace, a_X, a_Y, a_Z)
, m_Item(E_BLOCK_AIR)
, m_Rotation(0)
{
@@ -43,7 +43,7 @@ void cItemFrame::OnRightClicked(cPlayer & a_Player)
}
}
- GetWorld()->BroadcastEntityMetadata(*this); // Update clients
+ GetWorld()->BroadcastEntityMetadata(*this); // Update clients
}
@@ -51,17 +51,17 @@ void cItemFrame::OnRightClicked(cPlayer & a_Player)
-void cItemFrame::KilledBy(cEntity * a_Killer)
+void cItemFrame::KilledBy(TakeDamageInfo & a_TDI)
{
if (m_Item.IsEmpty())
{
SetHealth(0);
- super::KilledBy(a_Killer);
+ super::KilledBy(a_TDI);
Destroy();
return;
}
- if ((a_Killer != NULL) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative())
+ if ((a_TDI.Attacker != NULL) && a_TDI.Attacker->IsPlayer() && !((cPlayer *)a_TDI.Attacker)->IsGameModeCreative())
{
cItems Item;
Item.push_back(m_Item);
diff --git a/src/Entities/ItemFrame.h b/src/Entities/ItemFrame.h
index 6577e7d94..a63b78b70 100644
--- a/src/Entities/ItemFrame.h
+++ b/src/Entities/ItemFrame.h
@@ -16,7 +16,7 @@ class cItemFrame :
public:
- CLASS_PROTODEF(cItemFrame);
+ CLASS_PROTODEF(cItemFrame)
cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z);
@@ -24,7 +24,7 @@ public:
const cItem & GetItem(void) { return m_Item; } // tolua_export
/** Set the item in the frame */
- void SetItem(cItem & a_Item) { m_Item = a_Item; }; // tolua_export
+ void SetItem(cItem & a_Item) { m_Item = a_Item; } // tolua_export
/** Returns the rotation from the item in the frame */
Byte GetRotation(void) const { return m_Rotation; } // tolua_export
@@ -35,7 +35,7 @@ public:
private:
virtual void OnRightClicked(cPlayer & a_Player) override;
- virtual void KilledBy(cEntity * a_Killer) override;
+ virtual void KilledBy(TakeDamageInfo & a_TDI) override;
virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override;
cItem m_Item;
diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp
index 7bd440d6d..d4eadc5d5 100644
--- a/src/Entities/Minecart.cpp
+++ b/src/Entities/Minecart.cpp
@@ -103,21 +103,7 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) :
void cMinecart::SpawnOn(cClientHandle & a_ClientHandle)
{
- char SubType = 0;
- switch (m_Payload)
- {
- case mpNone: SubType = 0; break;
- case mpChest: SubType = 1; break;
- case mpFurnace: SubType = 2; break;
- case mpTNT: SubType = 3; break;
- case mpHopper: SubType = 5; break;
- default:
- {
- ASSERT(!"Unknown payload, cannot spawn on client");
- return;
- }
- }
- a_ClientHandle.SendSpawnVehicle(*this, 10, SubType); // 10 = Minecarts, SubType = What type of Minecart
+ a_ClientHandle.SendSpawnVehicle(*this, 10, (char)m_Payload); // 10 = Minecarts
a_ClientHandle.SendEntityMetadata(*this);
}
@@ -127,7 +113,7 @@ void cMinecart::SpawnOn(cClientHandle & a_ClientHandle)
void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
- if (IsDestroyed()) // Mainly to stop detector rails triggering again after minecart is dead
+ if (IsDestroyed()) // Mainly to stop detector rails triggering again after minecart is dead
{
return;
}
@@ -156,8 +142,8 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
if (!IsBlockRail(InsideType))
{
- Chunk->GetBlockTypeMeta(RelPosX, PosY + 1, RelPosZ, InsideType, InsideMeta); // When an descending minecart hits a flat rail, it goes through the ground; check for this
- if (IsBlockRail(InsideType)) AddPosY(1); // Push cart upwards
+ Chunk->GetBlockTypeMeta(RelPosX, PosY + 1, RelPosZ, InsideType, InsideMeta); // When an descending minecart hits a flat rail, it goes through the ground; check for this
+ if (IsBlockRail(InsideType)) AddPosY(1); // Push cart upwards
}
bool WasDetectorRail = false;
@@ -186,12 +172,12 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
default: VERIFY(!"Unhandled rail type despite checking if block was rail!"); break;
}
- AddPosition(GetSpeed() * (a_Dt / 1000)); // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp
+ AddPosition(GetSpeed() * (a_Dt / 1000)); // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp
}
else
{
// Not on rail, default physics
- SetPosY(floor(GetPosY()) + 0.35); // HandlePhysics overrides this if minecart can fall, else, it is to stop ground clipping minecart bottom when off-rail
+ SetPosY(floor(GetPosY()) + 0.35); // HandlePhysics overrides this if minecart can fall, else, it is to stop ground clipping minecart bottom when off-rail
super::HandlePhysics(a_Dt, *Chunk);
}
@@ -223,18 +209,18 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
switch (a_RailMeta)
{
- case E_META_RAIL_ZM_ZP: // NORTHSOUTH
+ case E_META_RAIL_ZM_ZP: // NORTHSOUTH
{
SetYaw(270);
SetPosY(floor(GetPosY()) + 0.55);
- SetSpeedY(0); // Don't move vertically as on ground
- SetSpeedX(0); // Correct diagonal movement from curved rails
+ SetSpeedY(0); // Don't move vertically as on ground
+ SetSpeedX(0); // Correct diagonal movement from curved rails
// Execute both the entity and block collision checks
bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta);
if (EntCol || BlckCol) return;
- if (GetSpeedZ() != 0) // Don't do anything if cart is stationary
+ if (GetSpeedZ() != 0) // Don't do anything if cart is stationary
{
if (GetSpeedZ() > 0)
{
@@ -249,7 +235,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
}
break;
}
- case E_META_RAIL_XM_XP: // EASTWEST
+ case E_META_RAIL_XM_XP: // EASTWEST
{
SetYaw(180);
SetPosY(floor(GetPosY()) + 0.55);
@@ -272,7 +258,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
}
break;
}
- case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH
+ case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH
{
SetYaw(270);
SetSpeedX(0);
@@ -280,21 +266,21 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
if (GetSpeedZ() >= 0)
{
// SpeedZ POSITIVE, going SOUTH
- if (GetSpeedZ() <= MAX_SPEED) // Speed limit
+ if (GetSpeedZ() <= MAX_SPEED) // Speed limit
{
- AddSpeedZ(0.5); // Speed up
- SetSpeedY(-GetSpeedZ()); // Downward movement is negative (0 minus positive numbers is negative)
+ AddSpeedZ(0.5); // Speed up
+ SetSpeedY(-GetSpeedZ()); // Downward movement is negative (0 minus positive numbers is negative)
}
}
else
{
// SpeedZ NEGATIVE, going NORTH
- AddSpeedZ(1); // Slow down
- SetSpeedY(-GetSpeedZ()); // Upward movement is positive (0 minus negative number is positive number)
+ AddSpeedZ(1); // Slow down
+ SetSpeedY(-GetSpeedZ()); // Upward movement is positive (0 minus negative number is positive number)
}
break;
}
- case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH
+ case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH
{
SetYaw(270);
SetSpeedX(0);
@@ -302,21 +288,21 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
if (GetSpeedZ() > 0)
{
// SpeedZ POSITIVE, going SOUTH
- AddSpeedZ(-1); // Slow down
- SetSpeedY(GetSpeedZ()); // Upward movement positive
+ AddSpeedZ(-1); // Slow down
+ SetSpeedY(GetSpeedZ()); // Upward movement positive
}
else
{
- if (GetSpeedZ() >= MAX_SPEED_NEGATIVE) // Speed limit
+ if (GetSpeedZ() >= MAX_SPEED_NEGATIVE) // Speed limit
{
// SpeedZ NEGATIVE, going NORTH
- AddSpeedZ(-0.5); // Speed up
- SetSpeedY(GetSpeedZ()); // Downward movement negative
+ AddSpeedZ(-0.5); // Speed up
+ SetSpeedY(GetSpeedZ()); // Downward movement negative
}
}
break;
}
- case E_META_RAIL_ASCEND_XM: // ASCEND EAST
+ case E_META_RAIL_ASCEND_XM: // ASCEND EAST
{
SetYaw(180);
SetSpeedZ(0);
@@ -336,7 +322,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
}
break;
}
- case E_META_RAIL_ASCEND_XP: // ASCEND WEST
+ case E_META_RAIL_ASCEND_XP: // ASCEND WEST
{
SetYaw(180);
SetSpeedZ(0);
@@ -356,10 +342,10 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
}
break;
}
- case E_META_RAIL_CURVED_ZM_XM: // Ends pointing NORTH and WEST
+ case E_META_RAIL_CURVED_ZM_XM: // Ends pointing NORTH and WEST
{
- SetYaw(315); // Set correct rotation server side
- SetPosY(floor(GetPosY()) + 0.55); // Levitate dat cart
+ SetYaw(315); // Set correct rotation server side
+ SetPosY(floor(GetPosY()) + 0.55); // Levitate dat cart
SetSpeedY(0);
TestBlockCollision(a_RailMeta);
@@ -369,7 +355,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
break;
}
- case E_META_RAIL_CURVED_ZM_XP: // Curved NORTH EAST
+ case E_META_RAIL_CURVED_ZM_XP: // Curved NORTH EAST
{
SetYaw(225);
SetPosY(floor(GetPosY()) + 0.55);
@@ -380,7 +366,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
break;
}
- case E_META_RAIL_CURVED_ZP_XM: // Curved SOUTH WEST
+ case E_META_RAIL_CURVED_ZP_XM: // Curved SOUTH WEST
{
SetYaw(135);
SetPosY(floor(GetPosY()) + 0.55);
@@ -391,7 +377,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
break;
}
- case E_META_RAIL_CURVED_ZP_XP: // Curved SOUTH EAST
+ case E_META_RAIL_CURVED_ZP_XP: // Curved SOUTH EAST
{
SetYaw(45);
SetPosY(floor(GetPosY()) + 0.55);
@@ -404,7 +390,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
}
default:
{
- ASSERT(!"Unhandled rail meta!"); // Dun dun DUN!
+ ASSERT(!"Unhandled rail meta!"); // Dun dun DUN!
break;
}
}
@@ -428,7 +414,7 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta)
switch (a_RailMeta & 0x07)
{
- case E_META_RAIL_ZM_ZP: // NORTHSOUTH
+ case E_META_RAIL_ZM_ZP: // NORTHSOUTH
{
SetYaw(270);
SetPosY(floor(GetPosY()) + 0.55);
@@ -451,7 +437,7 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta)
}
break;
}
- case E_META_RAIL_XM_XP: // EASTWEST
+ case E_META_RAIL_XM_XP: // EASTWEST
{
SetYaw(180);
SetPosY(floor(GetPosY()) + 0.55);
@@ -474,7 +460,7 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta)
}
break;
}
- case E_META_RAIL_ASCEND_XM: // ASCEND EAST
+ case E_META_RAIL_ASCEND_XM: // ASCEND EAST
{
SetYaw(180);
SetSpeedZ(0);
@@ -493,8 +479,8 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta)
SetSpeedY(-GetSpeedX());
}
break;
- }
- case E_META_RAIL_ASCEND_XP: // ASCEND WEST
+ }
+ case E_META_RAIL_ASCEND_XP: // ASCEND WEST
{
SetYaw(180);
SetSpeedZ(0);
@@ -513,8 +499,8 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta)
}
}
break;
- }
- case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH
+ }
+ case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH
{
SetYaw(270);
SetSpeedX(0);
@@ -534,7 +520,7 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta)
}
break;
}
- case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH
+ case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH
{
SetYaw(270);
SetSpeedX(0);
@@ -787,7 +773,7 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
}
}
break;
- }
+ }
case E_META_RAIL_CURVED_ZM_XM:
case E_META_RAIL_CURVED_ZM_XP:
case E_META_RAIL_CURVED_ZP_XM:
@@ -883,7 +869,7 @@ bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta)
}
}
return true;
- }
+ }
case E_META_RAIL_CURVED_ZM_XM:
case E_META_RAIL_CURVED_ZM_XP:
case E_META_RAIL_CURVED_ZP_XM:
@@ -907,7 +893,7 @@ bool cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
if ((TDI.Attacker != NULL) && TDI.Attacker->IsPlayer() && ((cPlayer *)TDI.Attacker)->IsGameModeCreative())
{
Destroy();
- TDI.FinalDamage = GetMaxHealth(); // Instant hit for creative
+ TDI.FinalDamage = GetMaxHealth(); // Instant hit for creative
SetInvulnerableTicks(0);
return super::DoTakeDamage(TDI); // No drops for creative
}
@@ -980,7 +966,7 @@ void cMinecart::Destroyed()
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cRideableMinecart:
cRideableMinecart::cRideableMinecart(double a_X, double a_Y, double a_Z, const cItem & a_Content, int a_Height) :
@@ -1023,7 +1009,7 @@ void cRideableMinecart::OnRightClicked(cPlayer & a_Player)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cMinecartWithChest:
cMinecartWithChest::cMinecartWithChest(double a_X, double a_Y, double a_Z) :
@@ -1056,7 +1042,7 @@ void cMinecartWithChest::OnRightClicked(cPlayer & a_Player)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cMinecartWithFurnace:
cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) :
@@ -1078,12 +1064,12 @@ void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player)
{
a_Player.GetInventory().RemoveOneEquippedItem();
}
- if (!m_IsFueled) // We don't want to change the direction by right clicking it.
+ if (!m_IsFueled) // We don't want to change the direction by right clicking it.
{
AddSpeed(a_Player.GetLookVector().x, 0, a_Player.GetLookVector().z);
}
m_IsFueled = true;
- m_FueledTimeLeft = m_FueledTimeLeft + 600; // The minecart will be active 600 more ticks.
+ m_FueledTimeLeft = m_FueledTimeLeft + 600; // The minecart will be active 600 more ticks.
m_World->BroadcastEntityMetadata(*this);
}
}
@@ -1118,7 +1104,7 @@ void cMinecartWithFurnace::Tick(float a_Dt, cChunk & a_Chunk)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cMinecartWithTNT:
cMinecartWithTNT::cMinecartWithTNT(double a_X, double a_Y, double a_Z) :
@@ -1132,7 +1118,7 @@ cMinecartWithTNT::cMinecartWithTNT(double a_X, double a_Y, double a_Z) :
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cMinecartWithHopper:
cMinecartWithHopper::cMinecartWithHopper(double a_X, double a_Y, double a_Z) :
diff --git a/src/Entities/Minecart.h b/src/Entities/Minecart.h
index 1e60f091c..410d3c77d 100644
--- a/src/Entities/Minecart.h
+++ b/src/Entities/Minecart.h
@@ -21,15 +21,16 @@ class cMinecart :
typedef cEntity super;
public:
- CLASS_PROTODEF(cMinecart);
+ CLASS_PROTODEF(cMinecart)
+ /** Minecart payload, values correspond to packet subtype */
enum ePayload
{
- mpNone, // Empty minecart, ridable by player or mobs
- mpChest, // Minecart-with-chest, can store a grid of 3*8 items
- mpFurnace, // Minecart-with-furnace, can be powered
- mpTNT, // Minecart-with-TNT, can be blown up with activator rail
- mpHopper, // Minecart-with-hopper, can be hopper
+ mpNone = 0, // Empty minecart, ridable by player or mobs
+ mpChest = 1, // Minecart-with-chest, can store a grid of 3*8 items
+ mpFurnace = 2, // Minecart-with-furnace, can be powered
+ mpTNT = 3, // Minecart-with-TNT, can be blown up with activator rail
+ mpHopper = 5, // Minecart-with-hopper, can be hopper
// TODO: Spawner minecarts, (and possibly any block in a minecart with NBT editing)
} ;
@@ -88,7 +89,7 @@ class cRideableMinecart :
typedef cMinecart super;
public:
- CLASS_PROTODEF(cRideableMinecart);
+ CLASS_PROTODEF(cRideableMinecart)
cRideableMinecart(double a_X, double a_Y, double a_Z, const cItem & a_Content, int a_Height);
@@ -99,7 +100,7 @@ public:
protected:
cItem m_Content;
- int m_Height;
+ int m_Height;
} ;
@@ -112,7 +113,7 @@ class cMinecartWithChest :
typedef cMinecart super;
public:
- CLASS_PROTODEF(cMinecartWithChest);
+ CLASS_PROTODEF(cMinecartWithChest)
/// Number of item slots in the chest
static const int NumSlots = 9 * 3;
@@ -143,7 +144,7 @@ class cMinecartWithFurnace :
typedef cMinecart super;
public:
- CLASS_PROTODEF(cMinecartWithFurnace);
+ CLASS_PROTODEF(cMinecartWithFurnace)
cMinecartWithFurnace(double a_X, double a_Y, double a_Z);
@@ -175,7 +176,7 @@ class cMinecartWithTNT :
typedef cMinecart super;
public:
- CLASS_PROTODEF(cMinecartWithTNT);
+ CLASS_PROTODEF(cMinecartWithTNT)
cMinecartWithTNT(double a_X, double a_Y, double a_Z);
} ;
@@ -190,7 +191,7 @@ class cMinecartWithHopper :
typedef cMinecart super;
public:
- CLASS_PROTODEF(cMinecartWithHopper);
+ CLASS_PROTODEF(cMinecartWithHopper)
cMinecartWithHopper(double a_X, double a_Y, double a_Z);
} ;
diff --git a/src/Entities/Painting.h b/src/Entities/Painting.h
index c1024bd1b..9877c95c5 100644
--- a/src/Entities/Painting.h
+++ b/src/Entities/Painting.h
@@ -15,20 +15,20 @@ class cPainting :
typedef cEntity super;
public:
- CLASS_PROTODEF(cPainting);
+ CLASS_PROTODEF(cPainting)
cPainting(const AString & a_Name, int a_Direction, double a_X, double a_Y, double a_Z);
- const AString & GetName(void) const { return m_Name; } // tolua_export
- int GetDirection(void) const { return m_Direction; } // tolua_export
+ const AString & GetName(void) const { return m_Name; } // tolua_export
+ int GetDirection(void) const { return m_Direction; } // tolua_export
private:
virtual void SpawnOn(cClientHandle & a_Client) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override;
- virtual void KilledBy(cEntity * a_Killer) override
+ virtual void KilledBy(TakeDamageInfo & a_TDI) override
{
- super::KilledBy(a_Killer);
+ super::KilledBy(a_TDI);
Destroy();
}
diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp
index fffefd538..fe6c24a7a 100644
--- a/src/Entities/Pawn.cpp
+++ b/src/Entities/Pawn.cpp
@@ -2,14 +2,16 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Pawn.h"
+#include "../World.h"
+#include "../Bindings/PluginManager.h"
-cPawn::cPawn(eEntityType a_EntityType, double a_Width, double a_Height)
- : cEntity(a_EntityType, 0, 0, 0, a_Width, a_Height)
- , m_bBurnable(true)
+cPawn::cPawn(eEntityType a_EntityType, double a_Width, double a_Height):
+ super(a_EntityType, 0, 0, 0, a_Width, a_Height),
+ m_EntityEffects(tEffectMap())
{
}
@@ -17,3 +19,95 @@ cPawn::cPawn(eEntityType a_EntityType, double a_Width, double a_Height)
+void cPawn::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ // Iterate through this entity's applied effects
+ for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();)
+ {
+ // Copies values to prevent pesky wrong accesses and erasures
+ cEntityEffect::eType EffectType = iter->first;
+ cEntityEffect * Effect = iter->second;
+
+ Effect->OnTick(*this);
+
+ // Iterates (must be called before any possible erasure)
+ ++iter;
+
+ // Remove effect if duration has elapsed
+ if (Effect->GetDuration() - Effect->GetTicks() <= 0)
+ {
+ RemoveEntityEffect(EffectType);
+ }
+
+ // TODO: Check for discrepancies between client and server effect values
+ }
+
+ super::Tick(a_Dt, a_Chunk);
+}
+
+
+
+
+
+void cPawn::KilledBy(TakeDamageInfo & a_TDI)
+{
+ ClearEntityEffects();
+ super::KilledBy(a_TDI);
+}
+
+
+
+
+
+void cPawn::AddEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier)
+{
+ // Check if the plugins allow the addition:
+ if (cPluginManager::Get()->CallHookEntityAddEffect(*this, a_EffectType, a_Duration, a_Intensity, a_DistanceModifier))
+ {
+ // A plugin disallows the addition, bail out.
+ return;
+ }
+
+ // No need to add empty effects:
+ if (a_EffectType == cEntityEffect::effNoEffect)
+ {
+ return;
+ }
+ a_Duration = (int)(a_Duration * a_DistanceModifier);
+
+ m_EntityEffects[a_EffectType] = cEntityEffect::CreateEntityEffect(a_EffectType, a_Duration, a_Intensity, a_DistanceModifier);
+ m_World->BroadcastEntityEffect(*this, a_EffectType, a_Intensity, a_Duration);
+ m_EntityEffects[a_EffectType]->OnActivate(*this);
+}
+
+
+
+
+
+void cPawn::RemoveEntityEffect(cEntityEffect::eType a_EffectType)
+{
+ m_World->BroadcastRemoveEntityEffect(*this, a_EffectType);
+ m_EntityEffects[a_EffectType]->OnDeactivate(*this);
+ delete m_EntityEffects[a_EffectType];
+ m_EntityEffects.erase(a_EffectType);
+}
+
+
+
+
+
+void cPawn::ClearEntityEffects()
+{
+ // Iterate through this entity's applied effects
+ for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();)
+ {
+ // Copy values to prevent pesky wrong erasures
+ cEntityEffect::eType EffectType = iter->first;
+
+ // Iterates (must be called before any possible erasure)
+ ++iter;
+
+ // Remove effect
+ RemoveEntityEffect(EffectType);
+ }
+}
diff --git a/src/Entities/Pawn.h b/src/Entities/Pawn.h
index e76337d86..d50bcd8af 100644
--- a/src/Entities/Pawn.h
+++ b/src/Entities/Pawn.h
@@ -2,6 +2,7 @@
#pragma once
#include "Entity.h"
+#include "EntityEffect.h"
@@ -15,12 +16,37 @@ class cPawn :
typedef cEntity super;
public:
- CLASS_PROTODEF(cPawn);
+ CLASS_PROTODEF(cPawn)
cPawn(eEntityType a_EntityType, double a_Width, double a_Height);
+
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void KilledBy(TakeDamageInfo & a_TDI) override;
+
+ // tolua_begin
+
+ /** Applies an entity effect
+ Checks with plugins if they allow the addition.
+ @param a_EffectType The entity effect to apply
+ @param a_EffectDurationTicks The duration of the effect
+ @param a_EffectIntensity The level of the effect (0 = Potion I, 1 = Potion II, etc)
+ @param a_DistanceModifier The scalar multiplied to the potion duration, only applies to splash potions)
+ */
+ void AddEntityEffect(cEntityEffect::eType a_EffectType, int a_EffectDurationTicks, short a_EffectIntensity, double a_DistanceModifier = 1);
+
+ /** Removes a currently applied entity effect
+ @param a_EffectType The entity effect to remove
+ */
+ void RemoveEntityEffect(cEntityEffect::eType a_EffectType);
+
+ /** Removes all currently applied entity effects (used when drinking milk) */
+ void ClearEntityEffects(void);
+
+ // tolua_end
protected:
- bool m_bBurnable;
+ typedef std::map<cEntityEffect::eType, cEntityEffect *> tEffectMap;
+ tEffectMap m_EntityEffects;
} ; // tolua_export
diff --git a/src/Entities/Pickup.cpp b/src/Entities/Pickup.cpp
index 24fa591da..aab534f41 100644
--- a/src/Entities/Pickup.cpp
+++ b/src/Entities/Pickup.cpp
@@ -85,7 +85,7 @@ protected:
cPickup::cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_Item, bool IsPlayerCreated, float a_SpeedX /* = 0.f */, float a_SpeedY /* = 0.f */, float a_SpeedZ /* = 0.f */)
- : cEntity(etPickup, a_PosX, a_PosY, a_PosZ, 0.2, 0.2)
+ : cEntity(etPickup, a_PosX, a_PosY, a_PosZ, 0.2, 0.2)
, m_Timer(0.f)
, m_Item(a_Item)
, m_bCollected(false)
@@ -113,7 +113,7 @@ void cPickup::SpawnOn(cClientHandle & a_Client)
void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
- BroadcastMovementUpdate(); //Notify clients of position
+ BroadcastMovementUpdate(); // Notify clients of position
m_Timer += a_Dt;
@@ -143,17 +143,17 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
m_bCollected = true;
m_Timer = 0; // We have to reset the timer.
m_Timer += a_Dt; // In case we have to destroy the pickup in the same tick.
- if (m_Timer > 500.f)
+ if (m_Timer > 500.f)
{
Destroy(true);
return;
}
}
- if (!IsDestroyed() && (m_Item.m_ItemCount < m_Item.GetMaxStackSize())) // Don't combine into an already full pickup
+ if (!IsDestroyed() && (m_Item.m_ItemCount < m_Item.GetMaxStackSize())) // Don't combine into an already full pickup
{
cPickupCombiningCallback PickupCombiningCallback(GetPosition(), this);
- m_World->ForEachEntity(PickupCombiningCallback); // Not ForEachEntityInChunk, otherwise pickups don't combine across chunk boundaries
+ m_World->ForEachEntity(PickupCombiningCallback); // Not ForEachEntityInChunk, otherwise pickups don't combine across chunk boundaries
if (PickupCombiningCallback.FoundMatchingPickup())
{
m_World->BroadcastEntityMetadata(*this);
@@ -176,7 +176,7 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
return;
}
- if (GetPosY() < VOID_BOUNDARY) // Out of this world and no more visible!
+ if (GetPosY() < VOID_BOUNDARY) // Out of this world and no more visible!
{
Destroy(true);
return;
@@ -194,14 +194,14 @@ bool cPickup::CollectedBy(cPlayer * a_Dest)
if (m_bCollected)
{
// LOG("Pickup %d cannot be collected by \"%s\", because it has already been collected.", m_UniqueID, a_Dest->GetName().c_str());
- return false; // It's already collected!
+ return false; // It's already collected!
}
// Two seconds if player created the pickup (vomiting), half a second if anything else
if (m_Timer < (m_bIsPlayerCreated ? 2000.f : 500.f))
{
// LOG("Pickup %d cannot be collected by \"%s\", because it is not old enough.", m_UniqueID, a_Dest->GetName().c_str());
- return false; // Not old enough
+ return false; // Not old enough
}
if (cRoot::Get()->GetPluginManager()->CallHookCollectingPickup(a_Dest, *this))
@@ -226,7 +226,7 @@ bool cPickup::CollectedBy(cPlayer * a_Dest)
m_Item.m_ItemCount -= NumAdded;
m_World->BroadcastCollectEntity(*this, *a_Dest);
// Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
- m_World->BroadcastSoundEffect("random.pop",(int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
+ m_World->BroadcastSoundEffect("random.pop", GetPosX(), GetPosY(), GetPosZ(), 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
if (m_Item.m_ItemCount <= 0)
{
// All of the pickup has been collected, schedule the pickup for destroying
diff --git a/src/Entities/Pickup.h b/src/Entities/Pickup.h
index 2dcbecaaf..4d5250819 100644
--- a/src/Entities/Pickup.h
+++ b/src/Entities/Pickup.h
@@ -23,16 +23,16 @@ class cPickup :
public:
// tolua_end
- CLASS_PROTODEF(cPickup);
+ CLASS_PROTODEF(cPickup)
cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_Item, bool IsPlayerCreated, float a_SpeedX = 0.f, float a_SpeedY = 0.f, float a_SpeedZ = 0.f);
- cItem & GetItem(void) {return m_Item; } // tolua_export
+ cItem & GetItem(void) {return m_Item; } // tolua_export
const cItem & GetItem(void) const {return m_Item; }
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
- bool CollectedBy(cPlayer * a_Dest); // tolua_export
+ bool CollectedBy(cPlayer * a_Dest); // tolua_export
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
@@ -46,7 +46,7 @@ public:
bool IsCollected(void) const { return m_bCollected; } // tolua_export
/** Returns true if created by player (i.e. vomiting), used for determining picking-up delay time */
- bool IsPlayerCreated(void) const { return m_bIsPlayerCreated; } // tolua_export
+ bool IsPlayerCreated(void) const { return m_bIsPlayerCreated; } // tolua_export
private:
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index dbb8cd26c..32290885d 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -2,6 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Player.h"
+#include "../ChatColor.h"
#include "../Server.h"
#include "../UI/Window.h"
#include "../UI/WindowOwner.h"
@@ -32,54 +33,58 @@
-
-
-cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
- : super(etPlayer, 0.6, 1.8)
- , m_bVisible(true)
- , m_FoodLevel(MAX_FOOD_LEVEL)
- , m_FoodSaturationLevel(5.0)
- , m_FoodTickTimer(0)
- , m_FoodExhaustionLevel(0.0)
- , m_FoodPoisonedTicksRemaining(0)
- , m_LastJumpHeight(0)
- , m_LastGroundHeight(0)
- , m_bTouchGround(false)
- , m_Stance(0.0)
- , m_Inventory(*this)
- , m_EnderChestContents(9, 3)
- , m_CurrentWindow(NULL)
- , m_InventoryWindow(NULL)
- , m_Color('-')
- , m_GameMode(eGameMode_NotSet)
- , m_IP("")
- , m_ClientHandle(a_Client)
- , m_NormalMaxSpeed(1.0)
- , m_SprintingMaxSpeed(1.3)
- , m_FlyingMaxSpeed(1.0)
- , m_IsCrouched(false)
- , m_IsSprinting(false)
- , m_IsFlying(false)
- , m_IsSwimming(false)
- , m_IsSubmerged(false)
- , m_IsFishing(false)
- , m_CanFly(false)
- , m_EatingFinishTick(-1)
- , m_LifetimeTotalXp(0)
- , m_CurrentXp(0)
- , m_bDirtyExperience(false)
- , m_IsChargingBow(false)
- , m_BowCharge(0)
- , m_FloaterID(-1)
- , m_Team(NULL)
- , m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL)
- , m_bIsTeleporting(false)
-{
- LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
- a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
- this, GetUniqueID()
- );
-
+const int cPlayer::MAX_HEALTH = 20;
+
+const int cPlayer::MAX_FOOD_LEVEL = 20;
+
+/** Number of ticks it takes to eat an item */
+const int cPlayer::EATING_TICKS = 30;
+
+
+
+
+
+cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) :
+ super(etPlayer, 0.6, 1.8),
+ m_bVisible(true),
+ m_FoodLevel(MAX_FOOD_LEVEL),
+ m_FoodSaturationLevel(5.0),
+ m_FoodTickTimer(0),
+ m_FoodExhaustionLevel(0.0),
+ m_LastJumpHeight(0),
+ m_LastGroundHeight(0),
+ m_bTouchGround(false),
+ m_Stance(0.0),
+ m_Inventory(*this),
+ m_EnderChestContents(9, 3),
+ m_CurrentWindow(NULL),
+ m_InventoryWindow(NULL),
+ m_Color('-'),
+ m_GameMode(eGameMode_NotSet),
+ m_IP(""),
+ m_ClientHandle(a_Client),
+ m_NormalMaxSpeed(1.0),
+ m_SprintingMaxSpeed(1.3),
+ m_FlyingMaxSpeed(1.0),
+ m_IsCrouched(false),
+ m_IsSprinting(false),
+ m_IsFlying(false),
+ m_IsSwimming(false),
+ m_IsSubmerged(false),
+ m_IsFishing(false),
+ m_CanFly(false),
+ m_EatingFinishTick(-1),
+ m_LifetimeTotalXp(0),
+ m_CurrentXp(0),
+ m_bDirtyExperience(false),
+ m_IsChargingBow(false),
+ m_BowCharge(0),
+ m_FloaterID(-1),
+ m_Team(NULL),
+ m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL),
+ m_bIsTeleporting(false),
+ m_UUID((a_Client != NULL) ? a_Client->GetUUID() : "")
+{
m_InventoryWindow = new cInventoryWindow(*this);
m_CurrentWindow = m_InventoryWindow;
m_InventoryWindow->OpenedByPlayer(*this);
@@ -92,13 +97,14 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
m_PlayerName = a_PlayerName;
- if (!LoadFromDisk())
+ cWorld * World = NULL;
+ if (!LoadFromDisk(World))
{
m_Inventory.Clear();
- cWorld * DefaultWorld = cRoot::Get()->GetDefaultWorld();
- SetPosX(DefaultWorld->GetSpawnX());
- SetPosY(DefaultWorld->GetSpawnY());
- SetPosZ(DefaultWorld->GetSpawnZ());
+ SetPosX(World->GetSpawnX());
+ SetPosY(World->GetSpawnY());
+ SetPosZ(World->GetSpawnZ());
+ SetBedPos(Vector3i((int)World->GetSpawnX(), (int)World->GetSpawnY(), (int)World->GetSpawnZ()));
LOGD("Player \"%s\" is connecting for the first time, spawning at default world spawn {%.2f, %.2f, %.2f}",
a_PlayerName.c_str(), GetPosX(), GetPosY(), GetPosZ()
@@ -111,11 +117,6 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
if (m_GameMode == gmNotSet)
{
- cWorld * World = cRoot::Get()->GetWorld(GetLoadedWorldName());
- if (World == NULL)
- {
- World = cRoot::Get()->GetDefaultWorld();
- }
if (World->IsGameModeCreative())
{
m_CanFly = true;
@@ -134,7 +135,7 @@ cPlayer::~cPlayer(void)
if (!cRoot::Get()->GetPluginManager()->CallHookPlayerDestroyed(*this))
{
cRoot::Get()->BroadcastChatLeave(Printf("%s has left the game", GetName().c_str()));
- LOGINFO("Player %s has left the game.", GetName().c_str());
+ LOGINFO("Player %s has left the game", GetName().c_str());
}
LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), this, GetUniqueID());
@@ -144,8 +145,6 @@ cPlayer::~cPlayer(void)
SaveToDisk();
- m_World->RemovePlayer( this );
-
m_ClientHandle = NULL;
delete m_InventoryWindow;
@@ -161,8 +160,6 @@ cPlayer::~cPlayer(void)
void cPlayer::Destroyed()
{
CloseWindow(false);
-
- m_ClientHandle = NULL;
}
@@ -177,11 +174,11 @@ void cPlayer::SpawnOn(cClientHandle & a_Client)
}
a_Client.SendPlayerSpawn(*this);
a_Client.SendEntityHeadLook(*this);
- a_Client.SendEntityEquipment(*this, 0, m_Inventory.GetEquippedItem() );
- a_Client.SendEntityEquipment(*this, 1, m_Inventory.GetEquippedBoots() );
- a_Client.SendEntityEquipment(*this, 2, m_Inventory.GetEquippedLeggings() );
- a_Client.SendEntityEquipment(*this, 3, m_Inventory.GetEquippedChestplate() );
- a_Client.SendEntityEquipment(*this, 4, m_Inventory.GetEquippedHelmet() );
+ a_Client.SendEntityEquipment(*this, 0, m_Inventory.GetEquippedItem());
+ a_Client.SendEntityEquipment(*this, 1, m_Inventory.GetEquippedBoots());
+ a_Client.SendEntityEquipment(*this, 2, m_Inventory.GetEquippedLeggings());
+ a_Client.SendEntityEquipment(*this, 3, m_Inventory.GetEquippedChestplate());
+ a_Client.SendEntityEquipment(*this, 4, m_Inventory.GetEquippedHelmet());
}
@@ -228,16 +225,24 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
SendExperience();
}
- if (!GetPosition().EqualsEps(m_LastPos, 0.01)) // Non negligible change in position from last tick?
+ bool CanMove = true;
+ if (!GetPosition().EqualsEps(m_LastPos, 0.01)) // Non negligible change in position from last tick?
{
// Apply food exhaustion from movement:
ApplyFoodExhaustionFromMovement();
- cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this);
+ if (cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this, m_LastPos, GetPosition()))
+ {
+ CanMove = false;
+ TeleportToCoords(m_LastPos.x, m_LastPos.y, m_LastPos.z);
+ }
m_ClientHandle->StreamChunks();
}
- BroadcastMovementUpdate(m_ClientHandle);
+ if (CanMove)
+ {
+ BroadcastMovementUpdate(m_ClientHandle);
+ }
if (m_Health > 0) // make sure player is alive
{
@@ -289,20 +294,20 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
short cPlayer::CalcLevelFromXp(short a_XpTotal)
{
- //level 0 to 15
- if(a_XpTotal <= XP_TO_LEVEL15)
+ // level 0 to 15
+ if (a_XpTotal <= XP_TO_LEVEL15)
{
return a_XpTotal / XP_PER_LEVEL_TO15;
}
- //level 30+
- if(a_XpTotal > XP_TO_LEVEL30)
+ // level 30+
+ if (a_XpTotal > XP_TO_LEVEL30)
{
return (short) (151.5 + sqrt( 22952.25 - (14 * (2220 - a_XpTotal)))) / 7;
}
- //level 16 to 30
- return (short) ( 29.5 + sqrt( 870.25 - (6 * ( 360 - a_XpTotal )))) / 3;
+ // level 16 to 30
+ return (short) ( 29.5 + sqrt( 870.25 - (6 * ( 360 - a_XpTotal)))) / 3;
}
@@ -311,20 +316,20 @@ short cPlayer::CalcLevelFromXp(short a_XpTotal)
short cPlayer::XpForLevel(short a_Level)
{
- //level 0 to 15
- if(a_Level <= 15)
+ // level 0 to 15
+ if (a_Level <= 15)
{
return a_Level * XP_PER_LEVEL_TO15;
}
- //level 30+
- if(a_Level >= 31)
+ // level 30+
+ if (a_Level >= 31)
{
- return (short) ( (3.5 * a_Level * a_Level) - (151.5 * a_Level) + 2220 );
+ return (short) ( (3.5 * a_Level * a_Level) - (151.5 * a_Level) + 2220);
}
- //level 16 to 30
- return (short) ( (1.5 * a_Level * a_Level) - (29.5 * a_Level) + 360 );
+ // level 16 to 30
+ return (short) ( (1.5 * a_Level * a_Level) - (29.5 * a_Level) + 360);
}
@@ -345,7 +350,7 @@ float cPlayer::GetXpPercentage()
short int currentLevel = CalcLevelFromXp(m_CurrentXp);
short int currentLevel_XpBase = XpForLevel(currentLevel);
- return (float)(m_CurrentXp - currentLevel_XpBase) /
+ return (float)(m_CurrentXp - currentLevel_XpBase) /
(float)(XpForLevel(1+currentLevel) - currentLevel_XpBase);
}
@@ -355,10 +360,10 @@ float cPlayer::GetXpPercentage()
bool cPlayer::SetCurrentExperience(short int a_CurrentXp)
{
- if(!(a_CurrentXp >= 0) || (a_CurrentXp > (SHRT_MAX - m_LifetimeTotalXp)))
+ if (!(a_CurrentXp >= 0) || (a_CurrentXp > (SHRT_MAX - m_LifetimeTotalXp)))
{
LOGWARNING("Tried to update experiece with an invalid Xp value: %d", a_CurrentXp);
- return false; //oops, they gave us a dodgey number
+ return false; // oops, they gave us a dodgey number
}
m_CurrentXp = a_CurrentXp;
@@ -380,16 +385,13 @@ short cPlayer::DeltaExperience(short a_Xp_delta)
// Value was bad, abort and report
LOGWARNING("Attempt was made to increment Xp by %d, which overflowed the short datatype. Ignoring.",
a_Xp_delta);
- return -1; // Should we instead just return the current Xp?
+ return -1; // Should we instead just return the current Xp?
}
m_CurrentXp += a_Xp_delta;
// Make sure they didn't subtract too much
- if (m_CurrentXp < 0)
- {
- m_CurrentXp = 0;
- }
+ m_CurrentXp = std::max<short int>(m_CurrentXp, 0);
// Update total for score calculation
if (a_Xp_delta > 0)
@@ -397,7 +399,7 @@ short cPlayer::DeltaExperience(short a_Xp_delta)
m_LifetimeTotalXp += a_Xp_delta;
}
- LOGD("Player \"%s\" gained/lost %d experience, total is now: %d",
+ LOGD("Player \"%s\" gained/lost %d experience, total is now: %d",
GetName().c_str(), a_Xp_delta, m_CurrentXp);
// Set experience to be updated
@@ -482,7 +484,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
{
float Dist = (float)(m_LastGroundHeight - floor(GetPosY()));
- if (Dist >= 2.0) // At least two blocks - TODO: Use m_LastJumpHeight instead of m_LastGroundHeight above
+ if (Dist >= 2.0) // At least two blocks - TODO: Use m_LastJumpHeight instead of m_LastGroundHeight above
{
// Increment statistic
m_Stats.AddValue(statDistFallen, (StatValue)floor(Dist * 100 + 0.5));
@@ -502,7 +504,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
// Fall particles
GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, (int)GetPosY() - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */);
- }
+ }
m_LastGroundHeight = (float)GetPosY();
}
@@ -524,7 +526,7 @@ void cPlayer::Heal(int a_Health)
void cPlayer::SetFoodLevel(int a_FoodLevel)
{
- int FoodLevel = std::max(0, std::min(a_FoodLevel, (int)MAX_FOOD_LEVEL));
+ int FoodLevel = Clamp(a_FoodLevel, 0, MAX_FOOD_LEVEL);
if (cRoot::Get()->GetPluginManager()->CallHookPlayerFoodLevelChange(*this, FoodLevel))
{
@@ -542,7 +544,7 @@ void cPlayer::SetFoodLevel(int a_FoodLevel)
void cPlayer::SetFoodSaturationLevel(double a_FoodSaturationLevel)
{
- m_FoodSaturationLevel = std::max(0.0, std::min(a_FoodSaturationLevel, (double)m_FoodLevel));
+ m_FoodSaturationLevel = Clamp(a_FoodSaturationLevel, 0.0, (double) m_FoodLevel);
}
@@ -560,16 +562,7 @@ void cPlayer::SetFoodTickTimer(int a_FoodTickTimer)
void cPlayer::SetFoodExhaustionLevel(double a_FoodExhaustionLevel)
{
- m_FoodExhaustionLevel = std::max(0.0, std::min(a_FoodExhaustionLevel, 4.0));
-}
-
-
-
-
-
-void cPlayer::SetFoodPoisonedTicksRemaining(int a_FoodPoisonedTicksRemaining)
-{
- m_FoodPoisonedTicksRemaining = a_FoodPoisonedTicksRemaining;
+ m_FoodExhaustionLevel = Clamp(a_FoodExhaustionLevel, 0.0, 40.0);
}
@@ -578,7 +571,7 @@ void cPlayer::SetFoodPoisonedTicksRemaining(int a_FoodPoisonedTicksRemaining)
bool cPlayer::Feed(int a_Food, double a_Saturation)
{
- if (m_FoodLevel >= MAX_FOOD_LEVEL)
+ if (IsSatiated())
{
return false;
}
@@ -592,18 +585,11 @@ bool cPlayer::Feed(int a_Food, double a_Saturation)
-void cPlayer::FoodPoison(int a_NumTicks)
+void cPlayer::AddFoodExhaustion(double a_Exhaustion)
{
- bool HasBeenFoodPoisoned = (m_FoodPoisonedTicksRemaining > 0);
- m_FoodPoisonedTicksRemaining = std::max(m_FoodPoisonedTicksRemaining, a_NumTicks);
- if (!HasBeenFoodPoisoned)
- {
- m_World->BroadcastRemoveEntityEffect(*this, E_EFFECT_HUNGER);
- SendHealth();
- }
- else
+ if (!IsGameModeCreative())
{
- m_World->BroadcastEntityEffect(*this, E_EFFECT_HUNGER, 0, 400); // Give the player the "Hunger" effect for 20 seconds.
+ m_FoodExhaustionLevel = std::min(m_FoodExhaustionLevel + a_Exhaustion, 40.0);
}
}
@@ -632,7 +618,6 @@ void cPlayer::FinishEating(void)
// Send the packets:
m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted);
- m_World->BroadcastEntityAnimation(*this, 0);
m_World->BroadcastEntityMetadata(*this);
// consume the item:
@@ -647,10 +632,11 @@ void cPlayer::FinishEating(void)
GetInventory().RemoveOneEquippedItem();
- //if the food is mushroom soup, return a bowl to the inventory
- if( Item.m_ItemType == E_ITEM_MUSHROOM_SOUP ) {
- cItem emptyBowl(E_ITEM_BOWL, 1, 0, "");
- GetInventory().AddItem(emptyBowl, true, true);
+ // if the food is mushroom soup, return a bowl to the inventory
+ if (Item.m_ItemType == E_ITEM_MUSHROOM_SOUP)
+ {
+ cItem EmptyBowl(E_ITEM_BOWL);
+ GetInventory().AddItem(EmptyBowl, true, true);
}
}
@@ -661,7 +647,6 @@ void cPlayer::FinishEating(void)
void cPlayer::AbortEating(void)
{
m_EatingFinishTick = -1;
- m_World->BroadcastEntityAnimation(*this, 0);
m_World->BroadcastEntityMetadata(*this);
}
@@ -730,16 +715,13 @@ double cPlayer::GetMaxSpeed(void) const
{
return m_FlyingMaxSpeed;
}
+ else if (m_IsSprinting)
+ {
+ return m_SprintingMaxSpeed;
+ }
else
{
- if (m_IsSprinting)
- {
- return m_SprintingMaxSpeed;
- }
- else
- {
- return m_NormalMaxSpeed;
- }
+ return m_NormalMaxSpeed;
}
}
@@ -889,16 +871,16 @@ bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
-void cPlayer::KilledBy(cEntity * a_Killer)
+void cPlayer::KilledBy(TakeDamageInfo & a_TDI)
{
- super::KilledBy(a_Killer);
+ super::KilledBy(a_TDI);
if (m_Health > 0)
{
- return; // not dead yet =]
+ return; // not dead yet =]
}
- m_bVisible = false; // So new clients don't see the player
+ m_bVisible = false; // So new clients don't see the player
// Puke out all the items
cItems Pickups;
@@ -910,25 +892,51 @@ void cPlayer::KilledBy(cEntity * a_Killer)
Pickups.Add(cItem(E_ITEM_RED_APPLE));
}
- m_Stats.AddValue(statItemsDropped, Pickups.Size());
+ m_Stats.AddValue(statItemsDropped, (StatValue)Pickups.Size());
m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10);
SaveToDisk(); // Save it, yeah the world is a tough place !
- if (a_Killer == NULL)
+ if ((a_TDI.Attacker == NULL) && m_World->ShouldBroadcastDeathMessages())
+ {
+ AString DamageText;
+ switch (a_TDI.DamageType)
+ {
+ case dtRangedAttack: DamageText = "was shot"; break;
+ case dtLightning: DamageText = "was plasmified by lightining"; break;
+ case dtFalling: DamageText = (GetWorld()->GetTickRandomNumber(10) % 2 == 0) ? "fell to death" : "hit the ground too hard"; break;
+ case dtDrowning: DamageText = "drowned"; break;
+ case dtSuffocating: DamageText = (GetWorld()->GetTickRandomNumber(10) % 2 == 0) ? "git merge'd into a block" : "fused with a block"; break;
+ case dtStarving: DamageText = "forgot the importance of food"; break;
+ case dtCactusContact: DamageText = "was impaled on a cactus"; break;
+ case dtLavaContact: DamageText = "was melted by lava"; break;
+ case dtPoisoning: DamageText = "died from septicaemia"; break;
+ case dtWithering: DamageText = "is a husk of their former selves"; break;
+ case dtOnFire: DamageText = "forgot to stop, drop, and roll"; break;
+ case dtFireContact: DamageText = "burnt themselves to death"; break;
+ case dtInVoid: DamageText = "somehow fell out of the world"; break;
+ case dtPotionOfHarming: DamageText = "was magicked to death"; break;
+ case dtEnderPearl: DamageText = "misused an ender pearl"; break;
+ case dtAdmin: DamageText = "was administrator'd"; break;
+ case dtExplosion: DamageText = "blew up"; break;
+ default: DamageText = "died, somehow; we've no idea how though"; break;
+ }
+ GetWorld()->BroadcastChatDeath(Printf("%s %s", GetName().c_str(), DamageText.c_str()));
+ }
+ else if (a_TDI.Attacker == NULL) // && !m_World->ShouldBroadcastDeathMessages() by fallthrough
{
- GetWorld()->BroadcastChatDeath(Printf("%s was killed by environmental damage", GetName().c_str()));
+ // no-op
}
- else if (a_Killer->IsPlayer())
+ else if (a_TDI.Attacker->IsPlayer())
{
- cPlayer * Killer = (cPlayer *)a_Killer;
+ cPlayer * Killer = (cPlayer *)a_TDI.Attacker;
GetWorld()->BroadcastChatDeath(Printf("%s was killed by %s", GetName().c_str(), Killer->GetName().c_str()));
}
else
{
- AString KillerClass = a_Killer->GetClass();
- KillerClass.erase(KillerClass.begin()); // Erase the 'c' of the class (e.g. "cWitch" -> "Witch")
+ AString KillerClass = a_TDI.Attacker->GetClass();
+ KillerClass.erase(KillerClass.begin()); // Erase the 'c' of the class (e.g. "cWitch" -> "Witch")
GetWorld()->BroadcastChatDeath(Printf("%s was killed by a %s", GetName().c_str(), KillerClass.c_str()));
}
@@ -986,12 +994,12 @@ void cPlayer::Respawn(void)
m_LifetimeTotalXp = 0;
// ToDo: send score to client? How?
- m_ClientHandle->SendRespawn(*m_World, true);
+ m_ClientHandle->SendRespawn(GetWorld()->GetDimension(), true);
// Extinguish the fire:
StopBurning();
- TeleportToCoords(GetWorld()->GetSpawnX(), GetWorld()->GetSpawnY(), GetWorld()->GetSpawnZ());
+ TeleportToCoords(GetLastBedPos().x, GetLastBedPos().y, GetLastBedPos().z);
SetVisible(true);
}
@@ -1010,7 +1018,7 @@ double cPlayer::GetEyeHeight(void) const
Vector3d cPlayer::GetEyePosition(void) const
{
- return Vector3d( GetPosX(), m_Stance, GetPosZ() );
+ return Vector3d( GetPosX(), m_Stance, GetPosZ());
}
@@ -1172,7 +1180,7 @@ void cPlayer::SetGameMode(eGameMode a_GameMode)
-void cPlayer::LoginSetGameMode( eGameMode a_GameMode )
+void cPlayer::LoginSetGameMode( eGameMode a_GameMode)
{
m_GameMode = a_GameMode;
}
@@ -1211,11 +1219,13 @@ unsigned int cPlayer::AwardAchievement(const eStatistic a_Ach)
}
else
{
- // First time, announce it
- cCompositeChat Msg;
- Msg.SetMessageType(mtSuccess);
- Msg.AddShowAchievementPart(GetName(), cStatInfo::GetName(a_Ach));
- m_World->BroadcastChat(Msg);
+ if (m_World->ShouldBroadcastAchievementMessages())
+ {
+ cCompositeChat Msg;
+ Msg.SetMessageType(mtSuccess);
+ Msg.AddShowAchievementPart(GetName(), cStatInfo::GetName(a_Ach));
+ m_World->BroadcastChat(Msg);
+ }
// Increment the statistic
StatValue New = m_Stats.AddValue(a_Ach);
@@ -1281,7 +1291,7 @@ Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const
// TODO: Add a slight random change (+-0.0075 in each direction)
return res * a_SpeedCoeff;
-}
+}
@@ -1308,13 +1318,13 @@ void cPlayer::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
-void cPlayer::MoveTo( const Vector3d & a_NewPos )
+void cPlayer::MoveTo( const Vector3d & a_NewPos)
{
if ((a_NewPos.y < -990) && (GetPosY() > -100))
{
// When attached to an entity, the client sends position packets with weird coords:
// Y = -999 and X, Z = attempting to create speed, usually up to 0.03
- // We cannot test m_AttachedTo, because when deattaching, the server thinks the client is already deattached while
+ // We cannot test m_AttachedTo, because when deattaching, the server thinks the client is already deattached while
// the client may still send more of these nonsensical packets.
if (m_AttachedTo != NULL)
{
@@ -1331,7 +1341,7 @@ void cPlayer::MoveTo( const Vector3d & a_NewPos )
Vector3d DeltaPos = a_NewPos - GetPosition();
UpdateMovementStats(DeltaPos);
- SetPosition( a_NewPos );
+ SetPosition( a_NewPos);
SetStance(a_NewPos.y + 1.62);
}
@@ -1341,7 +1351,7 @@ void cPlayer::MoveTo( const Vector3d & a_NewPos )
void cPlayer::SetVisible(bool a_bVisible)
{
- if (a_bVisible && !m_bVisible) // Make visible
+ if (a_bVisible && !m_bVisible) // Make visible
{
m_bVisible = true;
m_World->BroadcastSpawnEntity(*this);
@@ -1349,7 +1359,7 @@ void cPlayer::SetVisible(bool a_bVisible)
if (!a_bVisible && m_bVisible)
{
m_bVisible = false;
- m_World->BroadcastDestroyEntity(*this, m_ClientHandle); // Destroy on all clients
+ m_World->BroadcastDestroyEntity(*this, m_ClientHandle); // Destroy on all clients
}
}
@@ -1357,11 +1367,11 @@ void cPlayer::SetVisible(bool a_bVisible)
-void cPlayer::AddToGroup( const AString & a_GroupName )
+void cPlayer::AddToGroup( const AString & a_GroupName)
{
- cGroup* Group = cRoot::Get()->GetGroupManager()->GetGroup( a_GroupName );
- m_Groups.push_back( Group );
- LOGD("Added %s to group %s", GetName().c_str(), a_GroupName.c_str() );
+ cGroup* Group = cRoot::Get()->GetGroupManager()->GetGroup( a_GroupName);
+ m_Groups.push_back( Group);
+ LOGD("Added %s to group %s", GetName().c_str(), a_GroupName.c_str());
ResolveGroups();
ResolvePermissions();
}
@@ -1370,28 +1380,28 @@ void cPlayer::AddToGroup( const AString & a_GroupName )
-void cPlayer::RemoveFromGroup( const AString & a_GroupName )
+void cPlayer::RemoveFromGroup( const AString & a_GroupName)
{
bool bRemoved = false;
- for( GroupList::iterator itr = m_Groups.begin(); itr != m_Groups.end(); ++itr )
+ for (GroupList::iterator itr = m_Groups.begin(); itr != m_Groups.end(); ++itr)
{
- if( (*itr)->GetName().compare(a_GroupName ) == 0 )
+ if ((*itr)->GetName().compare(a_GroupName) == 0)
{
- m_Groups.erase( itr );
+ m_Groups.erase( itr);
bRemoved = true;
break;
}
}
- if( bRemoved )
+ if (bRemoved)
{
- LOGD("Removed %s from group %s", GetName().c_str(), a_GroupName.c_str() );
+ LOGD("Removed %s from group %s", GetName().c_str(), a_GroupName.c_str());
ResolveGroups();
ResolvePermissions();
}
else
{
- LOGWARN("Tried to remove %s from group %s but was not in that group", GetName().c_str(), a_GroupName.c_str() );
+ LOGWARN("Tried to remove %s from group %s but was not in that group", GetName().c_str(), a_GroupName.c_str());
}
}
@@ -1407,30 +1417,30 @@ bool cPlayer::HasPermission(const AString & a_Permission)
return true;
}
- AStringVector Split = StringSplit( a_Permission, "." );
+ AStringVector Split = StringSplit( a_Permission, ".");
PermissionMap Possibilities = m_ResolvedPermissions;
// Now search the namespaces
- while( Possibilities.begin() != Possibilities.end() )
+ while (Possibilities.begin() != Possibilities.end())
{
PermissionMap::iterator itr = Possibilities.begin();
- if( itr->second )
+ if (itr->second)
{
- AStringVector OtherSplit = StringSplit( itr->first, "." );
- if( OtherSplit.size() <= Split.size() )
+ AStringVector OtherSplit = StringSplit( itr->first, ".");
+ if (OtherSplit.size() <= Split.size())
{
unsigned int i;
- for( i = 0; i < OtherSplit.size(); ++i )
+ for (i = 0; i < OtherSplit.size(); ++i)
{
- if( OtherSplit[i].compare( Split[i] ) != 0 )
+ if (OtherSplit[i].compare( Split[i]) != 0)
{
- if( OtherSplit[i].compare("*") == 0 ) return true; // WildCard man!! WildCard!
+ if (OtherSplit[i].compare("*") == 0) return true; // WildCard man!! WildCard!
break;
}
}
- if( i == Split.size() ) return true;
+ if (i == Split.size()) return true;
}
}
- Possibilities.erase( itr );
+ Possibilities.erase( itr);
}
// Nothing that matched :(
@@ -1441,11 +1451,11 @@ bool cPlayer::HasPermission(const AString & a_Permission)
-bool cPlayer::IsInGroup( const AString & a_Group )
+bool cPlayer::IsInGroup( const AString & a_Group)
{
- for( GroupList::iterator itr = m_ResolvedGroups.begin(); itr != m_ResolvedGroups.end(); ++itr )
+ for (GroupList::iterator itr = m_ResolvedGroups.begin(); itr != m_ResolvedGroups.end(); ++itr)
{
- if( a_Group.compare( (*itr)->GetName().c_str() ) == 0 )
+ if (a_Group.compare( (*itr)->GetName().c_str()) == 0)
return true;
}
return false;
@@ -1457,18 +1467,18 @@ bool cPlayer::IsInGroup( const AString & a_Group )
void cPlayer::ResolvePermissions()
{
- m_ResolvedPermissions.clear(); // Start with an empty map yo~
+ m_ResolvedPermissions.clear(); // Start with an empty map
// Copy all player specific permissions into the resolved permissions map
- for( PermissionMap::iterator itr = m_Permissions.begin(); itr != m_Permissions.end(); ++itr )
+ for (PermissionMap::iterator itr = m_Permissions.begin(); itr != m_Permissions.end(); ++itr)
{
m_ResolvedPermissions[ itr->first ] = itr->second;
}
- for( GroupList::iterator GroupItr = m_ResolvedGroups.begin(); GroupItr != m_ResolvedGroups.end(); ++GroupItr )
+ for (GroupList::iterator GroupItr = m_ResolvedGroups.begin(); GroupItr != m_ResolvedGroups.end(); ++GroupItr)
{
const cGroup::PermissionMap & Permissions = (*GroupItr)->GetPermissions();
- for( cGroup::PermissionMap::const_iterator itr = Permissions.begin(); itr != Permissions.end(); ++itr )
+ for (cGroup::PermissionMap::const_iterator itr = Permissions.begin(); itr != Permissions.end(); ++itr)
{
m_ResolvedPermissions[ itr->first ] = itr->second;
}
@@ -1485,16 +1495,16 @@ void cPlayer::ResolveGroups()
m_ResolvedGroups.clear();
// Get a complete resolved list of all groups the player is in
- std::map< cGroup*, bool > AllGroups; // Use a map, because it's faster than iterating through a list to find duplicates
+ std::map< cGroup*, bool > AllGroups; // Use a map, because it's faster than iterating through a list to find duplicates
GroupList ToIterate;
- for( GroupList::iterator GroupItr = m_Groups.begin(); GroupItr != m_Groups.end(); ++GroupItr )
+ for (GroupList::iterator GroupItr = m_Groups.begin(); GroupItr != m_Groups.end(); ++GroupItr)
{
- ToIterate.push_back( *GroupItr );
+ ToIterate.push_back( *GroupItr);
}
- while( ToIterate.begin() != ToIterate.end() )
+ while (ToIterate.begin() != ToIterate.end())
{
cGroup* CurrentGroup = *ToIterate.begin();
- if( AllGroups.find( CurrentGroup ) != AllGroups.end() )
+ if (AllGroups.find( CurrentGroup) != AllGroups.end())
{
LOGWARNING("ERROR: Player \"%s\" is in the group multiple times (\"%s\"). Please fix your settings in users.ini!",
GetName().c_str(), CurrentGroup->GetName().c_str()
@@ -1503,19 +1513,19 @@ void cPlayer::ResolveGroups()
else
{
AllGroups[ CurrentGroup ] = true;
- m_ResolvedGroups.push_back( CurrentGroup ); // Add group to resolved list
+ m_ResolvedGroups.push_back( CurrentGroup); // Add group to resolved list
const cGroup::GroupList & Inherits = CurrentGroup->GetInherits();
- for( cGroup::GroupList::const_iterator itr = Inherits.begin(); itr != Inherits.end(); ++itr )
+ for (cGroup::GroupList::const_iterator itr = Inherits.begin(); itr != Inherits.end(); ++itr)
{
- if( AllGroups.find( *itr ) != AllGroups.end() )
+ if (AllGroups.find( *itr) != AllGroups.end())
{
- LOGERROR("ERROR: Player %s is in the same group multiple times due to inheritance (%s). FIX IT!", GetName().c_str(), (*itr)->GetName().c_str() );
+ LOGERROR("ERROR: Player %s is in the same group multiple times due to inheritance (%s). FIX IT!", GetName().c_str(), (*itr)->GetName().c_str());
continue;
}
- ToIterate.push_back( *itr );
+ ToIterate.push_back( *itr);
}
}
- ToIterate.erase( ToIterate.begin() );
+ ToIterate.erase( ToIterate.begin());
}
}
@@ -1525,12 +1535,12 @@ void cPlayer::ResolveGroups()
AString cPlayer::GetColor(void) const
{
- if ( m_Color != '-' )
+ if (m_Color != '-')
{
- return cChatColor::Color + m_Color;
+ return cChatColor::Delimiter + m_Color;
}
- if ( m_Groups.size() < 1 )
+ if (m_Groups.size() < 1)
{
return cChatColor::White;
}
@@ -1551,7 +1561,7 @@ void cPlayer::TossEquippedItem(char a_Amount)
char NewAmount = a_Amount;
if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount)
{
- NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there
+ NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there
}
GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount);
@@ -1608,41 +1618,41 @@ void cPlayer::TossPickup(const cItem & a_Item)
void cPlayer::TossItems(const cItems & a_Items)
{
- m_Stats.AddValue(statItemsDropped, a_Items.Size());
+ m_Stats.AddValue(statItemsDropped, (StatValue)a_Items.Size());
double vX = 0, vY = 0, vZ = 0;
EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY);
vY = -vY * 2 + 1.f;
- m_World->SpawnItemPickups(a_Items, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player
+ m_World->SpawnItemPickups(a_Items, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player
}
-bool cPlayer::MoveToWorld(const char * a_WorldName)
+bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn)
{
- cWorld * World = cRoot::Get()->GetWorld(a_WorldName);
- if (World == NULL)
+ ASSERT(a_World != NULL);
+
+ if (GetWorld() == a_World)
{
- LOG("%s: Couldn't find world \"%s\".", __FUNCTION__, a_WorldName);
+ // Don't move to same world
return false;
}
// Send the respawn packet:
- if (m_ClientHandle != NULL)
+ if (a_ShouldSendRespawn && (m_ClientHandle != NULL))
{
- m_ClientHandle->SendRespawn(*World);
+ m_ClientHandle->SendRespawn(a_World->GetDimension());
}
- // Remove all links to the old world
- m_World->RemovePlayer(this);
-
- // If the dimension is different, we can send the respawn packet
- // http://wiki.vg/Protocol#0x09 says "don't send if dimension is the same" as of 2013_07_02
+ // Remove player from the old world
+ SetWorldTravellingFrom(GetWorld()); // cChunk handles entity removal
+ GetWorld()->RemovePlayer(this, false);
// Queue adding player to the new world, including all the necessary adjustments to the object
- World->AddPlayer(this);
+ a_World->AddPlayer(this);
+ SetWorld(a_World); // Chunks may be streamed before cWorld::AddPlayer() sets the world to the new value
return true;
}
@@ -1690,53 +1700,104 @@ void cPlayer::LoadPermissionsFromDisk()
-bool cPlayer::LoadFromDisk()
+bool cPlayer::LoadFromDisk(cWorldPtr & a_World)
{
LoadPermissionsFromDisk();
- AString SourceFile;
- Printf(SourceFile, "players/%s.json", GetName().c_str() );
+ // Load from the UUID file:
+ if (LoadFromFile(GetUUIDFileName(m_UUID), a_World))
+ {
+ return true;
+ }
+
+ // Load from the offline UUID file, if allowed:
+ AString OfflineUUID = cClientHandle::GenerateOfflineUUID(GetName());
+ const char * OfflineUsage = " (unused)";
+ if (cRoot::Get()->GetServer()->ShouldLoadOfflinePlayerData())
+ {
+ OfflineUsage = "";
+ if (LoadFromFile(GetUUIDFileName(OfflineUUID), a_World))
+ {
+ return true;
+ }
+ }
+
+ // Load from the old-style name-based file, if allowed:
+ if (cRoot::Get()->GetServer()->ShouldLoadNamedPlayerData())
+ {
+ AString OldStyleFileName = Printf("players/%s.json", GetName().c_str());
+ if (LoadFromFile(OldStyleFileName, a_World))
+ {
+ // Save in new format and remove the old file
+ if (SaveToDisk())
+ {
+ cFile::Delete(OldStyleFileName);
+ }
+ return true;
+ }
+ }
+
+ // None of the files loaded successfully
+ LOG("Player data file not found for %s (%s, offline %s%s), will be reset to defaults.",
+ GetName().c_str(), m_UUID.c_str(), OfflineUUID.c_str(), OfflineUsage
+ );
+
+ if (a_World == NULL)
+ {
+ a_World = cRoot::Get()->GetDefaultWorld();
+ }
+ return false;
+}
+
+
+
+
+bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
+{
+ // Load the data from the file:
cFile f;
- if (!f.Open(SourceFile, cFile::fmRead))
+ if (!f.Open(a_FileName, cFile::fmRead))
{
// This is a new player whom we haven't seen yet, bail out, let them have the defaults
return false;
}
-
AString buffer;
if (f.ReadRestOfFile(buffer) != f.GetSize())
{
- LOGWARNING("Cannot read player data from file \"%s\"", SourceFile.c_str());
+ LOGWARNING("Cannot read player data from file \"%s\"", a_FileName.c_str());
return false;
}
- f.Close(); //cool kids play nice
+ f.Close();
+ // Parse the JSON format:
Json::Value root;
Json::Reader reader;
if (!reader.parse(buffer, root, false))
{
- LOGWARNING("Cannot parse player data in file \"%s\", player will be reset", SourceFile.c_str());
+ LOGWARNING("Cannot parse player data in file \"%s\"", a_FileName.c_str());
+ return false;
}
+ // Load the player data:
Json::Value & JSON_PlayerPosition = root["position"];
if (JSON_PlayerPosition.size() == 3)
{
- SetPosX(JSON_PlayerPosition[(unsigned int)0].asDouble());
- SetPosY(JSON_PlayerPosition[(unsigned int)1].asDouble());
- SetPosZ(JSON_PlayerPosition[(unsigned int)2].asDouble());
+ SetPosX(JSON_PlayerPosition[(unsigned)0].asDouble());
+ SetPosY(JSON_PlayerPosition[(unsigned)1].asDouble());
+ SetPosZ(JSON_PlayerPosition[(unsigned)2].asDouble());
m_LastPos = GetPosition();
}
Json::Value & JSON_PlayerRotation = root["rotation"];
if (JSON_PlayerRotation.size() == 3)
{
- SetYaw ((float)JSON_PlayerRotation[(unsigned int)0].asDouble());
- SetPitch ((float)JSON_PlayerRotation[(unsigned int)1].asDouble());
- SetRoll ((float)JSON_PlayerRotation[(unsigned int)2].asDouble());
+ SetYaw ((float)JSON_PlayerRotation[(unsigned)0].asDouble());
+ SetPitch ((float)JSON_PlayerRotation[(unsigned)1].asDouble());
+ SetRoll ((float)JSON_PlayerRotation[(unsigned)2].asDouble());
}
- m_Health = root.get("health", 0).asInt();
+ m_Health = root.get("health", 0).asInt();
m_AirLevel = root.get("air", MAX_AIR_LEVEL).asInt();
m_FoodLevel = root.get("food", MAX_FOOD_LEVEL).asInt();
m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
@@ -1757,14 +1818,19 @@ bool cPlayer::LoadFromDisk()
cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);
m_LoadedWorldName = root.get("world", "world").asString();
+ a_World = cRoot::Get()->GetWorld(GetLoadedWorldName(), true);
+
+ m_LastBedPos.x = root.get("SpawnX", a_World->GetSpawnX()).asInt();
+ m_LastBedPos.y = root.get("SpawnY", a_World->GetSpawnY()).asInt();
+ m_LastBedPos.z = root.get("SpawnZ", a_World->GetSpawnZ()).asInt();
// Load the player stats.
// We use the default world name (like bukkit) because stats are shared between dimensions/worlds.
cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
StatSerializer.Load();
- LOGD("Player \"%s\" was read from file, spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
- GetName().c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str()
+ LOGD("Player %s was read from file \"%s\", spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
+ GetName().c_str(), a_FileName.c_str(), GetPosX(), GetPosY(), GetPosZ(), a_World->GetName().c_str()
);
return true;
@@ -1776,7 +1842,8 @@ bool cPlayer::LoadFromDisk()
bool cPlayer::SaveToDisk()
{
- cFile::CreateFolder(FILE_IO_PREFIX + AString("players"));
+ cFile::CreateFolder(FILE_IO_PREFIX + AString("players/")); // Create the "players" folder, if it doesn't exist yet (#1268)
+ cFile::CreateFolder(FILE_IO_PREFIX + AString("players/") + m_UUID.substr(0, 2));
// create the JSON data
Json::Value JSON_PlayerPosition;
@@ -1808,33 +1875,49 @@ bool cPlayer::SaveToDisk()
root["foodSaturation"] = m_FoodSaturationLevel;
root["foodTickTimer"] = m_FoodTickTimer;
root["foodExhaustion"] = m_FoodExhaustionLevel;
- root["world"] = GetWorld()->GetName();
root["isflying"] = IsFlying();
+ root["lastknownname"] = GetName();
+ root["SpawnX"] = GetLastBedPos().x;
+ root["SpawnY"] = GetLastBedPos().y;
+ root["SpawnZ"] = GetLastBedPos().z;
- if (m_GameMode == GetWorld()->GetGameMode())
+ if (m_World != NULL)
{
- root["gamemode"] = (int) eGameMode_NotSet;
+ root["world"] = m_World->GetName();
+ if (m_GameMode == m_World->GetGameMode())
+ {
+ root["gamemode"] = (int) eGameMode_NotSet;
+ }
+ else
+ {
+ root["gamemode"] = (int) m_GameMode;
+ }
}
else
{
- root["gamemode"] = (int) m_GameMode;
+ // This happens if the player is saved to new format after loading from the old format
+ root["world"] = m_LoadedWorldName;
+ root["gamemode"] = (int) eGameMode_NotSet;
}
Json::StyledWriter writer;
std::string JsonData = writer.write(root);
- AString SourceFile;
- Printf(SourceFile, "players/%s.json", GetName().c_str() );
+ AString SourceFile = GetUUIDFileName(m_UUID);
cFile f;
if (!f.Open(SourceFile, cFile::fmWrite))
{
- LOGERROR("ERROR WRITING PLAYER \"%s\" TO FILE \"%s\" - cannot open file", GetName().c_str(), SourceFile.c_str());
+ LOGWARNING("Error writing player \"%s\" to file \"%s\" - cannot open file. Player will lose their progress.",
+ GetName().c_str(), SourceFile.c_str()
+ );
return false;
}
if (f.Write(JsonData.c_str(), JsonData.size()) != (int)JsonData.size())
{
- LOGERROR("ERROR WRITING PLAYER JSON TO FILE \"%s\"", SourceFile.c_str());
+ LOGWARNING("Error writing player \"%s\" to file \"%s\" - cannot save data. Player will lose their progress. ",
+ GetName().c_str(), SourceFile.c_str()
+ );
return false;
}
@@ -1843,7 +1926,7 @@ bool cPlayer::SaveToDisk()
cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
if (!StatSerializer.Save())
{
- LOGERROR("Could not save stats for player %s", GetName().c_str());
+ LOGWARNING("Could not save stats for player %s", GetName().c_str());
return false;
}
@@ -1859,11 +1942,11 @@ cPlayer::StringList cPlayer::GetResolvedPermissions()
StringList Permissions;
const PermissionMap& ResolvedPermissions = m_ResolvedPermissions;
- for( PermissionMap::const_iterator itr = ResolvedPermissions.begin(); itr != ResolvedPermissions.end(); ++itr )
+ for (PermissionMap::const_iterator itr = ResolvedPermissions.begin(); itr != ResolvedPermissions.end(); ++itr)
{
if (itr->second)
{
- Permissions.push_back( itr->first );
+ Permissions.push_back( itr->first);
}
}
@@ -1874,16 +1957,16 @@ cPlayer::StringList cPlayer::GetResolvedPermissions()
-void cPlayer::UseEquippedItem(void)
+void cPlayer::UseEquippedItem(int a_Amount)
{
- if (IsGameModeCreative()) // No damage in creative
+ if (IsGameModeCreative()) // No damage in creative
{
return;
}
- if (GetInventory().DamageEquippedItem())
+ if (GetInventory().DamageEquippedItem(a_Amount))
{
- m_World->BroadcastSoundEffect("random.break", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
+ m_World->BroadcastSoundEffect("random.break", GetPosX(), GetPosY(), GetPosZ(), 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
}
}
@@ -1918,19 +2001,34 @@ void cPlayer::HandleFood(void)
return;
}
+ // Apply food exhaustion that has accumulated:
+ if (m_FoodExhaustionLevel > 4.0)
+ {
+ m_FoodExhaustionLevel -= 4.0;
+
+ if (m_FoodSaturationLevel > 0.0)
+ {
+ m_FoodSaturationLevel = std::max(m_FoodSaturationLevel - 1.0, 0.0);
+ }
+ else
+ {
+ SetFoodLevel(m_FoodLevel - 1);
+ }
+ }
+
// Heal or damage, based on the food level, using the m_FoodTickTimer:
- if ((m_FoodLevel > 17) || (m_FoodLevel <= 0))
+ if ((m_FoodLevel >= 18) || (m_FoodLevel <= 0))
{
m_FoodTickTimer++;
if (m_FoodTickTimer >= 80)
{
m_FoodTickTimer = 0;
- if ((m_FoodLevel > 17) && (GetHealth() < GetMaxHealth()))
+ if ((m_FoodLevel >= 18) && (GetHealth() < GetMaxHealth()))
{
// Regenerate health from food, incur 3 pts of food exhaustion:
Heal(1);
- m_FoodExhaustionLevel += 3.0;
+ AddFoodExhaustion(3.0);
}
else if ((m_FoodLevel <= 0) && (m_Health > 1))
{
@@ -1939,31 +2037,9 @@ void cPlayer::HandleFood(void)
}
}
}
-
- // Apply food poisoning food exhaustion:
- if (m_FoodPoisonedTicksRemaining > 0)
- {
- m_FoodPoisonedTicksRemaining--;
- m_FoodExhaustionLevel += 0.025; // 0.5 per second = 0.025 per tick
- }
else
{
- m_World->BroadcastRemoveEntityEffect(*this, E_EFFECT_HUNGER); // Remove the "Hunger" effect.
- }
-
- // Apply food exhaustion that has accumulated:
- if (m_FoodExhaustionLevel >= 4.0)
- {
- m_FoodExhaustionLevel -= 4.0;
-
- if (m_FoodSaturationLevel >= 1.0)
- {
- m_FoodSaturationLevel -= 1.0;
- }
- else
- {
- SetFoodLevel(m_FoodLevel - 1);
- }
+ m_FoodTickTimer = 0;
}
}
@@ -2030,7 +2106,7 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos)
{
if (IsClimbing())
{
- if (a_DeltaPos.y > 0.0) // Going up
+ if (a_DeltaPos.y > 0.0) // Going up
{
m_Stats.AddValue(statDistClimbed, (StatValue)floor(a_DeltaPos.y * 100 + 0.5));
}
@@ -2038,18 +2114,21 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos)
else if (IsSubmerged())
{
m_Stats.AddValue(statDistDove, Value);
+ AddFoodExhaustion(0.00015 * (double)Value);
}
else if (IsSwimming())
{
m_Stats.AddValue(statDistSwum, Value);
+ AddFoodExhaustion(0.00015 * (double)Value);
}
else if (IsOnGround())
{
m_Stats.AddValue(statDistWalked, Value);
+ AddFoodExhaustion((m_IsSprinting ? 0.001 : 0.0001) * (double)Value);
}
else
{
- if (Value >= 25) // Ignore small/slow movement
+ if (Value >= 25) // Ignore small/slow movement
{
m_Stats.AddValue(statDistFlown, Value);
}
@@ -2087,6 +2166,8 @@ void cPlayer::ApplyFoodExhaustionFromMovement()
{
return;
}
+
+ // If we have just teleported, apply no exhaustion
if (m_bIsTeleporting)
{
m_bIsTeleporting = false;
@@ -2098,6 +2179,13 @@ void cPlayer::ApplyFoodExhaustionFromMovement()
{
return;
}
+
+ // Process exhaustion every two ticks as that is how frequently m_LastPos is updated
+ // Otherwise, we apply exhaustion for a 'movement' every tick, one of which is an already processed value
+ if (GetWorld()->GetWorldAge() % 2 != 0)
+ {
+ return;
+ }
// Calculate the distance travelled, update the last pos:
Vector3d Movement(GetPosition() - m_LastPos);
@@ -2156,3 +2244,20 @@ void cPlayer::Detach()
+
+AString cPlayer::GetUUIDFileName(const AString & a_UUID)
+{
+ AString UUID = cMojangAPI::MakeUUIDDashed(a_UUID);
+ ASSERT(UUID.length() == 36);
+
+ AString res("players/");
+ res.append(UUID, 0, 2);
+ res.push_back('/');
+ res.append(UUID, 2, AString::npos);
+ res.append(".json");
+ return res;
+}
+
+
+
+
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index f247ac2f9..d3ed1ef9d 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -29,25 +29,27 @@ class cPlayer :
typedef cPawn super;
public:
- enum
- {
- MAX_HEALTH = 20,
- MAX_FOOD_LEVEL = 20,
- EATING_TICKS = 30, ///< Number of ticks it takes to eat an item
- } ;
+ static const int MAX_HEALTH;
+
+ static const int MAX_FOOD_LEVEL;
+
+ /** Number of ticks it takes to eat an item */
+ static const int EATING_TICKS;
+
// tolua_end
CLASS_PROTODEF(cPlayer)
cPlayer(cClientHandle * a_Client, const AString & a_PlayerName);
+
virtual ~cPlayer();
virtual void SpawnOn(cClientHandle & a_Client) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
- virtual void HandlePhysics(float a_Dt, cChunk &) override { UNUSED(a_Dt); };
+ virtual void HandlePhysics(float a_Dt, cChunk &) override { UNUSED(a_Dt); }
/** Returns the curently equipped weapon; empty item if none */
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
@@ -116,13 +118,13 @@ public:
/** Returns true if the player is currently charging the bow */
bool IsChargingBow(void) const { return m_IsChargingBow; }
- void SetTouchGround( bool a_bTouchGround );
- inline void SetStance( const double a_Stance ) { m_Stance = a_Stance; }
- double GetEyeHeight(void) const; // tolua_export
- Vector3d GetEyePosition(void) const; // tolua_export
+ void SetTouchGround( bool a_bTouchGround);
+ inline void SetStance( const double a_Stance) { m_Stance = a_Stance; }
+ double GetEyeHeight(void) const; // tolua_export
+ Vector3d GetEyePosition(void) const; // tolua_export
inline bool IsOnGround(void) const {return m_bTouchGround; } // tolua_export
inline double GetStance(void) const { return GetPosY() + 1.62; } // tolua_export // TODO: Proper stance when crouching etc.
- inline cInventory & GetInventory(void) { return m_Inventory; } // tolua_export
+ inline cInventory & GetInventory(void) { return m_Inventory; } // tolua_export
inline const cInventory & GetInventory(void) const { return m_Inventory; }
/** Gets the contents of the player's associated enderchest */
@@ -130,7 +132,7 @@ public:
inline const cItem & GetEquippedItem(void) const { return GetInventory().GetEquippedItem(); } // tolua_export
- /** Returns whether the player is climbing (ladders, vines e.t.c). */
+ /** Returns whether the player is climbing (ladders, vines etc.) */
bool IsClimbing(void) const;
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) override;
@@ -173,7 +175,7 @@ public:
AString GetIP(void) const { return m_IP; } // tolua_export
/** Returns the associated team, NULL if none */
- cTeam * GetTeam(void) { return m_Team; } // tolua_export
+ cTeam * GetTeam(void) { return m_Team; } // tolua_export
/** Sets the player team, NULL if none */
void SetTeam(cTeam * a_Team);
@@ -197,9 +199,9 @@ public:
// Sets the current gamemode, doesn't check validity, doesn't send update packets to client
void LoginSetGameMode(eGameMode a_GameMode);
- /** Forces the player to move in the given direction.
+ /** Forces the player to move in the given direction.
@deprecated Use SetSpeed instead. */
- void ForceSetSpeed(const Vector3d & a_Speed); // tolua_export
+ void ForceSetSpeed(const Vector3d & a_Speed); // tolua_export
/** Tries to move to a new position, with attachment-related checks (y == -999) */
void MoveTo(const Vector3d & a_NewPos); // tolua_export
@@ -238,15 +240,15 @@ public:
typedef std::list< std::string > StringList;
/** Adds a player to existing group or creates a new group when it doesn't exist */
- void AddToGroup( const AString & a_GroupName ); // tolua_export
+ void AddToGroup( const AString & a_GroupName); // tolua_export
/** Removes a player from the group, resolves permissions and group inheritance (case sensitive) */
- void RemoveFromGroup( const AString & a_GroupName ); // tolua_export
+ void RemoveFromGroup( const AString & a_GroupName); // tolua_export
- bool HasPermission( const AString & a_Permission ); // tolua_export
- const GroupList & GetGroups() { return m_Groups; } // >> EXPORTED IN MANUALBINDINGS <<
- StringList GetResolvedPermissions(); // >> EXPORTED IN MANUALBINDINGS <<
- bool IsInGroup( const AString & a_Group ); // tolua_export
+ bool HasPermission( const AString & a_Permission); // tolua_export
+ const GroupList & GetGroups() { return m_Groups; } // >> EXPORTED IN MANUALBINDINGS <<
+ StringList GetResolvedPermissions(); // >> EXPORTED IN MANUALBINDINGS <<
+ bool IsInGroup( const AString & a_Group); // tolua_export
// tolua_begin
@@ -264,13 +266,12 @@ public:
void TossPickup(const cItem & a_Item);
/** Heals the player by the specified amount of HPs (positive only); sends health update */
- void Heal(int a_Health);
+ virtual void Heal(int a_Health) override;
int GetFoodLevel (void) const { return m_FoodLevel; }
double GetFoodSaturationLevel (void) const { return m_FoodSaturationLevel; }
int GetFoodTickTimer (void) const { return m_FoodTickTimer; }
double GetFoodExhaustionLevel (void) const { return m_FoodExhaustionLevel; }
- int GetFoodPoisonedTicksRemaining(void) const { return m_FoodPoisonedTicksRemaining; }
/** Returns true if the player is satiated, i. e. their foodlevel is at the max and they cannot eat anymore */
bool IsSatiated(void) const { return (m_FoodLevel >= MAX_FOOD_LEVEL); }
@@ -279,19 +280,12 @@ public:
void SetFoodSaturationLevel (double a_FoodSaturationLevel);
void SetFoodTickTimer (int a_FoodTickTimer);
void SetFoodExhaustionLevel (double a_FoodExhaustionLevel);
- void SetFoodPoisonedTicksRemaining(int a_FoodPoisonedTicksRemaining);
/** Adds to FoodLevel and FoodSaturationLevel, returns true if any food has been consumed, false if player "full" */
bool Feed(int a_Food, double a_Saturation);
/** Adds the specified exhaustion to m_FoodExhaustion. Expects only positive values. */
- void AddFoodExhaustion(double a_Exhaustion)
- {
- m_FoodExhaustionLevel += a_Exhaustion;
- }
-
- /** Starts the food poisoning for the specified amount of ticks; if already foodpoisoned, sets FoodPoisonedTicksRemaining to the larger of the two */
- void FoodPoison(int a_NumTicks);
+ void AddFoodExhaustion(double a_Exhaustion);
/** Returns true if the player is currently in the process of eating the currently equipped item */
bool IsEating(void) const { return (m_EatingFinishTick >= 0); }
@@ -323,33 +317,47 @@ public:
/** Aborts the current eating operation */
void AbortEating(void);
- virtual void KilledBy(cEntity * a_Killer) override;
+ virtual void KilledBy(TakeDamageInfo & a_TDI) override;
virtual void Killed(cEntity * a_Victim) override;
-
- void Respawn(void); // tolua_export
- void SetVisible( bool a_bVisible ); // tolua_export
- bool IsVisible(void) const { return m_bVisible; } // tolua_export
+ void Respawn(void); // tolua_export
+
+ void SetVisible( bool a_bVisible); // tolua_export
+ bool IsVisible(void) const { return m_bVisible; } // tolua_export
/** Moves the player to the specified world.
Returns true if successful, false on failure (world not found). */
- bool MoveToWorld(const char * a_WorldName); // tolua_export
+ virtual bool DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn) override;
+ /** Saves all player data, such as inventory, to JSON */
bool SaveToDisk(void);
- bool LoadFromDisk(void);
- void LoadPermissionsFromDisk(void); // tolua_export
+
+ typedef cWorld * cWorldPtr;
+
+ /** Loads the player data from the disk file
+ Sets a_World to the world where the player will spawn, based on the stored world name or the default world by calling LoadFromFile()
+ Returns true on success, false on failure
+ */
+ bool LoadFromDisk(cWorldPtr & a_World);
+
+ /** Loads the player data from the specified file
+ Sets a_World to the world where the player will spawn, based on the stored world name or the default world
+ Returns true on success, false on failure
+ */
+ bool LoadFromFile(const AString & a_FileName, cWorldPtr & a_World);
+
+ void LoadPermissionsFromDisk(void); // tolua_export
const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
- void UseEquippedItem(void);
+ void UseEquippedItem(int a_Amount = 1);
void SendHealth(void);
void SendExperience(void);
- // In UI windows, the item that the player is dragging:
- bool IsDraggingItem(void) const { return !m_DraggingItem.IsEmpty(); }
+ /** In UI windows, get the item that the player is dragging */
cItem & GetDraggingItem(void) {return m_DraggingItem; }
// In UI windows, when inventory-painting:
@@ -397,11 +405,23 @@ public:
/** If true the player can fly even when he's not in creative. */
void SetCanFly(bool a_CanFly);
+ /** Gets the last position that the player slept in
+ This is initialised to the world spawn point if the player has not slept in a bed as of yet
+ */
+ Vector3i GetLastBedPos(void) const { return m_LastBedPos; }
+
+ /** Sets the player's bed (home) position */
+ void SetBedPos(const Vector3i & a_Pos) { m_LastBedPos = a_Pos; }
+
/** Update movement-related statistics. */
void UpdateMovementStats(const Vector3d & a_DeltaPos);
/** Returns wheter the player can fly or not. */
virtual bool CanFly(void) const { return m_CanFly; }
+
+ /** Returns the UUID (short format) that has been read from the client, or empty string if not available. */
+ const AString & GetUUID(void) const { return m_UUID; }
+
// tolua_end
// cEntity overrides:
@@ -423,7 +443,7 @@ protected:
AString m_LoadedWorldName;
/** Xp Level stuff */
- enum
+ enum
{
XP_TO_LEVEL15 = 255,
XP_PER_LEVEL_TO15 = 17,
@@ -440,14 +460,11 @@ protected:
double m_FoodSaturationLevel;
/** Count-up to the healing or damaging action, based on m_FoodLevel */
- int m_FoodTickTimer;
+ int m_FoodTickTimer;
/** A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel. Each action adds a little */
double m_FoodExhaustionLevel;
- /** Number of ticks remaining for the foodpoisoning effect; zero if not foodpoisoned */
- int m_FoodPoisonedTicksRemaining;
-
float m_LastJumpHeight;
float m_LastGroundHeight;
bool m_bTouchGround;
@@ -462,6 +479,9 @@ protected:
cWindow * m_CurrentWindow;
cWindow * m_InventoryWindow;
+ /** The player's last saved bed position */
+ Vector3i m_LastBedPos;
+
char m_Color;
eGameMode m_GameMode;
@@ -519,6 +539,23 @@ protected:
cStatManager m_Stats;
+ /** Flag representing whether the player is currently in a bed
+ Set by a right click on unoccupied bed, unset by a time fast forward or teleport */
+ bool m_bIsInBed;
+
+ /** How long till the player's inventory will be saved
+ Default save interval is #defined in PLAYER_INVENTORY_SAVE_INTERVAL */
+ unsigned int m_TicksUntilNextSave;
+
+ /** Flag used by food handling system to determine whether a teleport has just happened
+ Will not apply food penalties if found to be true; will set to false after processing
+ */
+ bool m_bIsTeleporting;
+
+ /** The short UUID (no dashes) of the player, as read from the ClientHandle.
+ If no ClientHandle is given, the UUID is initialized to empty. */
+ AString m_UUID;
+
/** Sets the speed and sends it to the client, so that they are forced to move so. */
virtual void DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ) override;
@@ -545,20 +582,10 @@ protected:
/** Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) */
void ApplyFoodExhaustionFromMovement();
- /** Flag representing whether the player is currently in a bed
- Set by a right click on unoccupied bed, unset by a time fast forward or teleport */
- bool m_bIsInBed;
-
- /** How long till the player's inventory will be saved
- Default save interval is #defined in PLAYER_INVENTORY_SAVE_INTERVAL */
- unsigned int m_TicksUntilNextSave;
-
- /** Flag used by food handling system to determine whether a teleport has just happened
- Will not apply food penalties if found to be true; will set to false after processing
- */
- bool m_bIsTeleporting;
-
-} ; // tolua_export
+ /** Returns the filename for the player data based on the UUID given.
+ This can be used both for online and offline UUIDs. */
+ AString GetUUIDFileName(const AString & a_UUID);
+} ; // tolua_export
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index 0bb34019e..43023ec28 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -21,6 +21,8 @@
#include "FireChargeEntity.h"
#include "FireworkEntity.h"
#include "GhastFireballEntity.h"
+#include "WitherSkullEntity.h"
+#include "SplashPotionEntity.h"
#include "Player.h"
@@ -34,7 +36,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProjectileTracerCallback:
class cProjectileTracerCallback :
@@ -121,7 +123,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProjectileEntityCollisionCallback:
class cProjectileEntityCollisionCallback :
@@ -145,9 +147,11 @@ public:
(a_Entity->GetUniqueID() == m_Projectile->GetCreatorUniqueID()) // Do not check whoever shot the projectile
)
{
- // TODO: Don't check creator only for the first 5 ticks
- // so that arrows stuck in ground and dug up can hurt the player
- return false;
+ // Don't check creator only for the first 5 ticks so that projectiles can collide with the creator
+ if (m_Projectile->GetTicksAlive() <= 5)
+ {
+ return false;
+ }
}
cBoundingBox EntBox(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
@@ -210,7 +214,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProjectileEntity:
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) :
@@ -243,7 +247,7 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Ve
-cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem & a_Item, const Vector3d * a_Speed)
+cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem * a_Item, const Vector3d * a_Speed)
{
Vector3d Speed;
if (a_Speed != NULL)
@@ -260,14 +264,17 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator,
case pkGhastFireball: return new cGhastFireballEntity (a_Creator, a_X, a_Y, a_Z, Speed);
case pkFireCharge: return new cFireChargeEntity (a_Creator, a_X, a_Y, a_Z, Speed);
case pkExpBottle: return new cExpBottleEntity (a_Creator, a_X, a_Y, a_Z, Speed);
+ case pkSplashPotion: return new cSplashPotionEntity (a_Creator, a_X, a_Y, a_Z, Speed, *a_Item);
+ case pkWitherSkull: return new cWitherSkullEntity (a_Creator, a_X, a_Y, a_Z, Speed);
case pkFirework:
{
- if (a_Item.m_FireworkItem.m_Colours.empty())
+ ASSERT(a_Item != NULL);
+ if (a_Item->m_FireworkItem.m_Colours.empty())
{
return NULL;
}
- return new cFireworkEntity(a_Creator, a_X, a_Y, a_Z, a_Item);
+ return new cFireworkEntity(a_Creator, a_X, a_Y, a_Z, *a_Item);
}
}
@@ -310,7 +317,7 @@ AString cProjectileEntity::GetMCAClassName(void) const
case pkFireCharge: return "SmallFireball";
case pkEnderPearl: return "ThrownEnderpearl";
case pkExpBottle: return "ThrownExpBottle";
- case pkSplashPotion: return "ThrownPotion";
+ case pkSplashPotion: return "SplashPotion";
case pkWitherSkull: return "WitherSkull";
case pkFirework: return "Firework";
case pkFishingFloat: return ""; // Unknown, perhaps MC doesn't save this?
diff --git a/src/Entities/ProjectileEntity.h b/src/Entities/ProjectileEntity.h
index 7b38169e2..0ebc32f36 100644
--- a/src/Entities/ProjectileEntity.h
+++ b/src/Entities/ProjectileEntity.h
@@ -41,18 +41,18 @@ public:
// tolua_end
- CLASS_PROTODEF(cProjectileEntity);
+ CLASS_PROTODEF(cProjectileEntity)
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
- static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem & a_Item, const Vector3d * a_Speed = NULL);
+ static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem * a_Item, const Vector3d * a_Speed = NULL);
/// Called by the physics blocktracer when the entity hits a solid block, the hit position and the face hit (BLOCK_FACE_) is given
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace);
/// Called by the physics blocktracer when the entity hits another entity
- virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
+ virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
{
UNUSED(a_EntityHit);
UNUSED(a_HitPos);
@@ -89,7 +89,7 @@ public:
protected:
- /** A structure that stores the Entity ID and Playername of the projectile's creator
+ /** A structure that stores the Entity ID and Playername of the projectile's creator
Used to migitate invalid pointers caused by the creator being destroyed
*/
struct CreatorData
@@ -120,4 +120,4 @@ protected:
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
virtual void SpawnOn(cClientHandle & a_Client) override;
-} ; // tolua_export
+} ; // tolua_export
diff --git a/src/Entities/SplashPotionEntity.cpp b/src/Entities/SplashPotionEntity.cpp
new file mode 100644
index 000000000..fd1a0179b
--- /dev/null
+++ b/src/Entities/SplashPotionEntity.cpp
@@ -0,0 +1,134 @@
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "SplashPotionEntity.h"
+#include "Pawn.h"
+#include "../ClientHandle.h"
+
+
+
+
+
+/// Converts an angle in radians into a byte representation used by the network protocol
+#define ANGLE_TO_PROTO(X) (Byte)(X * 255 / 360)
+
+////////////////////////////////////////////////////////////////////////////////
+// cSplashPotionEntityCallback:
+
+/** Used to distribute the splashed potion effect among nearby entities */
+class cSplashPotionCallback :
+ public cEntityCallback
+{
+public:
+ /** Creates the callback.
+ @param a_HitPos The position where the splash potion has splashed
+ @param a_EntityEffectType The effect type of the potion
+ @param a_EntityEffect The effect description */
+ cSplashPotionCallback(const Vector3d & a_HitPos, cEntityEffect::eType a_EntityEffectType, const cEntityEffect & a_EntityEffect) :
+ m_HitPos(a_HitPos),
+ m_EntityEffectType(a_EntityEffectType),
+ m_EntityEffect(a_EntityEffect)
+ {
+ }
+
+ /** Called by cWorld::ForEachEntity(), adds the stored entity effect to the entity, if it is close enough. */
+ virtual bool Item(cEntity * a_Entity) override
+ {
+ if (!a_Entity->IsPawn())
+ {
+ // Not an entity that can take effects
+ return false;
+ }
+
+ double SplashDistance = (a_Entity->GetPosition() - m_HitPos).Length();
+ if (SplashDistance >= 20)
+ {
+ // Too far away
+ return false;
+ }
+
+ // y = -0.25x + 1, where x is the distance from the player. Approximation for potion splash.
+ // TODO: better equation
+ double Reduction = -0.25 * SplashDistance + 1.0;
+ Reduction = std::max(Reduction, 0.0);
+
+ ((cPawn *) a_Entity)->AddEntityEffect(m_EntityEffectType, m_EntityEffect.GetDuration(), m_EntityEffect.GetIntensity(), Reduction);
+ return false;
+ }
+
+private:
+ const Vector3d & m_HitPos;
+ cEntityEffect::eType m_EntityEffectType;
+ const cEntityEffect & m_EntityEffect;
+};
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cSplashPotionEntity:
+
+cSplashPotionEntity::cSplashPotionEntity(
+ cEntity * a_Creator,
+ double a_X, double a_Y, double a_Z,
+ const Vector3d & a_Speed,
+ const cItem & a_Item
+) :
+ super(pkSplashPotion, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25),
+ m_DestroyTimer(-1)
+{
+ SetSpeed(a_Speed);
+ m_EntityEffectType = cEntityEffect::GetPotionEffectType(a_Item.m_ItemDamage);
+ m_EntityEffect = cEntityEffect(
+ cEntityEffect::GetPotionEffectDuration(a_Item.m_ItemDamage),
+ cEntityEffect::GetPotionEffectIntensity(a_Item.m_ItemDamage)
+ );
+ m_PotionColor = cEntityEffect::GetPotionColor(a_Item.m_ItemDamage);
+}
+
+
+
+
+
+void cSplashPotionEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
+{
+ Splash(a_HitPos);
+ m_DestroyTimer = 2;
+}
+
+
+
+
+
+void cSplashPotionEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
+{
+ a_EntityHit.TakeDamage(dtRangedAttack, this, 0, 1);
+ Splash(a_HitPos);
+ m_DestroyTimer = 5;
+}
+
+
+
+
+
+void cSplashPotionEntity::Splash(const Vector3d & a_HitPos)
+{
+ cSplashPotionCallback Callback(a_HitPos, m_EntityEffectType, m_EntityEffect);
+ m_World->ForEachEntity(Callback);
+
+ m_World->BroadcastSoundParticleEffect(2002, (int)floor(a_HitPos.x), (int)floor(a_HitPos.y), (int)floor(a_HitPos.z), m_PotionColor);
+}
+
+
+
+
+
+void cSplashPotionEntity::SpawnOn(cClientHandle & a_Client)
+{
+ a_Client.SendSpawnObject(*this, 73, m_PotionColor, ANGLE_TO_PROTO(GetYaw()), ANGLE_TO_PROTO(GetPitch()));
+ a_Client.SendEntityMetadata(*this);
+}
+
+
+
+
diff --git a/src/Entities/SplashPotionEntity.h b/src/Entities/SplashPotionEntity.h
new file mode 100644
index 000000000..4afc5f204
--- /dev/null
+++ b/src/Entities/SplashPotionEntity.h
@@ -0,0 +1,79 @@
+//
+// SplashPotionEntity.h
+//
+
+#pragma once
+
+#include "ProjectileEntity.h"
+#include "EntityEffect.h"
+#include "../World.h"
+#include "Entity.h"
+
+
+
+
+// tolua_begin
+
+class cSplashPotionEntity :
+ public cProjectileEntity
+{
+ typedef cProjectileEntity super;
+
+public:
+
+ // tolua_end
+
+ CLASS_PROTODEF(cSplashPotionEntity)
+
+ cSplashPotionEntity(
+ cEntity * a_Creator,
+ double a_X, double a_Y, double a_Z,
+ const Vector3d & a_Speed,
+ const cItem & a_Item
+ );
+
+ cEntityEffect::eType GetEntityEffectType(void) const { return m_EntityEffectType; }
+ cEntityEffect GetEntityEffect(void) const { return m_EntityEffect; }
+ int GetPotionColor(void) const { return m_PotionColor; }
+
+ void SetEntityEffectType(cEntityEffect::eType a_EntityEffectType) { m_EntityEffectType = a_EntityEffectType; }
+ void SetEntityEffect(cEntityEffect a_EntityEffect) { m_EntityEffect = a_EntityEffect; }
+ void SetPotionColor(int a_PotionColor) { m_PotionColor = a_PotionColor; }
+
+protected:
+
+ cEntityEffect::eType m_EntityEffectType;
+ cEntityEffect m_EntityEffect;
+ int m_PotionColor;
+
+
+ // cProjectileEntity overrides:
+ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
+ virtual void OnHitEntity (cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
+ virtual void Tick (float a_Dt, cChunk & a_Chunk) override
+ {
+ if (m_DestroyTimer > 0)
+ {
+ m_DestroyTimer--;
+ if (m_DestroyTimer == 0)
+ {
+ Destroy();
+ return;
+ }
+ }
+ else
+ {
+ super::Tick(a_Dt, a_Chunk);
+ }
+ }
+
+ /** Splashes the potion, fires its particle effects and sounds
+ @param a_HitPos The position where the potion will splash */
+ void Splash(const Vector3d & a_HitPos);
+
+ virtual void SpawnOn(cClientHandle & a_Client) override;
+
+private:
+ /** Time in ticks to wait for the hit animation to begin before destroying */
+ int m_DestroyTimer;
+} ; // tolua_export
diff --git a/src/Entities/TNTEntity.cpp b/src/Entities/TNTEntity.cpp
index fd9a4e7ac..53af446cc 100644
--- a/src/Entities/TNTEntity.cpp
+++ b/src/Entities/TNTEntity.cpp
@@ -42,7 +42,7 @@ void cTNTEntity::Explode(void)
{
m_FuseTicks = 0;
Destroy(true);
- LOGD("BOOM at {%f,%f,%f}", GetPosX(), GetPosY(), GetPosZ());
+ LOGD("BOOM at {%f, %f, %f}", GetPosX(), GetPosY(), GetPosZ());
m_World->DoExplosionAt(4.0, GetPosX() + 0.49, GetPosY() + 0.49, GetPosZ() + 0.49, true, esPrimedTNT, this);
}
diff --git a/src/Entities/TNTEntity.h b/src/Entities/TNTEntity.h
index 116f5a8cb..48503cf76 100644
--- a/src/Entities/TNTEntity.h
+++ b/src/Entities/TNTEntity.h
@@ -14,7 +14,7 @@ class cTNTEntity :
public:
// tolua_end
- CLASS_PROTODEF(cTNTEntity);
+ CLASS_PROTODEF(cTNTEntity)
cTNTEntity(double a_X, double a_Y, double a_Z, int a_FuseTicks = 80);
cTNTEntity(const Vector3d & a_Pos, int a_FuseTicks = 80);
@@ -38,7 +38,7 @@ public:
protected:
int m_FuseTicks; ///< How much ticks is left, while the tnt will explode
-}; // tolua_export
+}; // tolua_export
diff --git a/src/Entities/ThrownEggEntity.h b/src/Entities/ThrownEggEntity.h
index dc72c279f..a0b7d5340 100644
--- a/src/Entities/ThrownEggEntity.h
+++ b/src/Entities/ThrownEggEntity.h
@@ -21,7 +21,7 @@ public:
// tolua_end
- CLASS_PROTODEF(cThrownEggEntity);
+ CLASS_PROTODEF(cThrownEggEntity)
cThrownEggEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
@@ -55,4 +55,4 @@ private:
/** Time in ticks to wait for the hit animation to begin before destroying */
int m_DestroyTimer;
-} ; // tolua_export
+} ; // tolua_export
diff --git a/src/Entities/ThrownEnderPearlEntity.h b/src/Entities/ThrownEnderPearlEntity.h
index 1cea5f7d9..436450013 100644
--- a/src/Entities/ThrownEnderPearlEntity.h
+++ b/src/Entities/ThrownEnderPearlEntity.h
@@ -21,7 +21,7 @@ public:
// tolua_end
- CLASS_PROTODEF(cThrownEnderPearlEntity);
+ CLASS_PROTODEF(cThrownEnderPearlEntity)
cThrownEnderPearlEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
@@ -55,4 +55,4 @@ private:
/** Time in ticks to wait for the hit animation to begin before destroying */
int m_DestroyTimer;
-} ; // tolua_export
+} ; // tolua_export
diff --git a/src/Entities/ThrownSnowballEntity.h b/src/Entities/ThrownSnowballEntity.h
index 9a8770379..8d195ced1 100644
--- a/src/Entities/ThrownSnowballEntity.h
+++ b/src/Entities/ThrownSnowballEntity.h
@@ -21,7 +21,7 @@ public:
// tolua_end
- CLASS_PROTODEF(cThrownSnowballEntity);
+ CLASS_PROTODEF(cThrownSnowballEntity)
cThrownSnowballEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
@@ -52,4 +52,4 @@ private:
/** Time in ticks to wait for the hit animation to begin before destroying */
int m_DestroyTimer;
-} ; // tolua_export
+} ; // tolua_export
diff --git a/src/Entities/WitherSkullEntity.cpp b/src/Entities/WitherSkullEntity.cpp
new file mode 100644
index 000000000..a7e774bba
--- /dev/null
+++ b/src/Entities/WitherSkullEntity.cpp
@@ -0,0 +1,49 @@
+
+// WitherSkullEntity.cpp
+
+// Implements the cWitherSkullEntity class representing the entity used by both blue and black wither skulls
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "WitherSkullEntity.h"
+#include "../World.h"
+
+
+
+
+
+cWitherSkullEntity::cWitherSkullEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
+ super(pkWitherSkull, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
+{
+ SetSpeed(a_Speed);
+}
+
+
+
+
+
+void cWitherSkullEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
+{
+ // TODO: Explode
+ // TODO: Apply wither effect to entities nearby
+ Destroy();
+}
+
+
+
+
+
+void cWitherSkullEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
+{
+ // TODO: If entity is Ender Crystal, destroy it
+ a_EntityHit.TakeDamage(dtRangedAttack, this, 0, 1);
+
+ // TODO: Explode
+ // TODO: Apply wither effect to entity and others nearby
+
+ Destroy(true);
+}
+
+
+
+
diff --git a/src/Entities/WitherSkullEntity.h b/src/Entities/WitherSkullEntity.h
new file mode 100644
index 000000000..c59acd807
--- /dev/null
+++ b/src/Entities/WitherSkullEntity.h
@@ -0,0 +1,35 @@
+
+// WitherSkullEntity.h
+
+// Declares the cWitherSkullEntity class representing the entity used by both blue and black wither skulls
+
+#pragma once
+
+#include "ProjectileEntity.h"
+
+
+
+
+
+// tolua_begin
+
+class cWitherSkullEntity :
+public cProjectileEntity
+{
+ typedef cProjectileEntity super;
+
+public:
+
+ // tolua_end
+
+ CLASS_PROTODEF(cWitherSkullEntity)
+
+ cWitherSkullEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed);
+
+protected:
+
+ // cProjectileEntity overrides:
+ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
+ virtual void OnHitEntity (cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
+
+} ; // tolua_export
diff --git a/src/FastRandom.h b/src/FastRandom.h
index 567198a31..2061a3958 100644
--- a/src/FastRandom.h
+++ b/src/FastRandom.h
@@ -44,6 +44,9 @@ public:
/// Returns a random float in the range [0 .. a_Range]; a_Range must be less than 1M; a_Salt is additional source of randomness
float NextFloat(float a_Range, int a_Salt);
+ /** Returns a random float between 0 and 1. */
+ float NextFloat(void) { return NextFloat(1); };
+
/** Returns a random int in the range [a_Begin .. a_End] */
int GenerateRandomInteger(int a_Begin, int a_End);
diff --git a/src/FurnaceRecipe.cpp b/src/FurnaceRecipe.cpp
index 8add9610c..ab772e97b 100644
--- a/src/FurnaceRecipe.cpp
+++ b/src/FurnaceRecipe.cpp
@@ -30,7 +30,7 @@ struct cFurnaceRecipe::sFurnaceRecipeState
cFurnaceRecipe::cFurnaceRecipe()
- : m_pState( new sFurnaceRecipeState )
+ : m_pState( new sFurnaceRecipeState)
{
ReloadRecipes();
}
@@ -107,7 +107,7 @@ void cFurnaceRecipe::AddFuelFromLine(const AString & a_Line, int a_LineNum)
{
// Fuel
int IItemID = 0, IItemCount = 0, IItemHealth = 0, IBurnTime = 0;
- AString::size_type BeginPos = 1; // Begin at one after exclamation mark (bang)
+ AString::size_type BeginPos = 1; // Begin at one after exclamation mark (bang)
if (
!ReadMandatoryNumber(BeginPos, ":", a_Line, a_LineNum, IItemID) || // Read item ID
@@ -133,7 +133,7 @@ void cFurnaceRecipe::AddRecipeFromLine(const AString & a_Line, int a_LineNum)
{
int IItemID = 0, IItemCount = 0, IItemHealth = 0, IBurnTime = 0;
int OItemID = 0, OItemCount = 0, OItemHealth = 0;
- AString::size_type BeginPos = 0; // Begin at start of line
+ AString::size_type BeginPos = 0; // Begin at start of line
if (
!ReadMandatoryNumber(BeginPos, ":", a_Line, a_LineNum, IItemID) || // Read item ID
@@ -193,7 +193,7 @@ bool cFurnaceRecipe::ReadMandatoryNumber(AString::size_type & a_Begin, const ASt
}
a_Value = atoi(a_Text.substr(a_Begin, End - a_Begin).c_str());
- a_Begin = End + 1; // Jump over delimiter
+ a_Begin = End + 1; // Jump over delimiter
return true;
}
@@ -236,7 +236,7 @@ bool cFurnaceRecipe::ReadOptionalNumbers(AString::size_type & a_Begin, const ASt
}
a_ValueTwo = atoi(a_Text.substr(Begin, End - Begin).c_str());
- a_Begin = End + 1; // Jump over delimiter
+ a_Begin = End + 1; // Jump over delimiter
return true;
}
else
diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp
index a17555f37..8fad9f5c9 100644
--- a/src/Generating/BioGen.cpp
+++ b/src/Generating/BioGen.cpp
@@ -12,7 +12,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBiomeGen:
cBiomeGen * cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault)
@@ -78,7 +78,7 @@ cBiomeGen * cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBioGenConstant:
void cBioGenConstant::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap)
@@ -95,7 +95,7 @@ void cBioGenConstant::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap
void cBioGenConstant::InitializeBiomeGen(cIniFile & a_IniFile)
{
- AString Biome = a_IniFile.GetValueSet("Generator", "ConstantBiome", "Plains");
+ AString Biome = a_IniFile.GetValueSet("Generator", "ConstantBiome", "");
m_Biome = StringToBiome(Biome);
if (m_Biome == biInvalidBiome)
{
@@ -108,7 +108,7 @@ void cBioGenConstant::InitializeBiomeGen(cIniFile & a_IniFile)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBioGenCache:
cBioGenCache::cBioGenCache(cBiomeGen * a_BioGenToCache, int a_CacheSize) :
@@ -209,7 +209,7 @@ void cBioGenCache::InitializeBiomeGen(cIniFile & a_IniFile)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBiomeGenList:
void cBiomeGenList::InitializeBiomes(const AString & a_Biomes)
@@ -290,7 +290,7 @@ void cBiomeGenList::InitializeBiomes(const AString & a_Biomes)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBioGenCheckerboard:
void cBioGenCheckerboard::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap)
@@ -324,7 +324,7 @@ void cBioGenCheckerboard::InitializeBiomeGen(cIniFile & a_IniFile)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBioGenVoronoi :
void cBioGenVoronoi::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap)
@@ -357,7 +357,7 @@ void cBioGenVoronoi::InitializeBiomeGen(cIniFile & a_IniFile)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBioGenDistortedVoronoi:
void cBioGenDistortedVoronoi::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap)
@@ -418,7 +418,7 @@ void cBioGenDistortedVoronoi::Distort(int a_BlockX, int a_BlockZ, int & a_Distor
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBioGenMultiStepMap :
cBioGenMultiStepMap::cBioGenMultiStepMap(int a_Seed) :
@@ -739,7 +739,7 @@ void cBioGenMultiStepMap::FreezeWaterBiomes(cChunkDef::BiomeMap & a_BiomeMap, co
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBioGenTwoLevel:
cBioGenTwoLevel::cBioGenTwoLevel(int a_Seed) :
diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt
index 3dacb5066..58df9d421 100644
--- a/src/Generating/CMakeLists.txt
+++ b/src/Generating/CMakeLists.txt
@@ -4,11 +4,64 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ BioGen.cpp
+ Caves.cpp
+ ChunkDesc.cpp
+ ChunkGenerator.cpp
+ CompoGen.cpp
+ ComposableGenerator.cpp
+ DistortedHeightmap.cpp
+ EndGen.cpp
+ FinishGen.cpp
+ GridStructGen.cpp
+ HeiGen.cpp
+ MineShafts.cpp
+ NetherFortGen.cpp
+ Noise3DGenerator.cpp
+ POCPieceGenerator.cpp
+ PieceGenerator.cpp
+ Prefab.cpp
+ PrefabPiecePool.cpp
+ RainbowRoadsGen.cpp
+ Ravines.cpp
+ RoughRavines.cpp
+ StructGen.cpp
+ TestRailsGen.cpp
+ Trees.cpp
+ UnderwaterBaseGen.cpp
+ VillageGen.cpp)
-add_library(Generating ${SOURCE})
+SET (HDRS
+ BioGen.h
+ Caves.h
+ ChunkDesc.h
+ ChunkGenerator.h
+ CompoGen.h
+ ComposableGenerator.h
+ DistortedHeightmap.h
+ EndGen.h
+ FinishGen.h
+ GridStructGen.h
+ HeiGen.h
+ MineShafts.h
+ NetherFortGen.h
+ Noise3DGenerator.h
+ POCPieceGenerator.h
+ PieceGenerator.h
+ Prefab.h
+ PrefabPiecePool.h
+ RainbowRoadsGen.h
+ Ravines.h
+ RoughRavines.h
+ StructGen.h
+ TestRailsGen.h
+ Trees.h
+ UnderwaterBaseGen.h
+ VillageGen.h)
-target_link_libraries(Generating OSSupport iniFile Blocks)
+if(NOT MSVC)
+ add_library(Generating ${SRCS} ${HDRS})
+
+ target_link_libraries(Generating OSSupport iniFile Blocks)
+endif()
diff --git a/src/Generating/Caves.cpp b/src/Generating/Caves.cpp
index 6aa7fd4cb..6fc371958 100644
--- a/src/Generating/Caves.cpp
+++ b/src/Generating/Caves.cpp
@@ -151,7 +151,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCaveTunnel:
cCaveTunnel::cCaveTunnel(
@@ -497,29 +497,9 @@ void cCaveTunnel::ProcessChunk(
int SqDist = (DifX - x) * (DifX - x) + (DifY - y) * (DifY - y) + (DifZ - z) * (DifZ - z);
if (4 * SqDist <= SqRad)
{
- switch (cChunkDef::GetBlock(a_BlockTypes, x, y, z))
+ if (cBlockInfo::CanBeTerraformed(cChunkDef::GetBlock(a_BlockTypes, x, y, z)))
{
- // Only carve out these specific block types
- case E_BLOCK_DIRT:
- case E_BLOCK_GRASS:
- case E_BLOCK_STONE:
- case E_BLOCK_COBBLESTONE:
- case E_BLOCK_GRAVEL:
- case E_BLOCK_SAND:
- case E_BLOCK_SANDSTONE:
- case E_BLOCK_SOULSAND:
- case E_BLOCK_NETHERRACK:
- case E_BLOCK_COAL_ORE:
- case E_BLOCK_IRON_ORE:
- case E_BLOCK_GOLD_ORE:
- case E_BLOCK_DIAMOND_ORE:
- case E_BLOCK_REDSTONE_ORE:
- case E_BLOCK_REDSTONE_ORE_GLOWING:
- {
- cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR);
- break;
- }
- default: break;
+ cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR);
}
}
} // for y
@@ -555,14 +535,14 @@ AString cCaveTunnel::ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) cons
{
AString SVG;
SVG.reserve(m_Points.size() * 20 + 200);
- AppendPrintf(SVG, "<path style=\"fill:none;stroke:#%06x;stroke-width:1px;\"\nd=\"", a_Color);
- char Prefix = 'M'; // The first point needs "M" prefix, all the others need "L"
- for (cCaveDefPoints::const_iterator itr = m_Points.begin(); itr != m_Points.end(); ++itr)
- {
- AppendPrintf(SVG, "%c %d,%d ", Prefix, a_OffsetX + itr->m_BlockX, a_OffsetZ + itr->m_BlockZ);
+ AppendPrintf(SVG, "<path style=\"fill:none;stroke:#%06x;stroke-width:1px;\"\nd=\"", a_Color);
+ char Prefix = 'M'; // The first point needs "M" prefix, all the others need "L"
+ for (cCaveDefPoints::const_iterator itr = m_Points.begin(); itr != m_Points.end(); ++itr)
+ {
+ AppendPrintf(SVG, "%c %d, %d ", Prefix, a_OffsetX + itr->m_BlockX, a_OffsetZ + itr->m_BlockZ);
Prefix = 'L';
- }
- SVG.append("\"/>\n");
+ }
+ SVG.append("\"/>\n");
return SVG;
}
#endif // _DEBUG
@@ -571,7 +551,7 @@ AString cCaveTunnel::ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) cons
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenWormNestCaves::cCaveSystem:
cStructGenWormNestCaves::cCaveSystem::cCaveSystem(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_MaxOffset, int a_Size, cNoise & a_Noise) :
@@ -687,7 +667,7 @@ int cStructGenWormNestCaves::cCaveSystem::GetRadius(cNoise & a_Noise, int a_Orig
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenWormNestCaves:
cGridStructGen::cStructurePtr cStructGenWormNestCaves::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
@@ -700,13 +680,13 @@ cGridStructGen::cStructurePtr cStructGenWormNestCaves::CreateStructure(int a_Gri
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenMarbleCaves:
-static float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise )
+static float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise)
{
static const float PI_2 = 1.57079633f;
- float oct1 = (a_Noise.CubicNoise3D(x * 0.1f, y * 0.1f, z * 0.1f )) * 4;
+ float oct1 = (a_Noise.CubicNoise3D(x * 0.1f, y * 0.1f, z * 0.1f)) * 4;
oct1 = oct1 * oct1 * oct1;
if (oct1 < 0.f) oct1 = PI_2;
@@ -730,7 +710,7 @@ void cStructGenMarbleCaves::GenFinish(cChunkDesc & a_ChunkDesc)
const float xx = (float)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + x);
int Top = a_ChunkDesc.GetHeight(x, z);
- for (int y = 1; y < Top; ++y )
+ for (int y = 1; y < Top; ++y)
{
if (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_STONE)
{
@@ -752,7 +732,7 @@ void cStructGenMarbleCaves::GenFinish(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenDualRidgeCaves:
void cStructGenDualRidgeCaves::GenFinish(cChunkDesc & a_ChunkDesc)
diff --git a/src/Generating/ChunkDesc.cpp b/src/Generating/ChunkDesc.cpp
index 7711723fc..c0b646fd0 100644
--- a/src/Generating/ChunkDesc.cpp
+++ b/src/Generating/ChunkDesc.cpp
@@ -20,7 +20,6 @@ cChunkDesc::cChunkDesc(int a_ChunkX, int a_ChunkZ) :
m_bUseDefaultBiomes(true),
m_bUseDefaultHeight(true),
m_bUseDefaultComposition(true),
- m_bUseDefaultStructures(true),
m_bUseDefaultFinish(true)
{
m_BlockArea.Create(cChunkDef::Width, cChunkDef::Height, cChunkDef::Width);
@@ -207,26 +206,6 @@ bool cChunkDesc::IsUsingDefaultComposition(void) const
-void cChunkDesc::SetUseDefaultStructures(bool a_bUseDefaultStructures)
-{
- LOGWARNING("%s: Structures are no longer accounted for, use Finishers instead", __FUNCTION__);
- m_bUseDefaultStructures = a_bUseDefaultStructures;
-}
-
-
-
-
-
-bool cChunkDesc::IsUsingDefaultStructures(void) const
-{
- LOGWARNING("%s: Structures are no longer accounted for, use Finishers instead", __FUNCTION__);
- return m_bUseDefaultStructures;
-}
-
-
-
-
-
void cChunkDesc::SetUseDefaultFinish(bool a_bUseDefaultFinish)
{
m_bUseDefaultFinish = a_bUseDefaultFinish;
@@ -290,7 +269,7 @@ void cChunkDesc::ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX
LOGWARNING("%s: MaxRelX less than zero, adjusting to zero", __FUNCTION__);
a_MaxRelX = 0;
}
- else if (a_MinRelX >= cChunkDef::Width)
+ else if (a_MaxRelX >= cChunkDef::Width)
{
LOGWARNING("%s: MaxRelX more than chunk width, adjusting to chunk width", __FUNCTION__);
a_MaxRelX = cChunkDef::Width - 1;
@@ -311,7 +290,7 @@ void cChunkDesc::ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX
LOGWARNING("%s: MaxRelY less than zero, adjusting to zero", __FUNCTION__);
a_MaxRelY = 0;
}
- else if (a_MinRelY >= cChunkDef::Height)
+ else if (a_MaxRelY >= cChunkDef::Height)
{
LOGWARNING("%s: MaxRelY more than chunk height, adjusting to chunk height", __FUNCTION__);
a_MaxRelY = cChunkDef::Height - 1;
@@ -332,7 +311,7 @@ void cChunkDesc::ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX
LOGWARNING("%s: MaxRelZ less than zero, adjusting to zero", __FUNCTION__);
a_MaxRelZ = 0;
}
- else if (a_MinRelZ >= cChunkDef::Width)
+ else if (a_MaxRelZ >= cChunkDef::Width)
{
LOGWARNING("%s: MaxRelZ more than chunk width, adjusting to chunk width", __FUNCTION__);
a_MaxRelZ = cChunkDef::Width - 1;
diff --git a/src/Generating/ChunkDesc.h b/src/Generating/ChunkDesc.h
index 8edc2800b..eeea0c957 100644
--- a/src/Generating/ChunkDesc.h
+++ b/src/Generating/ChunkDesc.h
@@ -68,8 +68,6 @@ public:
bool IsUsingDefaultHeight(void) const;
void SetUseDefaultComposition(bool a_bUseDefaultComposition);
bool IsUsingDefaultComposition(void) const;
- void SetUseDefaultStructures(bool a_bUseDefaultStructures);
- bool IsUsingDefaultStructures(void) const;
void SetUseDefaultFinish(bool a_bUseDefaultFinish);
bool IsUsingDefaultFinish(void) const;
@@ -186,7 +184,7 @@ public:
// Accessors used by cChunkGenerator::Generator descendants:
inline cChunkDef::BiomeMap & GetBiomeMap (void) { return m_BiomeMap; }
inline cChunkDef::BlockTypes & GetBlockTypes (void) { return *((cChunkDef::BlockTypes *)m_BlockArea.GetBlockTypes()); }
- // CANNOT, different compression!
+ // CANNOT, different compression!
// inline cChunkDef::BlockNibbles & GetBlockMetas (void) { return *((cChunkDef::BlockNibbles *)m_BlockArea.GetBlockMetas()); }
inline BlockNibbleBytes & GetBlockMetasUncompressed(void) { return *((BlockNibbleBytes *)m_BlockArea.GetBlockMetas()); }
inline cChunkDef::HeightMap & GetHeightMap (void) { return m_HeightMap; }
@@ -214,7 +212,6 @@ private:
bool m_bUseDefaultBiomes;
bool m_bUseDefaultHeight;
bool m_bUseDefaultComposition;
- bool m_bUseDefaultStructures;
bool m_bUseDefaultFinish;
} ; // tolua_export
diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp
index 73f0223e8..3d5af152c 100644
--- a/src/Generating/ChunkGenerator.cpp
+++ b/src/Generating/ChunkGenerator.cpp
@@ -22,7 +22,7 @@ const unsigned int QUEUE_SKIP_LIMIT = 500;
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cChunkGenerator:
cChunkGenerator::cChunkGenerator(void) :
@@ -52,7 +52,7 @@ bool cChunkGenerator::Start(cPluginInterface & a_PluginInterface, cChunkSink & a
m_ChunkSink = &a_ChunkSink;
MTRand rnd;
- m_Seed = a_IniFile.GetValueSetI("Seed", "Seed", rnd.randInt());
+ m_Seed = a_IniFile.GetValueSetI("Seed", "Seed", (int)rnd.randInt());
AString GeneratorName = a_IniFile.GetValueSet("Generator", "Generator", "Composable");
if (NoCaseCompare(GeneratorName, "Noise3D") == 0)
@@ -180,7 +180,7 @@ BLOCKTYPE cChunkGenerator::GetIniBlock(cIniFile & a_IniFile, const AString & a_S
BLOCKTYPE Block = BlockStringToType(BlockType);
if (Block < 0)
{
- LOGWARN("[%s].%s Could not parse block value \"%s\". Using default: \"%s\".", a_SectionName.c_str(), a_ValueName.c_str(), BlockType.c_str(),a_Default.c_str());
+ LOGWARN("[%s].%s Could not parse block value \"%s\". Using default: \"%s\".", a_SectionName.c_str(), a_ValueName.c_str(), BlockType.c_str(), a_Default.c_str());
return BlockStringToType(a_Default);
}
return Block;
@@ -228,10 +228,10 @@ void cChunkGenerator::Execute(void)
continue;
}
- cChunkCoords coords = m_Queue.front(); // Get next coord from queue
- m_Queue.erase( m_Queue.begin() ); // Remove coordinate from queue
+ cChunkCoords coords = m_Queue.front(); // Get next coord from queue
+ m_Queue.erase( m_Queue.begin()); // Remove coordinate from queue
bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT);
- Lock.Unlock(); // Unlock ASAP
+ Lock.Unlock(); // Unlock ASAP
m_evtRemoved.Set();
// Display perf info once in a while:
@@ -290,7 +290,7 @@ void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cChunkGenerator::cGenerator:
cChunkGenerator::cGenerator::cGenerator(cChunkGenerator & a_ChunkGenerator) :
diff --git a/src/Generating/ChunkGenerator.h b/src/Generating/ChunkGenerator.h
index 9b2d9eb3c..88d71f3f9 100644
--- a/src/Generating/ChunkGenerator.h
+++ b/src/Generating/ChunkGenerator.h
@@ -44,7 +44,7 @@ public:
{
public:
cGenerator(cChunkGenerator & a_ChunkGenerator);
- virtual ~cGenerator() {} ; // Force a virtual destructor
+ virtual ~cGenerator() {} // Force a virtual destructor
/// Called to initialize the generator on server startup.
virtual void Initialize(cIniFile & a_IniFile);
diff --git a/src/Generating/CompoGen.cpp b/src/Generating/CompoGen.cpp
index 2da285d72..178673e32 100644
--- a/src/Generating/CompoGen.cpp
+++ b/src/Generating/CompoGen.cpp
@@ -18,7 +18,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompoGenSameBlock:
void cCompoGenSameBlock::ComposeTerrain(cChunkDesc & a_ChunkDesc)
@@ -60,7 +60,7 @@ void cCompoGenSameBlock::InitializeCompoGen(cIniFile & a_IniFile)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompoGenDebugBiomes:
void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc)
@@ -68,7 +68,7 @@ void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc)
static BLOCKTYPE Blocks[] =
{
E_BLOCK_STONE,
- E_BLOCK_COBBLESTONE,
+ E_BLOCK_COBBLESTONE,
E_BLOCK_LOG,
E_BLOCK_PLANKS,
E_BLOCK_SANDSTONE,
@@ -111,7 +111,7 @@ void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompoGenClassic:
cCompoGenClassic::cCompoGenClassic(void) :
@@ -209,7 +209,7 @@ void cCompoGenClassic::InitializeCompoGen(cIniFile & a_IniFile)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompoGenBiomal:
void cCompoGenBiomal::ComposeTerrain(cChunkDesc & a_ChunkDesc)
@@ -526,7 +526,7 @@ void cCompoGenBiomal::FillColumnPattern(int a_RelX, int a_RelZ, int a_Height, cC
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompoGenNether:
cCompoGenNether::cCompoGenNether(int a_Seed) :
@@ -563,7 +563,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc)
{
//*
FloorLo[INTERPOL_X * x + 17 * INTERPOL_Z * z] =
- m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, 0, BaseZ + INTERPOL_Z * z) *
+ m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, 0, BaseZ + INTERPOL_Z * z) *
m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, 0, BaseZ + INTERPOL_Z * z) /
256;
//*/
@@ -628,7 +628,22 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc)
for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
{
a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK);
- a_ChunkDesc.SetBlockType(x, a_ChunkDesc.GetHeight(x, z), z, E_BLOCK_BEDROCK);
+
+ int Height = a_ChunkDesc.GetHeight(x, z);
+ a_ChunkDesc.SetBlockType(x, Height, z, E_BLOCK_BEDROCK);
+
+ NOISE_DATATYPE CeilingDisguise = (m_Noise1.CubicNoise2D((float)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + x) / 10, (float)(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z) / 10));
+ if (CeilingDisguise < 0)
+ {
+ CeilingDisguise = -CeilingDisguise;
+ }
+
+ int CeilingDisguiseHeight = Height - 2 - (int)CeilingDisguise * 3;
+
+ for (int y = Height - 1; y > CeilingDisguiseHeight; y--)
+ {
+ a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_NETHERRACK);
+ }
}
}
@@ -645,7 +660,7 @@ void cCompoGenNether::InitializeCompoGen(cIniFile & a_IniFile)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCompoGenCache:
cCompoGenCache::cCompoGenCache(cTerrainCompositionGen & a_Underlying, int a_CacheSize) :
diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp
index 7b6234161..2f575fe27 100644
--- a/src/Generating/ComposableGenerator.cpp
+++ b/src/Generating/ComposableGenerator.cpp
@@ -26,6 +26,7 @@
#include "POCPieceGenerator.h"
#include "RainbowRoadsGen.h"
#include "Ravines.h"
+#include "RoughRavines.h"
#include "TestRailsGen.h"
#include "UnderwaterBaseGen.h"
#include "VillageGen.h"
@@ -34,7 +35,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cTerrainCompositionGen:
cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_Seed)
@@ -44,7 +45,6 @@ cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile &
{
LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\".");
CompoGenName = "Biomal";
- a_IniFile.SetValue("Generator", "CompositionGen", CompoGenName);
}
cTerrainCompositionGen * res = NULL;
@@ -98,7 +98,6 @@ cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile &
else
{
LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str());
- a_IniFile.DeleteValue("Generator", "CompositionGen");
a_IniFile.SetValue("Generator", "CompositionGen", "Biomal");
return CreateCompositionGen(a_IniFile, a_BiomeGen, a_HeightGen, a_Seed);
}
@@ -114,7 +113,7 @@ cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile &
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cComposableGenerator:
cComposableGenerator::cComposableGenerator(cChunkGenerator & a_ChunkGenerator) :
@@ -234,7 +233,7 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
{
if (CacheSize < 4)
{
- LOGWARNING("Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
+ LOGWARNING("Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
CacheSize, 4
);
CacheSize = 4;
@@ -252,7 +251,7 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile)
{
bool CacheOffByDefault = false;
- m_HeightGen = cTerrainHeightGen::CreateHeightGen(a_IniFile, *m_BiomeGen, m_ChunkGenerator.GetSeed(), CacheOffByDefault);
+ m_HeightGen = cTerrainHeightGen::CreateHeightGen(a_IniFile, *m_BiomeGen, m_ChunkGenerator.GetSeed(), CacheOffByDefault);
// Add a cache, if requested:
int CacheSize = a_IniFile.GetValueSetI("Generator", "HeightGenCacheSize", CacheOffByDefault ? 0 : 64);
@@ -260,7 +259,7 @@ void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile)
{
if (CacheSize < 4)
{
- LOGWARNING("Heightgen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
+ LOGWARNING("Heightgen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
CacheSize, 4
);
CacheSize = 4;
@@ -296,19 +295,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
int Seed = m_ChunkGenerator.GetSeed();
eDimension Dimension = StringToDimension(a_IniFile.GetValue("General", "Dimension", "Overworld"));
- // Older configuration used "Structures" in addition to "Finishers"; we don't distinguish between the two anymore (#398)
- // Therefore, we load Structures from the ini file for compatibility, but move its contents over to Finishers:
- AString Structures = a_IniFile.GetValue("Generator", "Structures", "");
- AString Finishers = a_IniFile.GetValueSet("Generator", "Finishers", "Ravines, WormNestCaves, WaterLakes, LavaLakes, OreNests, Trees, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, PreSimulator");
- if (!Structures.empty())
- {
- LOGINFO("[Generator].Structures is deprecated, moving the contents to [Generator].Finishers.");
- // Structures used to generate before Finishers, so place them first:
- Structures.append(", ");
- Finishers = Structures + Finishers;
- a_IniFile.SetValue("Generator", "Finishers", Finishers);
- }
- a_IniFile.DeleteValue("Generator", "Structures");
+ AString Finishers = a_IniFile.GetValueSet("Generator", "Finishers", "");
// Create all requested finishers:
AStringVector Str = StringSplitAndTrim(Finishers, ",");
@@ -323,7 +310,25 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
}
else if (NoCaseCompare(*itr, "DeadBushes") == 0)
{
- m_FinishGens.push_back(new cFinishGenSingleBiomeSingleTopBlock(Seed, E_BLOCK_DEAD_BUSH, biDesert, 2, E_BLOCK_SAND, E_BLOCK_SAND));
+ // A list with all the allowed biomes.
+ cFinishGenSingleTopBlock::BiomeList AllowedBiomes;
+ AllowedBiomes.push_back(biDesert);
+ AllowedBiomes.push_back(biDesertHills);
+ AllowedBiomes.push_back(biDesertM);
+ AllowedBiomes.push_back(biMesa);
+ AllowedBiomes.push_back(biMesaBryce);
+ AllowedBiomes.push_back(biMesaPlateau);
+ AllowedBiomes.push_back(biMesaPlateauF);
+ AllowedBiomes.push_back(biMesaPlateauFM);
+ AllowedBiomes.push_back(biMesaPlateauM);
+
+ // A list with all the allowed blocks that can be below the dead bush.
+ cFinishGenSingleTopBlock::BlockList AllowedBlocks;
+ AllowedBlocks.push_back(E_BLOCK_SAND);
+ AllowedBlocks.push_back(E_BLOCK_HARDENED_CLAY);
+ AllowedBlocks.push_back(E_BLOCK_STAINED_CLAY);
+
+ m_FinishGens.push_back(new cFinishGenSingleTopBlock(Seed, E_BLOCK_DEAD_BUSH, AllowedBiomes, 2, AllowedBlocks));
}
else if (NoCaseCompare(*itr, "DirectOverhangs") == 0)
{
@@ -370,7 +375,39 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
}
else if (NoCaseCompare(*itr, "Lilypads") == 0)
{
- m_FinishGens.push_back(new cFinishGenSingleBiomeSingleTopBlock(Seed, E_BLOCK_LILY_PAD, biSwampland, 4, E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER));
+ // A list with all the allowed biomes.
+ cFinishGenSingleTopBlock::BiomeList AllowedBiomes;
+ AllowedBiomes.push_back(biSwampland);
+ AllowedBiomes.push_back(biSwamplandM);
+
+ // A list with all the allowed blocks that can be below the lilypad.
+ cFinishGenSingleTopBlock::BlockList AllowedBlocks;
+ AllowedBlocks.push_back(E_BLOCK_WATER);
+ AllowedBlocks.push_back(E_BLOCK_STATIONARY_WATER);
+
+ m_FinishGens.push_back(new cFinishGenSingleTopBlock(Seed, E_BLOCK_LILY_PAD, AllowedBiomes, 4, AllowedBlocks));
+ }
+ else if (NoCaseCompare(*itr, "NaturalPatches") == 0)
+ {
+ cStructGenOreNests::OreList Ores;
+
+ // Dirt vein
+ cStructGenOreNests::OreInfo DirtVein;
+ DirtVein.BlockType = E_BLOCK_DIRT;
+ DirtVein.MaxHeight = 127;
+ DirtVein.NumNests = 20;
+ DirtVein.NestSize = 32;
+ Ores.push_back(DirtVein);
+
+ // Gravel vein
+ cStructGenOreNests::OreInfo GravelVein;
+ GravelVein.BlockType = E_BLOCK_DIRT;
+ GravelVein.MaxHeight = 127;
+ GravelVein.NumNests = 20;
+ GravelVein.NestSize = 32;
+ Ores.push_back(GravelVein);
+
+ m_FinishGens.push_back(new cStructGenOreNests(Seed, Ores, E_BLOCK_STONE));
}
else if (NoCaseCompare(*itr, "NetherClumpFoliage") == 0)
{
@@ -383,9 +420,74 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
int MaxDepth = a_IniFile.GetValueSetI("Generator", "NetherFortsMaxDepth", 12);
m_FinishGens.push_back(new cNetherFortGen(Seed, GridSize, MaxOffset, MaxDepth));
}
+ else if (NoCaseCompare(*itr, "NetherOreNests") == 0)
+ {
+ cStructGenOreNests::OreList Ores;
+
+ // Quartz vein
+ cStructGenOreNests::OreInfo QuartzVein;
+ QuartzVein.BlockType = E_BLOCK_NETHER_QUARTZ_ORE;
+ QuartzVein.MaxHeight = 255;
+ QuartzVein.NumNests = 80;
+ QuartzVein.NestSize = 8;
+ Ores.push_back(QuartzVein);
+
+ m_FinishGens.push_back(new cStructGenOreNests(Seed, Ores, E_BLOCK_NETHERRACK));
+
+ }
else if (NoCaseCompare(*itr, "OreNests") == 0)
{
- m_FinishGens.push_back(new cStructGenOreNests(Seed));
+ cStructGenOreNests::OreList Ores;
+
+ // Coal vein
+ cStructGenOreNests::OreInfo CoalVein;
+ CoalVein.BlockType = E_BLOCK_COAL_ORE;
+ CoalVein.MaxHeight = 127;
+ CoalVein.NumNests = 50;
+ CoalVein.NestSize = 10;
+ Ores.push_back(CoalVein);
+
+ // Iron vein
+ cStructGenOreNests::OreInfo IronVein;
+ IronVein.BlockType = E_BLOCK_IRON_ORE;
+ IronVein.MaxHeight = 64;
+ IronVein.NumNests = 14;
+ IronVein.NestSize = 6;
+ Ores.push_back(IronVein);
+
+ // Gold vein
+ cStructGenOreNests::OreInfo GoldVein;
+ GoldVein.BlockType = E_BLOCK_GOLD_ORE;
+ GoldVein.MaxHeight = 32;
+ GoldVein.NumNests = 2;
+ GoldVein.NestSize = 6;
+ Ores.push_back(GoldVein);
+
+ // Redstone vein
+ cStructGenOreNests::OreInfo RedstoneVein;
+ RedstoneVein.BlockType = E_BLOCK_REDSTONE_ORE;
+ RedstoneVein.MaxHeight = 16;
+ RedstoneVein.NumNests = 4;
+ RedstoneVein.NestSize = 6;
+ Ores.push_back(RedstoneVein);
+
+ // Lapis vein
+ cStructGenOreNests::OreInfo LapisVein;
+ LapisVein.BlockType = E_BLOCK_LAPIS_ORE;
+ LapisVein.MaxHeight = 30;
+ LapisVein.NumNests = 2;
+ LapisVein.NestSize = 5;
+ Ores.push_back(LapisVein);
+
+ // Diamond vein
+ cStructGenOreNests::OreInfo DiamondVein;
+ DiamondVein.BlockType = E_BLOCK_DIAMOND_ORE;
+ DiamondVein.MaxHeight = 15;
+ DiamondVein.NumNests = 1;
+ DiamondVein.NestSize = 4;
+ Ores.push_back(DiamondVein);
+
+ m_FinishGens.push_back(new cStructGenOreNests(Seed, Ores, E_BLOCK_STONE));
}
else if (NoCaseCompare(*itr, "POCPieces") == 0)
{
@@ -393,20 +495,54 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
}
else if (NoCaseCompare(*itr, "PreSimulator") == 0)
{
- m_FinishGens.push_back(new cFinishGenPreSimulator);
+ // Load the settings
+ bool PreSimulateFallingBlocks = a_IniFile.GetValueSetB("Generator", "PreSimulatorFallingBlocks", true);
+ bool PreSimulateWater = a_IniFile.GetValueSetB("Generator", "PreSimulatorWater", true);
+ bool PreSimulateLava = a_IniFile.GetValueSetB("Generator", "PreSimulatorLava", true);
+
+ m_FinishGens.push_back(new cFinishGenPreSimulator(PreSimulateFallingBlocks, PreSimulateWater, PreSimulateLava));
}
else if (NoCaseCompare(*itr, "RainbowRoads") == 0)
{
- int GridSize = a_IniFile.GetValueSetI("Generator", "RainbowRoadsGridSize", 512);
+ int GridSize = a_IniFile.GetValueSetI("Generator", "RainbowRoadsGridSize", 512);
int MaxOffset = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxOffset", 128);
- int MaxDepth = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxDepth", 30);
- int MaxSize = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxSize", 260);
+ int MaxDepth = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxDepth", 30);
+ int MaxSize = a_IniFile.GetValueSetI("Generator", "RainbowRoadsMaxSize", 260);
m_FinishGens.push_back(new cRainbowRoadsGen(Seed, GridSize, MaxOffset, MaxDepth, MaxSize));
}
else if (NoCaseCompare(*itr, "Ravines") == 0)
{
m_FinishGens.push_back(new cStructGenRavines(Seed, 128));
}
+ else if (NoCaseCompare(*itr, "RoughRavines") == 0)
+ {
+ int GridSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesGridSize", 256);
+ int MaxOffset = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxOffset", 128);
+ int MaxSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMaxSize", 128);
+ int MinSize = a_IniFile.GetValueSetI("Generator", "RoughRavinesMinSize", 64);
+ double MaxCenterWidth = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCenterWidth", 8);
+ double MinCenterWidth = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCenterWidth", 2);
+ double MaxRoughness = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxRoughness", 0.2);
+ double MinRoughness = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinRoughness", 0.05);
+ double MaxFloorHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxFloorHeightEdge", 8);
+ double MinFloorHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinFloorHeightEdge", 30);
+ double MaxFloorHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxFloorHeightCenter", 20);
+ double MinFloorHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinFloorHeightCenter", 6);
+ double MaxCeilingHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCeilingHeightEdge", 56);
+ double MinCeilingHeightEdge = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCeilingHeightEdge", 38);
+ double MaxCeilingHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMaxCeilingHeightCenter", 58);
+ double MinCeilingHeightCenter = a_IniFile.GetValueSetF("Generator", "RoughRavinesMinCeilingHeightCenter", 36);
+ m_FinishGens.push_back(new cRoughRavines(
+ Seed, MaxSize, MinSize,
+ (float)MaxCenterWidth, (float)MinCenterWidth,
+ (float)MaxRoughness, (float)MinRoughness,
+ (float)MaxFloorHeightEdge, (float)MinFloorHeightEdge,
+ (float)MaxFloorHeightCenter, (float)MinFloorHeightCenter,
+ (float)MaxCeilingHeightEdge, (float)MinCeilingHeightEdge,
+ (float)MaxCeilingHeightCenter, (float)MinCeilingHeightCenter,
+ GridSize, MaxOffset
+ ));
+ }
else if (NoCaseCompare(*itr, "Snow") == 0)
{
m_FinishGens.push_back(new cFinishGenSnow);
@@ -415,6 +551,10 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
{
m_FinishGens.push_back(new cFinishGenSprinkleFoliage(Seed));
}
+ else if (NoCaseCompare(*itr, "TallGrass") == 0)
+ {
+ m_FinishGens.push_back(new cFinishGenTallGrass(Seed));
+ }
else if (NoCaseCompare(*itr, "TestRails") == 0)
{
m_FinishGens.push_back(new cTestRailsGen(Seed, 100, 1, 7, 50));
diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp
index eb9fe92ba..c18c402da 100644
--- a/src/Generating/DistortedHeightmap.cpp
+++ b/src/Generating/DistortedHeightmap.cpp
@@ -14,7 +14,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cPattern:
/// This class is used to store a column pattern initialized at runtime,
@@ -50,7 +50,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// The arrays to use for the top block pattern definitions:
static cDistortedHeightmap::sBlockInfo tbGrass[] =
@@ -119,7 +119,7 @@ static cDistortedHeightmap::sBlockInfo tbStone[] =
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Ocean floor pattern top-block definitions:
static cDistortedHeightmap::sBlockInfo tbOFSand[] =
@@ -151,7 +151,7 @@ static cDistortedHeightmap::sBlockInfo tbOFRedSand[] =
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Individual patterns to use:
static cPattern patGrass (tbGrass, ARRAYCOUNT(tbGrass));
@@ -171,7 +171,7 @@ static cPattern patOFRedSand(tbOFRedSand, ARRAYCOUNT(tbOFRedSand));
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cDistortedHeightmap:
/** This table assigns a relative maximum overhang size in each direction to biomes.
@@ -675,6 +675,8 @@ void cDistortedHeightmap::ComposeColumn(cChunkDesc & a_ChunkDesc, int a_RelX, in
case biForestHills:
case biTaigaHills:
case biExtremeHillsEdge:
+ case biExtremeHillsPlus:
+ case biExtremeHills:
case biJungle:
case biJungleHills:
case biJungleEdge:
@@ -750,18 +752,6 @@ void cDistortedHeightmap::ComposeColumn(cChunkDesc & a_ChunkDesc, int a_RelX, in
return;
}
- case biExtremeHillsPlus:
- case biExtremeHills:
- {
- // Select the pattern to use - stone or grass:
- NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(m_CurChunkX * cChunkDef::Width + a_RelX)) / FrequencyX;
- NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(m_CurChunkZ * cChunkDef::Width + a_RelZ)) / FrequencyZ;
- NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY);
- const sBlockInfo * Pattern = (Val < -0.1) ? patStone.Get() : patGrass.Get();
- FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern);
- return;
- }
-
case biExtremeHillsPlusM:
case biExtremeHillsM:
{
@@ -769,7 +759,7 @@ void cDistortedHeightmap::ComposeColumn(cChunkDesc & a_ChunkDesc, int a_RelX, in
NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(m_CurChunkX * cChunkDef::Width + a_RelX)) / FrequencyX;
NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(m_CurChunkZ * cChunkDef::Width + a_RelZ)) / FrequencyZ;
NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY);
- const sBlockInfo * Pattern = (Val < -0.9) ? patStone.Get() : ((Val > 0) ? patGravel.Get() : patGrass.Get());
+ const sBlockInfo * Pattern = (Val < 0.0) ? patStone.Get() : patGrass.Get();
FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern);
return;
}
@@ -819,7 +809,7 @@ void cDistortedHeightmap::FillColumnPattern(cChunkDesc & a_ChunkDesc, int a_RelX
}
// Select the ocean-floor pattern to use:
- a_Pattern = ChooseOceanFloorPattern(a_RelX, a_RelZ);
+ a_Pattern = a_ChunkDesc.GetBiome(a_RelX, a_RelZ) == biDeepOcean ? patGravel.Get() : ChooseOceanFloorPattern(a_RelX, a_RelZ);
HasHadWater = true;
} // for y
a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK);
diff --git a/src/Generating/EndGen.cpp b/src/Generating/EndGen.cpp
index f466039b9..c94cd1eff 100644
--- a/src/Generating/EndGen.cpp
+++ b/src/Generating/EndGen.cpp
@@ -29,7 +29,7 @@ enum
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cEndGen:
cEndGen::cEndGen(int a_Seed) :
@@ -50,7 +50,7 @@ cEndGen::cEndGen(int a_Seed) :
-void cEndGen::Initialize(cIniFile & a_IniFile)
+void cEndGen::InitializeCompoGen(cIniFile & a_IniFile)
{
m_IslandSizeX = a_IniFile.GetValueSetI("Generator", "EndGenIslandSizeX", m_IslandSizeX);
m_IslandSizeY = a_IniFile.GetValueSetI("Generator", "EndGenIslandSizeY", m_IslandSizeY);
diff --git a/src/Generating/EndGen.h b/src/Generating/EndGen.h
index 4904a0e3d..322061810 100644
--- a/src/Generating/EndGen.h
+++ b/src/Generating/EndGen.h
@@ -23,8 +23,6 @@ class cEndGen :
public:
cEndGen(int a_Seed);
- void Initialize(cIniFile & a_IniFile);
-
protected:
/// Seed for the noise
@@ -66,4 +64,5 @@ protected:
// cTerrainCompositionGen overrides:
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override;
+ virtual void InitializeCompoGen(cIniFile & a_IniFile) override;
} ;
diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp
index f2d66af70..eb57a5faa 100644
--- a/src/Generating/FinishGen.cpp
+++ b/src/Generating/FinishGen.cpp
@@ -40,47 +40,19 @@ static inline bool IsWater(BLOCKTYPE a_BlockType)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFinishGenNetherClumpFoliage:
void cFinishGenNetherClumpFoliage::GenFinish(cChunkDesc & a_ChunkDesc)
{
- double ChunkX = a_ChunkDesc.GetChunkX() + 0.1; // We can't devide through 0 so lets add 0.1 to all the chunk coordinates.
- double ChunkZ = a_ChunkDesc.GetChunkZ() + 0.1;
-
- NOISE_DATATYPE Val1 = m_Noise.CubicNoise2D((float) (ChunkX * ChunkZ * 0.01f), (float) (ChunkZ / ChunkX * 0.01f));
- NOISE_DATATYPE Val2 = m_Noise.CubicNoise2D((float) (ChunkX / ChunkZ / 0.01f), (float) (ChunkZ * ChunkX / 0.01f));
+ int ChunkX = a_ChunkDesc.GetChunkX();
+ int ChunkZ = a_ChunkDesc.GetChunkZ();
- if (Val1 < 0)
- {
- Val1 = -Val1;
- }
-
- if (Val2 < 0)
- {
- Val2 = -Val2;
- }
+ int Val1 = m_Noise.IntNoise2DInt(ChunkX ^ ChunkZ, ChunkZ + ChunkX);
+ int Val2 = m_Noise.IntNoise2DInt(ChunkZ ^ ChunkX, ChunkZ - ChunkX);
- int PosX, PosZ;
- // Calculate PosX
- if (Val1 <= 1)
- {
- PosX = (int) floor(Val1 * 16);
- }
- else
- {
- PosX = (int) floor(16 / Val1);
- }
-
- // Calculate PosZ
- if (Val2 <= 1)
- {
- PosZ = (int) floor(Val2 * 16);
- }
- else
- {
- PosZ = (int) floor(16 / Val2);
- }
+ int PosX = Val1 % 16;
+ int PosZ = Val2 % 16;
for (int y = 1; y < cChunkDef::Height; y++)
{
@@ -88,12 +60,14 @@ void cFinishGenNetherClumpFoliage::GenFinish(cChunkDesc & a_ChunkDesc)
{
continue;
}
+
if (!cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(PosX, y - 1, PosZ))) // Only place on solid blocks
{
continue;
}
- NOISE_DATATYPE BlockType = m_Noise.CubicNoise1D((float) (ChunkX * ChunkZ) / (y * 0.1f));
+ // Choose what block to use.
+ NOISE_DATATYPE BlockType = m_Noise.IntNoise3D((int) ChunkX, y, (int) ChunkZ);
if (BlockType < -0.7)
{
TryPlaceClump(a_ChunkDesc, PosX, y, PosZ, E_BLOCK_BROWN_MUSHROOM);
@@ -117,26 +91,71 @@ void cFinishGenNetherClumpFoliage::TryPlaceClump(cChunkDesc & a_ChunkDesc, int a
{
bool IsFireBlock = a_Block == E_BLOCK_FIRE;
- for (int x = a_RelX - 4; x < a_RelX + 4; x++)
+ int MinX = a_RelX - 4;
+ if (MinX < 0) // Check if the coordinate is outside the chunk. If it it then adjust it.
{
- float xx = (float) a_ChunkDesc.GetChunkX() * cChunkDef::Width + x;
- for (int z = a_RelZ - 4; z < a_RelZ + 4; z++)
+ MinX = 0;
+ }
+
+ int MaxX = a_RelX + 4;
+ if (MaxX > cChunkDef::Width) // Check if the coordinate is outside the chunk. If it it then adjust it.
+ {
+ MaxX = cChunkDef::Width;
+ }
+
+ int MinZ = a_RelZ - 4;
+ if (MinZ < 0) // Check if the coordinate is outside the chunk. If it it then adjust it.
+ {
+ MinZ = 0;
+ }
+
+ int MaxZ = a_RelZ + 4;
+ if (MaxZ > cChunkDef::Width) // Check if the coordinate is outside the chunk. If it it then adjust it.
+ {
+ MaxZ = cChunkDef::Width;
+ }
+
+ int MinY = a_RelY - 2;
+ if (MinY < 0) // Check if the coordinate is outside the chunk. If it it then adjust it.
+ {
+ MinY = 0;
+ }
+
+ int MaxY = a_RelY + 2;
+ if (MaxY > cChunkDef::Height) // Check if the coordinate is outside the chunk. If it it then adjust it.
+ {
+ MaxY = cChunkDef::Height;
+ }
+
+ for (int x = MinX; x < MaxX; x++)
+ {
+ int xx = a_ChunkDesc.GetChunkX() * cChunkDef::Width + x;
+ for (int z = MinZ; z < MaxZ; z++)
{
- float zz = (float) a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z;
- for (int y = a_RelY - 2; y < a_RelY + 2; y++)
+ int zz = a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z;
+ for (int y = MinY; y < MaxY; y++)
{
- if (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_AIR) // Don't replace non air blocks.
+ if (
+ ((x < 0) || (x >= cChunkDef::Width)) ||
+ ((y < 0) || (y >= cChunkDef::Height)) ||
+ ((z < 0) || (z >= cChunkDef::Width))
+ )
+ {
+ continue;
+ }
+
+ if (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_AIR) // Don't replace non air blocks.
{
continue;
}
BLOCKTYPE BlockBelow = a_ChunkDesc.GetBlockType(x, y - 1, z);
- if (!cBlockInfo::IsSolid(BlockBelow)) // Only place on solid blocks
+ if (!cBlockInfo::FullyOccupiesVoxel(BlockBelow)) // Only place on solid blocks
{
continue;
}
- if (IsFireBlock) // don't place fire on non-forever burning blocks.
+ if (IsFireBlock) // don't place fire on non-forever burning blocks.
{
if (!cFireSimulator::DoesBurnForever(BlockBelow))
{
@@ -144,9 +163,8 @@ void cFinishGenNetherClumpFoliage::TryPlaceClump(cChunkDesc & a_ChunkDesc, int a
}
}
-
- NOISE_DATATYPE Val = m_Noise.CubicNoise2D(xx, zz);
- if (Val < -0.70)
+ NOISE_DATATYPE Val = m_Noise.IntNoise2D(xx, zz);
+ if (Val < -0.5)
{
a_ChunkDesc.SetBlockType(x, y, z, a_Block);
}
@@ -159,7 +177,66 @@ void cFinishGenNetherClumpFoliage::TryPlaceClump(cChunkDesc & a_ChunkDesc, int a
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// cFinishGenTallGrass:
+
+void cFinishGenTallGrass::GenFinish(cChunkDesc & a_ChunkDesc)
+{
+ for (int x = 0; x < cChunkDef::Width; x++)
+ {
+ int xx = x + a_ChunkDesc.GetChunkX() * cChunkDef::Width;
+ for (int z = 0; z < cChunkDef::Width; z++)
+ {
+ int zz = z + a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
+ int BiomeDensity = GetBiomeDensity(a_ChunkDesc.GetBiome(x, z));
+
+ // Choose if we want to place long grass here. If not then bail out:
+ if ((m_Noise.IntNoise2DInt(xx + m_Noise.IntNoise1DInt(xx), zz + m_Noise.IntNoise1DInt(zz)) / 7 % 100) > BiomeDensity)
+ {
+ continue;
+ }
+
+ // Get the top block + 1. This is the place where the grass would finaly be placed:
+ int y = a_ChunkDesc.GetHeight(x, z) + 1;
+
+ // Check if long grass can be placed:
+ if (
+ (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_AIR) ||
+ ((a_ChunkDesc.GetBlockType(x, y - 1, z) != E_BLOCK_GRASS) && (a_ChunkDesc.GetBlockType(x, y - 1, z) != E_BLOCK_DIRT))
+ )
+ {
+ continue;
+ }
+
+ // Choose what long grass meta we should use:
+ int GrassType = m_Noise.IntNoise2DInt(xx * 50, zz * 50) / 7 % 100;
+ if (GrassType < 60)
+ {
+ a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_TALL_GRASS, 1);
+ }
+ else if (GrassType < 90)
+ {
+ a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_TALL_GRASS, 2);
+ }
+ else
+ {
+ // If double long grass we have to choose what type we should use:
+ if (a_ChunkDesc.GetBlockType(x, y + 1, z) == E_BLOCK_AIR)
+ {
+ NIBBLETYPE Meta = (m_Noise.IntNoise2DInt(xx * 100, zz * 100) / 7 % 100) > 25 ? 2 : 3;
+ a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_BIG_FLOWER, Meta);
+ a_ChunkDesc.SetBlockTypeMeta(x, y + 1, z, E_BLOCK_BIG_FLOWER, 8);
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
// cFinishGenSprinkleFoliage:
bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ)
@@ -193,8 +270,8 @@ bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_
if (
!IsWater(a_ChunkDesc.GetBlockType(a_RelX - 1, a_RelY, a_RelZ)) &&
!IsWater(a_ChunkDesc.GetBlockType(a_RelX + 1, a_RelY, a_RelZ)) &&
- !IsWater(a_ChunkDesc.GetBlockType(a_RelX , a_RelY, a_RelZ - 1)) &&
- !IsWater(a_ChunkDesc.GetBlockType(a_RelX , a_RelY, a_RelZ + 1))
+ !IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ - 1)) &&
+ !IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ + 1))
)
{
return false;
@@ -214,7 +291,7 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc)
// Generate small foliage (1-block):
// TODO: Update heightmap with 1-block-tall foliage
- for (int z = 0; z < cChunkDef::Width; z++)
+ for (int z = 0; z < cChunkDef::Width; z++)
{
int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width + z;
const float zz = (float)BlockZ;
@@ -239,14 +316,14 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc)
}
const float xx = (float)BlockX;
- float val1 = m_Noise.CubicNoise2D(xx * 0.1f, zz * 0.1f );
- float val2 = m_Noise.CubicNoise2D(xx * 0.01f, zz * 0.01f );
+ float val1 = m_Noise.CubicNoise2D(xx * 0.1f, zz * 0.1f);
+ float val2 = m_Noise.CubicNoise2D(xx * 0.01f, zz * 0.01f);
switch (a_ChunkDesc.GetBlockType(x, Top, z))
{
case E_BLOCK_GRASS:
{
- float val3 = m_Noise.CubicNoise2D(xx * 0.01f + 10, zz * 0.01f + 10 );
- float val4 = m_Noise.CubicNoise2D(xx * 0.05f + 20, zz * 0.05f + 20 );
+ float val3 = m_Noise.CubicNoise2D(xx * 0.01f + 10, zz * 0.01f + 10);
+ float val4 = m_Noise.CubicNoise2D(xx * 0.05f + 20, zz * 0.05f + 20);
if (val1 + val2 > 0.2f)
{
a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_YELLOW_FLOWER);
@@ -309,7 +386,7 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFinishGenSnow:
void cFinishGenSnow::GenFinish(cChunkDesc & a_ChunkDesc)
@@ -345,7 +422,7 @@ void cFinishGenSnow::GenFinish(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFinishGenIce:
void cFinishGenIce::GenFinish(cChunkDesc & a_ChunkDesc)
@@ -385,15 +462,15 @@ void cFinishGenIce::GenFinish(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cFinishGenLilypads:
+////////////////////////////////////////////////////////////////////////////////
+// cFinishGenSingleTopBlock:
-int cFinishGenSingleBiomeSingleTopBlock::GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap)
+int cFinishGenSingleTopBlock::GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap)
{
int res = 0;
for (size_t i = 0; i < ARRAYCOUNT(a_BiomeMap); i++)
{
- if (a_BiomeMap[i] == m_Biome)
+ if (IsAllowedBiome(a_BiomeMap[i]))
{
res++;
}
@@ -405,10 +482,8 @@ int cFinishGenSingleBiomeSingleTopBlock::GetNumToGen(const cChunkDef::BiomeMap &
-void cFinishGenSingleBiomeSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc)
+void cFinishGenSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc)
{
- // Add Lilypads on top of water surface in Swampland
-
int NumToGen = GetNumToGen(a_ChunkDesc.GetBiomeMap());
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
@@ -418,11 +493,13 @@ void cFinishGenSingleBiomeSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc)
int z = (m_Noise.IntNoise3DInt(ChunkX - ChunkZ, i, ChunkZ) / 11) % cChunkDef::Width;
// Place the block at {x, z} if possible:
- if (a_ChunkDesc.GetBiome(x, z) != m_Biome)
+ EMCSBiome Biome = a_ChunkDesc.GetBiome(x, z);
+ if (!IsAllowedBiome(Biome))
{
// Incorrect biome
continue;
}
+
int Height = a_ChunkDesc.GetHeight(x, z);
if (Height >= cChunkDef::Height)
{
@@ -434,20 +511,23 @@ void cFinishGenSingleBiomeSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc)
// Not an empty block
continue;
}
+
BLOCKTYPE BlockBelow = a_ChunkDesc.GetBlockType(x, Height, z);
- if ((BlockBelow == m_AllowedBelow1) || (BlockBelow == m_AllowedBelow2))
+ if (!IsAllowedBlockBelow(BlockBelow))
{
- a_ChunkDesc.SetBlockType(x, Height + 1, z, m_BlockType);
- a_ChunkDesc.SetHeight(x, z, Height + 1);
+ continue;
}
- } // for i
+
+ a_ChunkDesc.SetBlockType(x, Height + 1, z, m_BlockType);
+ a_ChunkDesc.SetHeight(x, z, Height + 1);
+ }
}
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFinishGenBottomLava:
void cFinishGenBottomLava::GenFinish(cChunkDesc & a_ChunkDesc)
@@ -470,10 +550,13 @@ void cFinishGenBottomLava::GenFinish(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFinishGenPreSimulator:
-cFinishGenPreSimulator::cFinishGenPreSimulator(void)
+cFinishGenPreSimulator::cFinishGenPreSimulator(bool a_PreSimulateFallingBlocks, bool a_PreSimulateWater, bool a_PreSimulateLava) :
+ m_PreSimulateFallingBlocks(a_PreSimulateFallingBlocks),
+ m_PreSimulateWater(a_PreSimulateWater),
+ m_PreSimulateLava(a_PreSimulateLava)
{
// Nothing needed yet
}
@@ -484,9 +567,20 @@ cFinishGenPreSimulator::cFinishGenPreSimulator(void)
void cFinishGenPreSimulator::GenFinish(cChunkDesc & a_ChunkDesc)
{
- CollapseSandGravel(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap());
- StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER);
- StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA);
+ if (m_PreSimulateFallingBlocks)
+ {
+ CollapseSandGravel(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap());
+ }
+
+ if (m_PreSimulateWater)
+ {
+ StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER);
+ }
+
+ if (m_PreSimulateLava)
+ {
+ StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA);
+ }
// TODO: other operations
}
@@ -637,7 +731,7 @@ void cFinishGenPreSimulator::StationarizeFluid(
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFinishGenFluidSprings:
cFinishGenFluidSprings::cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cIniFile & a_IniFile, eDimension a_Dimension) :
@@ -678,7 +772,7 @@ cFinishGenFluidSprings::cFinishGenFluidSprings(int a_Seed, BLOCKTYPE a_Fluid, cI
AString HeightDistribution = a_IniFile.GetValueSet(SectionName, "HeightDistribution", DefaultHeightDistribution);
if (!m_HeightDistribution.SetDefString(HeightDistribution) || (m_HeightDistribution.GetSum() <= 0))
{
- LOGWARNING("[%sSprings]: HeightDistribution is invalid, using the default of \"%s\".",
+ LOGWARNING("[%sSprings]: HeightDistribution is invalid, using the default of \"%s\".",
(a_Fluid == E_BLOCK_WATER) ? "Water" : "Lava",
DefaultHeightDistribution.c_str()
);
diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h
index 2e5732929..4a08d70c8 100644
--- a/src/Generating/FinishGen.h
+++ b/src/Generating/FinishGen.h
@@ -69,6 +69,54 @@ protected:
+class cFinishGenTallGrass :
+ public cFinishGen
+{
+public:
+ cFinishGenTallGrass(int a_Seed) : m_Noise(a_Seed), m_Seed(a_Seed) {}
+
+protected:
+ cNoise m_Noise;
+ int m_Seed;
+
+ // cFinishGen override:
+ virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
+
+ int GetBiomeDensity(EMCSBiome a_Biome)
+ {
+ switch (a_Biome)
+ {
+ case biSavanna:
+ case biSavannaM:
+ case biSavannaPlateau:
+ case biSavannaPlateauM:
+ case biPlains:
+ {
+ return 70;
+ }
+
+ case biExtremeHillsEdge:
+ case biExtremeHillsPlus:
+ case biExtremeHills:
+ case biExtremeHillsPlusM:
+ case biExtremeHillsM:
+ case biIceMountains:
+ {
+ return 3;
+ }
+
+ default:
+ {
+ return 20;
+ }
+ }
+ }
+};
+
+
+
+
+
class cFinishGenSprinkleFoliage :
public cFinishGen
{
@@ -95,32 +143,69 @@ Used for:
- Lilypads finisher
- DeadBushes finisher
*/
-class cFinishGenSingleBiomeSingleTopBlock :
+class cFinishGenSingleTopBlock :
public cFinishGen
{
public:
- cFinishGenSingleBiomeSingleTopBlock(
- int a_Seed, BLOCKTYPE a_BlockType, EMCSBiome a_Biome, int a_Amount,
- BLOCKTYPE a_AllowedBelow1, BLOCKTYPE a_AllowedBelow2
+ typedef std::vector<BLOCKTYPE> BlockList;
+ bool m_IsAllowedBelow[256];
+
+ typedef std::vector<EMCSBiome> BiomeList;
+ bool m_IsBiomeAllowed[256];
+
+
+ cFinishGenSingleTopBlock(
+ int a_Seed, BLOCKTYPE a_BlockType, BiomeList a_Biomes, int a_Amount,
+ BlockList a_AllowedBelow
) :
m_Noise(a_Seed),
m_BlockType(a_BlockType),
- m_Biome(a_Biome),
- m_Amount(a_Amount),
- m_AllowedBelow1(a_AllowedBelow1),
- m_AllowedBelow2(a_AllowedBelow2)
+ m_Amount(a_Amount)
{
+ // Initialize all the block types.
+ for (size_t idx = 0; idx < ARRAYCOUNT(m_IsAllowedBelow); ++idx)
+ {
+ m_IsAllowedBelow[idx] = false;
+ }
+
+ // Load the allowed blocks into m_IsAllowedBelow
+ for (BlockList::iterator itr = a_AllowedBelow.begin(); itr != a_AllowedBelow.end(); ++itr)
+ {
+ m_IsAllowedBelow[*itr] = true;
+ }
+
+ // Initialize all the biome types.
+ for (size_t idx = 0; idx < ARRAYCOUNT(m_IsBiomeAllowed); ++idx)
+ {
+ m_IsBiomeAllowed[idx] = false;
+ }
+
+ // Load the allowed biomes into m_IsBiomeAllowed
+ for (BiomeList::iterator itr = a_Biomes.begin(); itr != a_Biomes.end(); ++itr)
+ {
+ m_IsBiomeAllowed[*itr] = true;
+ }
}
protected:
cNoise m_Noise;
BLOCKTYPE m_BlockType;
- EMCSBiome m_Biome;
int m_Amount; ///< Relative amount of blocks to try adding. 1 = one block per 256 biome columns.
- BLOCKTYPE m_AllowedBelow1; ///< First of the two blocktypes that are allowed below m_BlockType
- BLOCKTYPE m_AllowedBelow2; ///< Second of the two blocktypes that are allowed below m_BlockType
int GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap);
+
+ // Returns true if the given biome is a biome that is allowed.
+ inline bool IsAllowedBiome(EMCSBiome a_Biome)
+ {
+ return m_IsBiomeAllowed[a_Biome];
+ }
+
+ // Returns true if the given blocktype may be below m_BlockType
+ inline bool IsAllowedBlockBelow(BLOCKTYPE a_BlockBelow)
+ {
+ return m_IsAllowedBelow[a_BlockBelow];
+ }
+
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
@@ -155,9 +240,14 @@ class cFinishGenPreSimulator :
public cFinishGen
{
public:
- cFinishGenPreSimulator(void);
+ cFinishGenPreSimulator(bool a_PreSimulateFallingBlocks, bool a_PreSimulateWater, bool a_PreSimulateLava);
protected:
+
+ bool m_PreSimulateFallingBlocks;
+ bool m_PreSimulateWater;
+ bool m_PreSimulateLava;
+
// Drops hanging sand and gravel down to the ground, recalculates heightmap
void CollapseSandGravel(
cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change
@@ -199,7 +289,7 @@ protected:
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
- /// Tries to place a spring at the specified coords, checks neighbors. Returns true if successful
+ /// Tries to place a spring at the specified coords, checks neighbors. Returns true if successful
bool TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int y, int z);
} ;
diff --git a/src/Generating/GridStructGen.cpp b/src/Generating/GridStructGen.cpp
index 95f8c38bc..7090f14b1 100644
--- a/src/Generating/GridStructGen.cpp
+++ b/src/Generating/GridStructGen.cpp
@@ -9,7 +9,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cEmptyStructure:
/** A cStructure descendant representing an empty structure.
@@ -44,6 +44,7 @@ cGridStructGen::cGridStructGen(
int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
size_t a_MaxCacheSize
) :
+ m_Seed(a_Seed),
m_Noise(a_Seed),
m_GridSizeX(a_GridSizeX),
m_GridSizeZ(a_GridSizeZ),
@@ -53,6 +54,16 @@ cGridStructGen::cGridStructGen(
m_MaxStructureSizeZ(a_MaxStructureSizeZ),
m_MaxCacheSize(a_MaxCacheSize)
{
+ if (m_GridSizeX == 0)
+ {
+ LOG("Grid Size cannot be zero, setting to 1");
+ m_GridSizeX = 1;
+ }
+ if (m_GridSizeZ == 0)
+ {
+ LOG("Grid Size cannot be zero, setting to 1");
+ m_GridSizeZ = 1;
+ }
size_t NumStructuresPerQuery = (size_t)(((m_MaxStructureSizeX + m_MaxOffsetX) / m_GridSizeX + 1) * ((m_MaxStructureSizeZ + m_MaxOffsetZ) / m_GridSizeZ + 1));
if (NumStructuresPerQuery > m_MaxCacheSize)
{
diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp
index 202f7db7e..c3f3b38a9 100644
--- a/src/Generating/HeiGen.cpp
+++ b/src/Generating/HeiGen.cpp
@@ -16,7 +16,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cTerrainHeightGen:
cTerrainHeightGen * cTerrainHeightGen::CreateHeightGen(cIniFile &a_IniFile, cBiomeGen & a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault)
@@ -91,7 +91,7 @@ cTerrainHeightGen * cTerrainHeightGen::CreateHeightGen(cIniFile &a_IniFile, cBio
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cHeiGenFlat:
void cHeiGenFlat::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap)
@@ -115,7 +115,7 @@ void cHeiGenFlat::InitializeHeightGen(cIniFile & a_IniFile)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cHeiGenCache:
cHeiGenCache::cHeiGenCache(cTerrainHeightGen & a_HeiGenToCache, int a_CacheSize) :
@@ -234,7 +234,7 @@ bool cHeiGenCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_Rel
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cHeiGenClassic:
cHeiGenClassic::cHeiGenClassic(int a_Seed) :
@@ -253,9 +253,9 @@ float cHeiGenClassic::GetNoise(float x, float y)
float oct2 = m_Noise.CubicNoise2D(x * m_HeightFreq2, y * m_HeightFreq2) * m_HeightAmp2;
float oct3 = m_Noise.CubicNoise2D(x * m_HeightFreq3, y * m_HeightFreq3) * m_HeightAmp3;
- float height = m_Noise.CubicNoise2D(x * 0.1f, y * 0.1f ) * 2;
+ float height = m_Noise.CubicNoise2D(x * 0.1f, y * 0.1f) * 2;
- float flatness = ((m_Noise.CubicNoise2D(x * 0.5f, y * 0.5f) + 1.f) * 0.5f) * 1.1f; // 0 ... 1.5
+ float flatness = ((m_Noise.CubicNoise2D(x * 0.5f, y * 0.5f) + 1.f) * 0.5f) * 1.1f; // 0 ... 1.5
flatness *= flatness * flatness;
return (oct1 + oct2 + oct3) * flatness + height;
@@ -267,7 +267,7 @@ float cHeiGenClassic::GetNoise(float x, float y)
void cHeiGenClassic::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap)
{
- for (int z = 0; z < cChunkDef::Width; z++)
+ for (int z = 0; z < cChunkDef::Width; z++)
{
const float zz = (float)(a_ChunkZ * cChunkDef::Width + z);
for (int x = 0; x < cChunkDef::Width; x++)
@@ -283,7 +283,7 @@ void cHeiGenClassic::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightM
{
hei = 250;
}
- cChunkDef::SetHeight(a_HeightMap, x , z, hei);
+ cChunkDef::SetHeight(a_HeightMap, x, z, hei);
} // for x
} // for z
}
@@ -306,7 +306,7 @@ void cHeiGenClassic::InitializeHeightGen(cIniFile & a_IniFile)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cHeiGenMountains:
cHeiGenMountains::cHeiGenMountains(int a_Seed) :
@@ -345,7 +345,7 @@ void cHeiGenMountains::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::Heigh
{
hei = 250;
}
- cChunkDef::SetHeight(a_HeightMap, x , z, hei);
+ cChunkDef::SetHeight(a_HeightMap, x, z, hei);
} // for x
} // for z
}
@@ -368,7 +368,7 @@ void cHeiGenMountains::InitializeHeightGen(cIniFile & a_IniFile)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cHeiGenBiomal:
const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] =
@@ -432,7 +432,7 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] =
/* biExtremeHillsM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 131
/* biFlowerForest */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 132
/* biTaigaM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 133
- /* biSwamplandM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 134
+ /* biSwamplandM */ { 1.0f, 3.0f, 1.10f, 7.0f, 0.01f, 0.01f, 60}, // 134
// Biomes 135 .. 139 unused, 5 empty placeholders here:
{}, {}, {}, {}, {}, // 135 .. 139
diff --git a/src/Generating/MineShafts.cpp b/src/Generating/MineShafts.cpp
index ab9b1aa29..0532aff39 100644
--- a/src/Generating/MineShafts.cpp
+++ b/src/Generating/MineShafts.cpp
@@ -275,7 +275,7 @@ public:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenMineShafts::cMineShaftSystem:
cStructGenMineShafts::cMineShaftSystem::cMineShaftSystem(
@@ -400,7 +400,7 @@ bool cStructGenMineShafts::cMineShaftSystem::CanAppend(const cCuboid & a_Boundin
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cMineShaftDirtRoom:
cMineShaftDirtRoom::cMineShaftDirtRoom(cStructGenMineShafts::cMineShaftSystem & a_Parent, cNoise & a_Noise) :
@@ -492,7 +492,7 @@ void cMineShaftDirtRoom::ProcessChunk(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cMineShaftCorridor:
cMineShaftCorridor::cMineShaftCorridor(
@@ -732,7 +732,7 @@ void cMineShaftCorridor::ProcessChunk(cChunkDesc & a_ChunkDesc)
PlaceChest(a_ChunkDesc);
PlaceTracks(a_ChunkDesc);
- PlaceSpawner(a_ChunkDesc); // (must be after Tracks!)
+ PlaceSpawner(a_ChunkDesc); // (must be after Tracks!)
PlaceTorches(a_ChunkDesc);
}
@@ -964,7 +964,7 @@ void cMineShaftCorridor::PlaceTorches(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cMineShaftCrossing:
cMineShaftCrossing::cMineShaftCrossing(cStructGenMineShafts::cMineShaftSystem & a_ParentSystem, const cCuboid & a_BoundingBox) :
@@ -997,7 +997,6 @@ cMineShaft * cMineShaftCrossing::CreateAndFit(
BoundingBox.p2.y -= 4;
}
}
- rnd >>= 2;
switch (a_Direction)
{
case dirXP: BoundingBox.p2.x += 4; BoundingBox.p1.z -= 2; BoundingBox.p2.z += 2; break;
@@ -1100,7 +1099,7 @@ void cMineShaftCrossing::ProcessChunk(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cMineShaftStaircase:
cMineShaftStaircase::cMineShaftStaircase(
@@ -1278,7 +1277,7 @@ void cMineShaftStaircase::ProcessChunk(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenMineShafts:
cStructGenMineShafts::cStructGenMineShafts(
diff --git a/src/Generating/NetherFortGen.cpp b/src/Generating/NetherFortGen.cpp
index 23fa56048..f35555efd 100644
--- a/src/Generating/NetherFortGen.cpp
+++ b/src/Generating/NetherFortGen.cpp
@@ -11,7 +11,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cNetherFortGen::cNetherFort:
class cNetherFortGen::cNetherFort :
@@ -65,7 +65,7 @@ public:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Performance test of the NetherFort generator:
/*
@@ -99,7 +99,7 @@ public:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cNetherFortGen:
cPrefabPiecePool cNetherFortGen::m_PiecePool(g_NetherFortPrefabs, g_NetherFortPrefabsCount, g_NetherFortStartingPrefabs, g_NetherFortStartingPrefabsCount);
diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp
index 15a588d45..eb816f564 100644
--- a/src/Generating/Noise3DGenerator.cpp
+++ b/src/Generating/Noise3DGenerator.cpp
@@ -61,7 +61,7 @@ public:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cNoise3DGenerator:
cNoise3DGenerator::cNoise3DGenerator(cChunkGenerator & a_ChunkGenerator) :
@@ -342,7 +342,7 @@ void cNoise3DGenerator::ComposeTerrain(cChunkDesc & a_ChunkDesc)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cNoise3DComposable:
cNoise3DComposable::cNoise3DComposable(int a_Seed) :
@@ -412,11 +412,12 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ)
for (int x = 0; x < 17; x += UPSCALE_X)
{
NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width + x)) / m_FrequencyX;
- CurFloor[x + 17 * z] =
+ CurFloor[x + 17 * z] = (
m_Noise1.CubicNoise3D(NoiseX, NoiseY, NoiseZ) * (NOISE_DATATYPE)0.5 +
m_Noise2.CubicNoise3D(NoiseX / 2, NoiseY / 2, NoiseZ / 2) +
m_Noise3.CubicNoise3D(NoiseX / 4, NoiseY / 4, NoiseZ / 4) * 2 +
- AddHeight / Height[x + 17 * z];
+ AddHeight / Height[x + 17 * z]
+ );
}
}
// Linear-interpolate this XZ floor:
diff --git a/src/Generating/POCPieceGenerator.cpp b/src/Generating/POCPieceGenerator.cpp
index 491f4d206..6e7e74d7a 100644
--- a/src/Generating/POCPieceGenerator.cpp
+++ b/src/Generating/POCPieceGenerator.cpp
@@ -150,7 +150,7 @@ static void DebugPieces(const cPlacedPieces & a_Pieces)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cPOCPieceGenerator:
cPOCPieceGenerator::cPOCPieceGenerator(int a_Seed) :
diff --git a/src/Generating/PieceGenerator.cpp b/src/Generating/PieceGenerator.cpp
index 5de231f75..ae4b6e36c 100644
--- a/src/Generating/PieceGenerator.cpp
+++ b/src/Generating/PieceGenerator.cpp
@@ -1,7 +1,7 @@
// PieceGenerator.cpp
-// Implements the cBFSPieceGenerator class and cDFSPieceGenerator class
+// Implements the cBFSPieceGenerator class and cDFSPieceGenerator class
// representing base classes for generating structures composed of individual "pieces"
#include "Globals.h"
@@ -13,7 +13,7 @@
#ifdef SELF_TEST
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Self-test:
static class cPieceGeneratorSelfTest :
@@ -140,7 +140,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cPiece:
@@ -254,7 +254,7 @@ cCuboid cPiece::RotateMoveHitBox(int a_NumCCWRotations, int a_MoveX, int a_MoveY
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cPiece::cConnector:
cPiece::cConnector::cConnector(int a_X, int a_Y, int a_Z, int a_Type, eBlockFace a_Direction) :
@@ -279,7 +279,7 @@ cPiece::cConnector::cConnector(const Vector3i & a_Pos, int a_Type, eBlockFace a_
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cPlacedPiece:
cPlacedPiece::cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece, const Vector3i & a_Coords, int a_NumCCWRotations) :
@@ -328,7 +328,7 @@ void cPlacedPiece::MoveToGroundBy(int a_OffsetY)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cPieceGenerator:
cPieceGenerator::cPieceGenerator(cPiecePool & a_PiecePool, int a_Seed) :
@@ -578,7 +578,7 @@ void cPieceGenerator::DebugConnectorPool(const cPieceGenerator::cFreeConnectors
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cPieceGenerator::cConnection:
cPieceGenerator::cConnection::cConnection(cPiece & a_Piece, cPiece::cConnector & a_Connector, int a_NumCCWRotations, int a_Weight) :
@@ -593,7 +593,7 @@ cPieceGenerator::cConnection::cConnection(cPiece & a_Piece, cPiece::cConnector &
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cPieceGenerator::cFreeConnector:
cPieceGenerator::cFreeConnector::cFreeConnector(cPlacedPiece * a_Piece, const cPiece::cConnector & a_Connector) :
@@ -606,7 +606,7 @@ cPieceGenerator::cFreeConnector::cFreeConnector(cPlacedPiece * a_Piece, const cP
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cBFSPieceGenerator:
cBFSPieceGenerator::cBFSPieceGenerator(cPiecePool & a_PiecePool, int a_Seed) :
diff --git a/src/Generating/PieceGenerator.h b/src/Generating/PieceGenerator.h
index fd8576706..f06029280 100644
--- a/src/Generating/PieceGenerator.h
+++ b/src/Generating/PieceGenerator.h
@@ -1,7 +1,7 @@
// PieceGenerator.h
-// Declares the cBFSPieceGenerator class and cDFSPieceGenerator class
+// Declares the cBFSPieceGenerator class and cDFSPieceGenerator class
// representing base classes for generating structures composed of individual "pieces"
/*
@@ -251,7 +251,7 @@ protected:
const cPiece::cConnector & a_ExistingConnector, // The existing connector
const Vector3i & a_ToPos, // The position on which the new connector should be placed
const cPiece & a_Piece, // The new piece
- const cPiece::cConnector & a_NewConnector, // The connector of the new piece
+ const cPiece::cConnector & a_NewConnector, // The connector of the new piece
int a_NumCCWRotations, // Number of rotations for the new piece to align the connector
const cPlacedPieces & a_OutPieces // All the already-placed pieces to check
);
diff --git a/src/Generating/Prefab.cpp b/src/Generating/Prefab.cpp
index 7d876909a..6da3c3d10 100644
--- a/src/Generating/Prefab.cpp
+++ b/src/Generating/Prefab.cpp
@@ -181,7 +181,7 @@ void cPrefab::AddRotatedBlockAreas(void)
m_BlockArea[2].CopyFrom(m_BlockArea[0]);
m_BlockArea[2].MirrorXY();
m_BlockArea[2].MirrorYZ();
- }
+ }
// 3 CCW rotations = 1 CW rotation:
if ((m_AllowedRotations & 0x04) != 0)
diff --git a/src/Generating/Prefab.h b/src/Generating/Prefab.h
index 8b4e4b4ef..eb905e78e 100644
--- a/src/Generating/Prefab.h
+++ b/src/Generating/Prefab.h
@@ -183,7 +183,7 @@ protected:
bool m_MoveToGround;
- // cPiece overrides:
+ // cPiece overrides:
virtual cConnectors GetConnectors(void) const override;
virtual Vector3i GetSize(void) const override;
virtual cCuboid GetHitBox(void) const override;
diff --git a/src/Generating/Prefabs/AlchemistVillagePrefabs.cpp b/src/Generating/Prefabs/AlchemistVillagePrefabs.cpp
index 976f8490e..c08e53ef6 100644
--- a/src/Generating/Prefabs/AlchemistVillagePrefabs.cpp
+++ b/src/Generating/Prefabs/AlchemistVillagePrefabs.cpp
@@ -15,7 +15,7 @@
const cPrefab::sDef g_AlchemistVillagePrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BarWithBasement:
// The data has been exported from the gallery Desert, area index 82, ID 598, created by STR_Warrior
{
@@ -264,7 +264,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BarWithoutBasement:
// The data has been exported from the gallery Desert, area index 81, ID 597, created by STR_Warrior
{
@@ -463,7 +463,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BlackSmith:
// The data has been exported from the gallery Desert, area index 97, ID 642, created by STR_Warrior
{
@@ -633,7 +633,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LargeHouse1:
// The data has been exported from the gallery Desert, area index 77, ID 577, created by STR_Warrior
{
@@ -922,7 +922,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LargeTower:
// The data has been exported from the gallery Desert, area index 80, ID 596, created by STR_Warrior
{
@@ -1108,7 +1108,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LittleHouse:
// The data has been exported from the gallery Desert, area index 65, ID 551, created by STR_Warrior
{
@@ -1229,7 +1229,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LittleHouse2:
// The data has been exported from the gallery Desert, area index 72, ID 562, created by STR_Warrior
{
@@ -1376,7 +1376,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LittleHouse3:
// The data has been exported from the gallery Desert, area index 66, ID 553, created by STR_Warrior
{
@@ -1496,7 +1496,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LittleHouse4:
// The data has been exported from the gallery Desert, area index 70, ID 560, created by STR_Warrior
{
@@ -1647,7 +1647,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LittleHouse5:
// The data has been exported from the gallery Desert, area index 68, ID 558, created by STR_Warrior
{
@@ -1781,7 +1781,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LittleHouse6:
// The data has been exported from the gallery Desert, area index 69, ID 559, created by STR_Warrior
{
@@ -1922,7 +1922,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LittleHouse7:
// The data has been exported from the gallery Desert, area index 73, ID 563, created by xoft
{
@@ -2068,7 +2068,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LittleHouse8:
// The data has been exported from the gallery Desert, area index 99, ID 739, created by STR_Warrior
{
@@ -2200,7 +2200,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LittleTower:
// The data has been exported from the gallery Desert, area index 79, ID 595, created by STR_Warrior
{
@@ -2351,7 +2351,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MediumHouse1:
// The data has been exported from the gallery Desert, area index 71, ID 561, created by STR_Warrior
{
@@ -2367,9 +2367,9 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
"a: 24: 2\n" /* sandstone */
"b: 4: 0\n" /* cobblestone */
"c: 24: 0\n" /* sandstone */
- "d: 12: 0\n" /* sand */
- "e: 13: 0\n" /* gravel */
- "f: 5: 0\n" /* wood */
+ "d: 13: 0\n" /* gravel */
+ "e: 5: 0\n" /* wood */
+ "f: 12: 0\n" /* sand */
"g: 64: 3\n" /* wooddoorblock */
"h: 85: 0\n" /* fence */
"i: 64: 0\n" /* wooddoorblock */
@@ -2392,26 +2392,26 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
/* * 012345678901234 */
/* 0 */ "mmmabbbammmmmmm"
/* 1 */ "mmmmbbbmmmmmmmm"
- /* 2 */ "acccccccccadddd"
- /* 3 */ "cccccccccccdddd"
- /* 4 */ "cccccccccccdddd"
- /* 5 */ "cccccccccccdddd"
- /* 6 */ "cccccccccccdddd"
- /* 7 */ "cccccccccccdddd"
- /* 8 */ "acccccccccadddd"
+ /* 2 */ "acccccccccacccc"
+ /* 3 */ "ccccccccccccccc"
+ /* 4 */ "ccccccccccccccc"
+ /* 5 */ "ccccccccccccccc"
+ /* 6 */ "ccccccccccccccc"
+ /* 7 */ "ccccccccccccccc"
+ /* 8 */ "acccccccccacccc"
// Level 1
/* z\x* 11111 */
/* * 012345678901234 */
- /* 0 */ "mmmaeeeammmmmmm"
- /* 1 */ "mmmmeeemmmmmmmm"
- /* 2 */ "accccfccccadddd"
- /* 3 */ "cfffffffffcdddd"
- /* 4 */ "cfffffffffcdddd"
- /* 5 */ "cffffffffffdddd"
- /* 6 */ "cfffffffffcdddd"
- /* 7 */ "cfffffffffcdddd"
- /* 8 */ "acccccccccadddd"
+ /* 0 */ "mmmadddammmmmmm"
+ /* 1 */ "mmmmdddmmmmmmmm"
+ /* 2 */ "acccceccccaffff"
+ /* 3 */ "ceeeeeeeeecffff"
+ /* 4 */ "ceeeeeeeeecffff"
+ /* 5 */ "ceeeeeeeeeeffff"
+ /* 6 */ "ceeeeeeeeecffff"
+ /* 7 */ "ceeeeeeeeecffff"
+ /* 8 */ "acccccccccaffff"
// Level 2
/* z\x* 11111 */
@@ -2531,7 +2531,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MediumHouse2:
// The data has been exported from the gallery Desert, area index 74, ID 573, created by STR_Warrior
{
@@ -2740,7 +2740,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MediumHouse3:
// The data has been exported from the gallery Desert, area index 76, ID 575, created by STR_Warrior
{
@@ -2958,7 +2958,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// SmallHouse9:
// The data has been exported from the gallery Desert, area index 67, ID 556, created by STR_Warrior
{
@@ -3104,7 +3104,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Temple:
// The data has been exported from the gallery Desert, area index 83, ID 599, created by STR_Warrior
{
@@ -3310,7 +3310,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
const cPrefab::sDef g_AlchemistVillageStartingPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Well:
// The data has been exported from the gallery Desert, area index 90, ID 631, created by STR_Warrior
{
diff --git a/src/Generating/Prefabs/CMakeLists.txt b/src/Generating/Prefabs/CMakeLists.txt
index a1f09112d..2c62aa73d 100644
--- a/src/Generating/Prefabs/CMakeLists.txt
+++ b/src/Generating/Prefabs/CMakeLists.txt
@@ -4,11 +4,30 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ AlchemistVillagePrefabs.cpp
+ JapaneseVillagePrefabs.cpp
+ NetherFortPrefabs.cpp
+ PlainsVillagePrefabs.cpp
+ RainbowRoadPrefabs.cpp
+ SandFlatRoofVillagePrefabs.cpp
+ SandVillagePrefabs.cpp
+ TestRailsPrefabs.cpp
+ UnderwaterBasePrefabs.cpp)
-add_library(Generating_Prefabs ${SOURCE})
+SET (HDRS
+ AlchemistVillagePrefabs.h
+ JapaneseVillagePrefabs.h
+ NetherFortPrefabs.h
+ PlainsVillagePrefabs.h
+ RainbowRoadPrefabs.h
+ SandFlatRoofVillagePrefabs.h
+ SandVillagePrefabs.h
+ TestRailsPrefabs.h
+ UnderwaterBasePrefabs.h)
-target_link_libraries(Generating_Prefabs OSSupport iniFile Blocks)
+if(NOT MSVC)
+ add_library(Generating_Prefabs ${SRCS} ${HDRS})
+
+ target_link_libraries(Generating_Prefabs OSSupport iniFile Blocks)
+endif()
diff --git a/src/Generating/Prefabs/JapaneseVillagePrefabs.cpp b/src/Generating/Prefabs/JapaneseVillagePrefabs.cpp
index d22153d87..0362c9406 100644
--- a/src/Generating/Prefabs/JapaneseVillagePrefabs.cpp
+++ b/src/Generating/Prefabs/JapaneseVillagePrefabs.cpp
@@ -15,7 +15,7 @@
const cPrefab::sDef g_JapaneseVillagePrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Arch:
// The data has been exported from the gallery Plains, area index 144, ID 488, created by Aloe_vera
{
@@ -129,16 +129,16 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Farm:
// The data has been exported from the gallery Plains, area index 166, ID 554, created by Aloe_vera
{
// Size:
- 11, 7, 13, // SizeX = 11, SizeY = 7, SizeZ = 13
+ 11, 8, 13, // SizeX = 11, SizeY = 8, SizeZ = 13
// Hitbox (relative to bounding box):
0, 0, 0, // MinX, MinY, MinZ
- 10, 6, 12, // MaxX, MaxY, MaxZ
+ 10, 7, 12, // MaxX, MaxY, MaxZ
// Block definitions:
".: 0: 0\n" /* air */
@@ -150,6 +150,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
"f: 59: 7\n" /* crops */
"g: 83: 0\n" /* reedblock */
"h:113: 0\n" /* netherbrickfence */
+ "i: 50: 5\n" /* torch */
"m: 19: 0\n" /* sponge */,
// Block data:
@@ -270,7 +271,24 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
/* 9 */ "..........."
/* 10 */ ".h.......h."
/* 11 */ "hhh.....hhh"
- /* 12 */ ".h.......h.",
+ /* 12 */ ".h.......h."
+
+ // Level 7
+ /* z\x* 1 */
+ /* * 01234567890 */
+ /* 0 */ ".i.......i."
+ /* 1 */ "i.i.....i.i"
+ /* 2 */ ".i.......i."
+ /* 3 */ "..........."
+ /* 4 */ "..........."
+ /* 5 */ "..........."
+ /* 6 */ "..........."
+ /* 7 */ "..........."
+ /* 8 */ "..........."
+ /* 9 */ "..........."
+ /* 10 */ ".i.......i."
+ /* 11 */ "i.i.....i.i"
+ /* 12 */ ".i.......i.",
// Connectors:
"-1: 10, 2, 6: 5\n" /* Type -1, direction X+ */,
@@ -299,7 +317,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Forge:
// The data has been exported from the gallery Plains, area index 79, ID 145, created by Aloe_vera
{
@@ -565,7 +583,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Garden2:
// The data has been exported from the gallery Plains, area index 147, ID 491, created by Aloe_vera
{
@@ -717,7 +735,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseMid:
// The data has been exported from the gallery Plains, area index 62, ID 119, created by Aloe_vera
{
@@ -893,7 +911,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseSmall:
// The data has been exported from the gallery Plains, area index 68, ID 131, created by Aloe_vera
{
@@ -1004,7 +1022,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseSmallDblWithDoor:
// The data has been exported from the gallery Plains, area index 113, ID 265, created by Aloe_vera
{
@@ -1128,7 +1146,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseSmallDouble:
// The data has been exported from the gallery Plains, area index 72, ID 135, created by Aloe_vera
{
@@ -1249,7 +1267,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseSmallWithDoor:
// The data has been exported from the gallery Plains, area index 112, ID 264, created by Aloe_vera
{
@@ -1362,7 +1380,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseWide:
// The data has been exported from the gallery Plains, area index 64, ID 121, created by STR_Warrior
{
@@ -1510,7 +1528,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseWithGarden:
// The data has been exported from the gallery Plains, area index 67, ID 130, created by Aloe_vera
{
@@ -1756,7 +1774,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseWithSakura1:
// The data has been exported from the gallery Plains, area index 75, ID 141, created by Aloe_vera
{
@@ -1950,7 +1968,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseWithSpa:
// The data has been exported from the gallery Plains, area index 73, ID 139, created by Aloe_vera
{
@@ -2158,7 +2176,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MediumSakuraTree:
// The data has been exported from the gallery Plains, area index 146, ID 490, created by STR_Warrior
{
@@ -2195,33 +2213,33 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
// Level 1
/* z\x* 0123456 */
- /* 0 */ "bmmmmmm"
- /* 1 */ "bmmmmmm"
- /* 2 */ "bmmmmmm"
- /* 3 */ "bmmmmmm"
- /* 4 */ "bmmmmmm"
- /* 5 */ "bmmmmmm"
+ /* 0 */ "bbbbbbb"
+ /* 1 */ "bbbbbbb"
+ /* 2 */ "bbbbbbb"
+ /* 3 */ "bbbabbb"
+ /* 4 */ "bbbbbbb"
+ /* 5 */ "bbbbbbb"
/* 6 */ "bbbbbbb"
// Level 2
/* z\x* 0123456 */
- /* 0 */ "......."
- /* 1 */ "..c.c.."
+ /* 0 */ "mm...mm"
+ /* 1 */ "m.c...m"
/* 2 */ ".dccdc."
/* 3 */ "..cefc."
/* 4 */ ".ccfgh."
- /* 5 */ "..ccc.."
- /* 6 */ "......."
+ /* 5 */ "m.ccc.m"
+ /* 6 */ "mm...mm"
// Level 3
/* z\x* 0123456 */
- /* 0 */ "......."
+ /* 0 */ "m.....m"
/* 1 */ "......."
/* 2 */ "......."
/* 3 */ "...e..."
/* 4 */ "......."
/* 5 */ "......."
- /* 6 */ "......."
+ /* 6 */ "m.....m"
// Level 4
/* z\x* 0123456 */
@@ -2312,7 +2330,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Restaurant:
// The data has been exported from the gallery Plains, area index 61, ID 117, created by Aloe_vera
{
@@ -2566,7 +2584,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// SakuraDouble:
// The data has been exported from the gallery Plains, area index 76, ID 142, created by Aloe_vera
{
@@ -2697,7 +2715,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// SakuraSmall:
// The data has been exported from the gallery Plains, area index 145, ID 489, created by Aloe_vera
{
@@ -2808,7 +2826,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
const cPrefab::sDef g_JapaneseVillageStartingPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HighTemple:
// The data has been exported from the gallery Plains, area index 70, ID 133, created by Aloe_vera
{
@@ -3159,7 +3177,7 @@ const cPrefab::sDef g_JapaneseVillageStartingPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Well:
// The data has been exported from the gallery Plains, area index 143, ID 487, created by STR_Warrior
{
diff --git a/src/Generating/Prefabs/NetherFortPrefabs.cpp b/src/Generating/Prefabs/NetherFortPrefabs.cpp
index 2c97f28ea..a3e3da158 100644
--- a/src/Generating/Prefabs/NetherFortPrefabs.cpp
+++ b/src/Generating/Prefabs/NetherFortPrefabs.cpp
@@ -15,7 +15,7 @@
const cPrefab::sDef g_NetherFortPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BalconyCorridor:
// The data has been exported from the gallery Nether, area index 37, ID 288, created by Aloe_vera
{
@@ -162,7 +162,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BalconyTee2:
// The data has been exported from the gallery Nether, area index 38, ID 289, created by Aloe_vera
{
@@ -325,7 +325,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BlazePlatform:
// The data has been exported from the gallery Nether, area index 26, ID 276, created by tonibm1999
{
@@ -448,7 +448,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BlazePlatformOverhang:
// The data has been exported from the gallery Nether, area index 20, ID 162, created by STR_Warrior
{
@@ -621,7 +621,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BridgeCircleCrossing:
// The data has been exported from the gallery Nether, area index 49, ID 308, created by Aloe_vera
{
@@ -824,7 +824,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BridgeCrossing:
// The data has been exported from the gallery Nether, area index 17, ID 159, created by Aloe_vera
{
@@ -1028,7 +1028,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BridgeCrumble1:
// The data has been exported from the gallery Nether, area index 19, ID 161, created by Aloe_vera
{
@@ -1125,7 +1125,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BridgeCrumble2:
// The data has been exported from the gallery Nether, area index 18, ID 160, created by Aloe_vera
{
@@ -1228,7 +1228,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BridgeDoubleCrumble:
// The data has been exported from the gallery Nether, area index 46, ID 305, created by STR_Warrior
{
@@ -1410,7 +1410,384 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ // BridgeDoubleStairs:
+ // The data has been exported from the gallery Nether, area index 115, ID 810, created by STR_Warrior
+ {
+ // Size:
+ 15, 16, 16, // SizeX = 15, SizeY = 16, SizeZ = 16
+
+ // Hitbox (relative to bounding box):
+ 0, 0, 0, // MinX, MinY, MinZ
+ 14, 15, 15, // MaxX, MaxY, MaxZ
+
+ // Block definitions:
+ ".: 0: 0\n" /* air */
+ "a:112: 0\n" /* netherbrick */
+ "b:114: 7\n" /* netherbrickstairs */
+ "c:114: 6\n" /* netherbrickstairs */
+ "d:114: 4\n" /* netherbrickstairs */
+ "e:114: 5\n" /* netherbrickstairs */
+ "f:114: 2\n" /* netherbrickstairs */
+ "g:114: 3\n" /* netherbrickstairs */
+ "h:114: 1\n" /* netherbrickstairs */
+ "i: 44:14\n" /* step */
+ "m: 19: 0\n" /* sponge */,
+
+ // Block data:
+ // Level 0
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmmaaam"
+ /* 1 */ "aammmmmmmmmaaaa"
+ /* 2 */ "aammmmmmmmmmmma"
+ /* 3 */ "aammmmmmmmmmmma"
+ /* 4 */ "mmmmmmmmmmmmmmm"
+ /* 5 */ "mmmmmmmmmmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmm"
+ /* 12 */ "aammmmmmmmmmmma"
+ /* 13 */ "aammmmmmmmmmmma"
+ /* 14 */ "aammmmmmmmmaaaa"
+ /* 15 */ "mmmmmmmmmmmaaam"
+
+ // Level 1
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmmaaam"
+ /* 1 */ "aammmmmmmmmaaaa"
+ /* 2 */ "aammmmmmmmmmmma"
+ /* 3 */ "aammmmmmmmmmmma"
+ /* 4 */ "mmmmmmmmmmmmmmm"
+ /* 5 */ "mmmmmmmmmmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmm"
+ /* 12 */ "aammmmmmmmmmmma"
+ /* 13 */ "aammmmmmmmmmmma"
+ /* 14 */ "aammmmmmmmmaaaa"
+ /* 15 */ "mmmmmmmmmmmaaam"
+
+ // Level 2
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmmaaam"
+ /* 1 */ "aammmmmmmmmaaaa"
+ /* 2 */ "aammmmmmmmmmmma"
+ /* 3 */ "aammmmmmmmmmmma"
+ /* 4 */ "mmmmmmmmmmmmmmm"
+ /* 5 */ "mmmmmmmmmmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmm"
+ /* 12 */ "aammmmmmmmmmmma"
+ /* 13 */ "aammmmmmmmmmmma"
+ /* 14 */ "aammmmmmmmmaaaa"
+ /* 15 */ "mmmmmmmmmmmaaam"
+
+ // Level 3
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmmaaam"
+ /* 1 */ "aammmmmmmmmaaaa"
+ /* 2 */ "aammmmmmmmmbbba"
+ /* 3 */ "aammmmmmmmmmmma"
+ /* 4 */ "mmmmmmmmmmmmmmm"
+ /* 5 */ "mmmmmmmmmmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmm"
+ /* 12 */ "aammmmmmmmmmmma"
+ /* 13 */ "aammmmmmmmmccca"
+ /* 14 */ "aammmmmmmmmaaaa"
+ /* 15 */ "mmmmmmmmmmmaaam"
+
+ // Level 4
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmmaaam"
+ /* 1 */ "aammmmmmmmmaaaa"
+ /* 2 */ "aammmmmmmmmaaaa"
+ /* 3 */ "aammmmmmmmmbbba"
+ /* 4 */ "mmmmmmmmmmmmmmm"
+ /* 5 */ "mmmmmmmmmmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmm"
+ /* 12 */ "aammmmmmmmmccca"
+ /* 13 */ "aammmmmmmmmaaaa"
+ /* 14 */ "aammmmmmmmmaaaa"
+ /* 15 */ "mmmmmmmmmmmaaam"
+
+ // Level 5
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmdaaae"
+ /* 1 */ "aammmmmmmmdaaaa"
+ /* 2 */ "aammmmmmmmdaaaa"
+ /* 3 */ "aammmmmmmmdaaaa"
+ /* 4 */ "mmmmmmmmmmdaaae"
+ /* 5 */ "mmmmmmmmmmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmdaaae"
+ /* 12 */ "aammmmmmmmdaaaa"
+ /* 13 */ "aammmmmmmmdaaaa"
+ /* 14 */ "aammmmmmmmdaaaa"
+ /* 15 */ "mmmmmmmmmmdaaae"
+
+ // Level 6
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmaaaaa"
+ /* 1 */ "aammmmmmmmaaaaa"
+ /* 2 */ "aammmmmmmmaaaaa"
+ /* 3 */ "aammmmmmmmaaaaa"
+ /* 4 */ "mmmmmmmmmmaaaaa"
+ /* 5 */ "mmmmmmmmmmdaaae"
+ /* 6 */ "mmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmdaaae"
+ /* 11 */ "mmmmmmmmmmaaaaa"
+ /* 12 */ "aammmmmmmmaaaaa"
+ /* 13 */ "aammmmmmmmaaaaa"
+ /* 14 */ "aammmmmmmmaaaaa"
+ /* 15 */ "mmmmmmmmmmaaaaa"
+
+ // Level 7
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmma...a"
+ /* 1 */ "aammmmmmmma...a"
+ /* 2 */ "aammmmmmmma...a"
+ /* 3 */ "aammmmmmmma...a"
+ /* 4 */ "mmmmmmmmmmafffa"
+ /* 5 */ "mmmmmmmmmaaaaaa"
+ /* 6 */ "mmmmmmmmmaaaaae"
+ /* 7 */ "mmmmmmmmmaaaaae"
+ /* 8 */ "mmmmmmmmmaaaaae"
+ /* 9 */ "mmmmmmmmmaaaaae"
+ /* 10 */ "mmmmmmmmmaaaaaa"
+ /* 11 */ "mmmmmmmmmmaggga"
+ /* 12 */ "aammmmmmmma...a"
+ /* 13 */ "aammmmmmmma...a"
+ /* 14 */ "aammmmmmmma...a"
+ /* 15 */ "mmmmmmmmmma...a"
+
+ // Level 8
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmm...m"
+ /* 1 */ "aammmmmmmma...a"
+ /* 2 */ "aammmmmmmma...a"
+ /* 3 */ "aammmmmmmma...a"
+ /* 4 */ "mmmmmmmmmma...a"
+ /* 5 */ "mmmmmmmmmaafffa"
+ /* 6 */ "mmmmmmmmaaaaaaa"
+ /* 7 */ "mmmmmmmmaaaaaaa"
+ /* 8 */ "mmmmmmmmaaaaaaa"
+ /* 9 */ "mmmmmmmmaaaaaaa"
+ /* 10 */ "mmmmmmmmmaaggga"
+ /* 11 */ "mmmmmmmmmma...a"
+ /* 12 */ "aammmmmmmma...a"
+ /* 13 */ "aammmmmmmma...a"
+ /* 14 */ "aammmmmmmma...a"
+ /* 15 */ "mmmmmmmmmmm...m"
+
+ // Level 9
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmm...m"
+ /* 1 */ "aaemmmmmmma...a"
+ /* 2 */ "aaemmmmmmma...a"
+ /* 3 */ "aaemmmmmmma...a"
+ /* 4 */ "mmmmmmmmmma...a"
+ /* 5 */ "mmmmmmmmmaa...a"
+ /* 6 */ "mmmmaaaaah....a"
+ /* 7 */ "mmmmaaaaah....a"
+ /* 8 */ "mmmmaaaaah....a"
+ /* 9 */ "mmmmaaaaah....a"
+ /* 10 */ "mmmmmmmmmaa...a"
+ /* 11 */ "mmmmmmmmmma...a"
+ /* 12 */ "aaemmmmmmma...a"
+ /* 13 */ "aaemmmmmmma...a"
+ /* 14 */ "aaemmmmmmma...a"
+ /* 15 */ "mmmmmmmmmmm...m"
+
+ // Level 10
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmmmmmm"
+ /* 1 */ "aaaeimmmmmammma"
+ /* 2 */ "aaaeimmmmmammma"
+ /* 3 */ "aaaeimmmmma...a"
+ /* 4 */ "mmmmmmmmmmm...m"
+ /* 5 */ "mmmmaaaaaam...m"
+ /* 6 */ "mmmmaaaah.....m"
+ /* 7 */ "mmmmaaaah.....m"
+ /* 8 */ "mmmmaaaah.....m"
+ /* 9 */ "mmmmaaaah.....m"
+ /* 10 */ "mmmmaaaaaam...m"
+ /* 11 */ "mmmmmmmmmmm...m"
+ /* 12 */ "aaaeimmmmma...a"
+ /* 13 */ "aaaeimmmmmammma"
+ /* 14 */ "aaaeimmmmmammma"
+ /* 15 */ "mmmmmmmmmmmmmmm"
+
+ // Level 11
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "ccccccccccccccc"
+ /* 1 */ "aaaaaaaaaaaaaaa"
+ /* 2 */ "aaaaaaaaaaaaaaa"
+ /* 3 */ "aaaaaaaaaaaaaaa"
+ /* 4 */ "bbbbaaaaabbbbbb"
+ /* 5 */ "mmmmagggamm...m"
+ /* 6 */ "mmmma.........m"
+ /* 7 */ "mmmma.........m"
+ /* 8 */ "mmmma.........m"
+ /* 9 */ "mmmma.........m"
+ /* 10 */ "mmmmafffamm...m"
+ /* 11 */ "ccccaaaahcccccc"
+ /* 12 */ "aaaaaaaaaaaaaaa"
+ /* 13 */ "aaaaaaaaaaaaaaa"
+ /* 14 */ "aaaaaaaaaaaaaaa"
+ /* 15 */ "bbbbbbbbbbbbbbb"
+
+ // Level 12
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "aaaaaaaaaaaaaaa"
+ /* 1 */ "aaaaaaaaaaaaaaa"
+ /* 2 */ "aaaaaaaaaaaaaaa"
+ /* 3 */ "aaaaaaaaaaaaaaa"
+ /* 4 */ "aaaaagggaaaaaaa"
+ /* 5 */ "mmmma...ammmmmm"
+ /* 6 */ "mmmma.........m"
+ /* 7 */ "mmmmm.........m"
+ /* 8 */ "mmmmm.........m"
+ /* 9 */ "mmmma.........m"
+ /* 10 */ "mmmma...ammmmmm"
+ /* 11 */ "aaaaafffaaaaaaa"
+ /* 12 */ "aaaaaaaaaaaaaaa"
+ /* 13 */ "aaaaaaaaaaaaaaa"
+ /* 14 */ "aaaaaaaaaaaaaaa"
+ /* 15 */ "aaaaaaaaaaaaaaa"
+
+ // Level 13
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "aaaaaaaaaaaaaaa"
+ /* 1 */ "..............."
+ /* 2 */ "..............."
+ /* 3 */ "..............."
+ /* 4 */ "aaaaa...aaaaaaa"
+ /* 5 */ "mmmma...ammmmmm"
+ /* 6 */ "mmmmm.....mmmmm"
+ /* 7 */ "mmmmm.....mmmmm"
+ /* 8 */ "mmmmm.....mmmmm"
+ /* 9 */ "mmmmm.....mmmmm"
+ /* 10 */ "mmmma...ammmmmm"
+ /* 11 */ "aaaaa...aaaaaaa"
+ /* 12 */ "..............."
+ /* 13 */ "..............."
+ /* 14 */ "..............."
+ /* 15 */ "aaaaaaaaaaaaaaa"
+
+ // Level 14
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmmmmmm"
+ /* 1 */ "..............."
+ /* 2 */ "..............."
+ /* 3 */ "..............."
+ /* 4 */ "mmmmm...mmmmmmm"
+ /* 5 */ "mmmmm...mmmmmmm"
+ /* 6 */ "mmmmm...mmmmmmm"
+ /* 7 */ "mmmmm...mmmmmmm"
+ /* 8 */ "mmmmm...mmmmmmm"
+ /* 9 */ "mmmmm...mmmmmmm"
+ /* 10 */ "mmmmm...mmmmmmm"
+ /* 11 */ "mmmmm...mmmmmmm"
+ /* 12 */ "..............."
+ /* 13 */ "..............."
+ /* 14 */ "..............."
+ /* 15 */ "mmmmmmmmmmmmmmm"
+
+ // Level 15
+ /* z\x* 11111 */
+ /* * 012345678901234 */
+ /* 0 */ "mmmmmmmmmmmmmmm"
+ /* 1 */ "..............."
+ /* 2 */ "..............."
+ /* 3 */ "..............."
+ /* 4 */ "mmmmm...mmmmmmm"
+ /* 5 */ "mmmmm...mmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmm...mmmmmmm"
+ /* 11 */ "mmmmm...mmmmmmm"
+ /* 12 */ "..............."
+ /* 13 */ "..............."
+ /* 14 */ "..............."
+ /* 15 */ "mmmmmmmmmmmmmmm",
+
+ // Connectors:
+ "0: 0, 13, 13: 4\n" /* Type 0, direction X- */
+ "0: 14, 13, 13: 5\n" /* Type 0, direction X+ */
+ "0: 0, 13, 2: 4\n" /* Type 0, direction X- */
+ "0: 14, 13, 2: 5\n" /* Type 0, direction X+ */
+ "0: 12, 7, 15: 3\n" /* Type 0, direction Z+ */
+ "0: 12, 7, 0: 2\n" /* Type 0, direction Z- */,
+
+ // AllowedRotations:
+ 7, /* 1, 2, 3 CCW rotation allowed */
+
+ // Merge strategy:
+ cBlockArea::msSpongePrint,
+
+ // ShouldExtendFloor:
+ true,
+
+ // DefaultWeight:
+ 20,
+
+ // DepthWeight:
+ "",
+
+ // AddWeightIfSame:
+ 0,
+
+ // MoveToGround:
+ false,
+ }, // BridgeDoubleStairs
+
+
+
+ ////////////////////////////////////////////////////////////////////////////////
// BridgeFunnelDown:
// The data has been exported from the gallery Nether, area index 0, ID 2, created by Aloe_vera
{
@@ -1653,7 +2030,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BridgeLevelCrossing:
// The data has been exported from the gallery Nether, area index 61, ID 321, created by Aloe_vera
{
@@ -1985,7 +2362,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BridgeSegment:
// The data has been exported from the gallery Nether, area index 16, ID 158, created by Aloe_vera
{
@@ -2107,7 +2484,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BridgeTee:
// The data has been exported from the gallery Nether, area index 39, ID 290, created by STR_Warrior
{
@@ -2270,7 +2647,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Corridor11:
// The data has been exported from the gallery Nether, area index 36, ID 287, created by Aloe_vera
{
@@ -2374,7 +2751,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Corridor13:
// The data has been exported from the gallery Nether, area index 35, ID 286, created by Aloe_vera
{
@@ -2478,7 +2855,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Corridor5:
// The data has been exported from the gallery Nether, area index 65, ID 330, created by xoft
{
@@ -2576,7 +2953,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CorridorCorner5:
// The data has been exported from the gallery Nether, area index 10, ID 40, created by xoft
{
@@ -2606,12 +2983,12 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
/* 2 */ "aaaaaaaaaaa"
/* 3 */ "aaaaaaaaaaa"
/* 4 */ "aaaaaaaaaaa"
- /* 5 */ "aaaaa......"
- /* 6 */ "aaaaa......"
- /* 7 */ "aaaaa......"
- /* 8 */ "aaaaa......"
- /* 9 */ "aaaaa......"
- /* 10 */ "aaaaa......"
+ /* 5 */ "aaaaammmmmm"
+ /* 6 */ "aaaaammmmmm"
+ /* 7 */ "aaaaammmmmm"
+ /* 8 */ "aaaaammmmmm"
+ /* 9 */ "aaaaammmmmm"
+ /* 10 */ "aaaaammmmmm"
// Level 1
/* z\x* 1 */
@@ -2621,12 +2998,12 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
/* 2 */ "a.........."
/* 3 */ "a.........."
/* 4 */ "a...aaaaaaa"
- /* 5 */ "a...a......"
- /* 6 */ "a...a......"
- /* 7 */ "a...a......"
- /* 8 */ "a...a......"
- /* 9 */ "a...a......"
- /* 10 */ "a...a......"
+ /* 5 */ "a...ammmmmm"
+ /* 6 */ "a...ammmmmm"
+ /* 7 */ "a...ammmmmm"
+ /* 8 */ "a...ammmmmm"
+ /* 9 */ "a...ammmmmm"
+ /* 10 */ "a...ammmmmm"
// Level 2
/* z\x* 1 */
@@ -2636,12 +3013,12 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
/* 2 */ "a.........."
/* 3 */ "b.........."
/* 4 */ "a...abababa"
- /* 5 */ "b...b......"
- /* 6 */ "a...a......"
- /* 7 */ "b...b......"
- /* 8 */ "a...a......"
- /* 9 */ "b...b......"
- /* 10 */ "a...a......"
+ /* 5 */ "b...bmmmmmm"
+ /* 6 */ "a...ammmmmm"
+ /* 7 */ "b...bmmmmmm"
+ /* 8 */ "a...ammmmmm"
+ /* 9 */ "b...bmmmmmm"
+ /* 10 */ "a...ammmmmm"
// Level 3
/* z\x* 1 */
@@ -2651,12 +3028,12 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
/* 2 */ "a.........."
/* 3 */ "b.........."
/* 4 */ "a...abababa"
- /* 5 */ "b...b......"
- /* 6 */ "a...a......"
- /* 7 */ "b...b......"
- /* 8 */ "a...a......"
- /* 9 */ "b...b......"
- /* 10 */ "a...a......"
+ /* 5 */ "b...bmmmmmm"
+ /* 6 */ "a...ammmmmm"
+ /* 7 */ "b...bmmmmmm"
+ /* 8 */ "a...ammmmmm"
+ /* 9 */ "b...bmmmmmm"
+ /* 10 */ "a...ammmmmm"
// Level 4
/* z\x* 1 */
@@ -2666,12 +3043,12 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
/* 2 */ "a.........."
/* 3 */ "b.........."
/* 4 */ "a...abababa"
- /* 5 */ "b...b......"
- /* 6 */ "a...a......"
- /* 7 */ "b...b......"
- /* 8 */ "a...a......"
- /* 9 */ "b...b......"
- /* 10 */ "a...a......"
+ /* 5 */ "b...bmmmmmm"
+ /* 6 */ "a...ammmmmm"
+ /* 7 */ "b...bmmmmmm"
+ /* 8 */ "a...ammmmmm"
+ /* 9 */ "b...bmmmmmm"
+ /* 10 */ "a...ammmmmm"
// Level 5
/* z\x* 1 */
@@ -2681,12 +3058,12 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
/* 2 */ "daaaaaaaaaa"
/* 3 */ "daaaaaaaaaa"
/* 4 */ "daaaeeeeeee"
- /* 5 */ "daaaf......"
- /* 6 */ "daaaf......"
- /* 7 */ "daaaf......"
- /* 8 */ "daaaf......"
- /* 9 */ "daaaf......"
- /* 10 */ "daaaf......",
+ /* 5 */ "daaafmmmmmm"
+ /* 6 */ "daaafmmmmmm"
+ /* 7 */ "daaafmmmmmm"
+ /* 8 */ "daaafmmmmmm"
+ /* 9 */ "daaafmmmmmm"
+ /* 10 */ "daaafmmmmmm",
// Connectors:
"1: 2, 1, 10: 3\n" /* Type 1, direction Z+ */
@@ -2718,7 +3095,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CorridorCornerChest5:
// The data has been exported from the gallery Nether, area index 42, ID 293, created by STR_Warrior
{
@@ -2861,7 +3238,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CorridorCrossing:
// The data has been exported from the gallery Nether, area index 63, ID 328, created by xoft
{
@@ -2989,7 +3366,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CorridorStairs:
// The data has been exported from the gallery Nether, area index 12, ID 42, created by xoft
{
@@ -3144,7 +3521,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// DarkCorridor:
// The data has been exported from the gallery Nether, area index 3, ID 30, created by STR_Warrior
{
@@ -3248,7 +3625,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LavaStaircase:
// The data has been exported from the gallery Nether, area index 28, ID 278, created by Aloe_vera
{
@@ -3508,7 +3885,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LavaStaircaseBig:
// The data has been exported from the gallery Nether, area index 31, ID 282, created by STR_Warrior
{
@@ -3842,7 +4219,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LavaStairsBridge:
// The data has been exported from the gallery Nether, area index 30, ID 281, created by STR_Warrior
{
@@ -4097,7 +4474,12 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
/* 14 */ "abbaabbaabbaabba",
// Connectors:
- "",
+ "1: 0, 6, 7: 4\n" /* Type 1, direction X- */
+ "-1: 0, 6, 7: 4\n" /* Type -1, direction X- */
+ "1: 9, 1, 0: 2\n" /* Type 1, direction Z- */
+ "-1: 9, 1, 0: 2\n" /* Type -1, direction Z- */
+ "1: 9, 1, 14: 3\n" /* Type 1, direction Z+ */
+ "-1: 9, 1, 14: 3\n" /* Type -1, direction Z+ */,
// AllowedRotations:
7, /* 1, 2, 3 CCW rotation allowed */
@@ -4123,7 +4505,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MidStaircase:
// The data has been exported from the gallery Nether, area index 23, ID 165, created by Aloe_vera
{
@@ -4314,7 +4696,340 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ // SlabbedBridgeStairs:
+ // The data has been exported from the gallery Nether, area index 116, ID 811, created by Aloe_vera
+ {
+ // Size:
+ 16, 14, 16, // SizeX = 16, SizeY = 14, SizeZ = 16
+
+ // Hitbox (relative to bounding box):
+ 0, 0, 0, // MinX, MinY, MinZ
+ 15, 13, 15, // MaxX, MaxY, MaxZ
+
+ // Block definitions:
+ ".: 0: 0\n" /* air */
+ "a:112: 0\n" /* netherbrick */
+ "b:114: 5\n" /* netherbrickstairs */
+ "c:114: 4\n" /* netherbrickstairs */
+ "d: 44:14\n" /* step */
+ "e:114: 6\n" /* netherbrickstairs */
+ "f:114: 7\n" /* netherbrickstairs */
+ "g: 44: 6\n" /* step */
+ "m: 19: 0\n" /* sponge */,
+
+ // Block data:
+ // Level 0
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmmmmmmm"
+ /* 1 */ "aammmmmmmmmmmmaa"
+ /* 2 */ "aammmmmmmmmmmmaa"
+ /* 3 */ "aammmmmmmmmmmmaa"
+ /* 4 */ "mmmmmmmmmmmmmmmm"
+ /* 5 */ "mmmmmmmmmmmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmmm"
+ /* 12 */ "maaammmmmmmmmmmm"
+ /* 13 */ "maaammmmmmmmmmmm"
+ /* 14 */ "maaammmmmmmmaaam"
+ /* 15 */ "mmmmmmmmmmmmaaam"
+
+ // Level 1
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmmmmmmm"
+ /* 1 */ "aabmmmmmmmmmmcaa"
+ /* 2 */ "aabmmmmmmmmmmcaa"
+ /* 3 */ "aabmmmmmmmmmmcaa"
+ /* 4 */ "mmmmmmmmmmmmmmmm"
+ /* 5 */ "mmmmmmmmmmmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmmm"
+ /* 12 */ "maaammmmmmmmmmmm"
+ /* 13 */ "maaammmmmmmmmmmm"
+ /* 14 */ "maaammmmmmmmaaam"
+ /* 15 */ "mmmmmmmmmmmmaaam"
+
+ // Level 2
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmmmmmmm"
+ /* 1 */ "aaabdmmmmmmdcaaa"
+ /* 2 */ "aaabdmmmmmmdcaaa"
+ /* 3 */ "aaabdmmmmmmdcaaa"
+ /* 4 */ "mmmmmmmmmmmmmmmm"
+ /* 5 */ "mmmmmmmmmmmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmmm"
+ /* 12 */ "maaammmmmmmmmmmm"
+ /* 13 */ "maaammmmmmmmmmmm"
+ /* 14 */ "maaammmmmmmmaaam"
+ /* 15 */ "mmmmmmmmmmmmaaam"
+
+ // Level 3
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "eeeeeeeeeeeeeeee"
+ /* 1 */ "aaaaaaaaaaaaaaaa"
+ /* 2 */ "aaaaaaaaaaaaaaaa"
+ /* 3 */ "aaaaaaaaaaaaaaaa"
+ /* 4 */ "ffffffffffffffff"
+ /* 5 */ "mmmmmmmmmmmmmmmm"
+ /* 6 */ "mmmmmmmmmmmmmmmm"
+ /* 7 */ "mmmmmmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmmm"
+ /* 12 */ "maaammmmmmmmmmmm"
+ /* 13 */ "maaammmmmmmmmmmm"
+ /* 14 */ "maaammmmmmmmaaam"
+ /* 15 */ "mmmmmmmmmmmmaaam"
+
+ // Level 4
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "aaaaaaaaaaaaaaaa"
+ /* 1 */ "aaaaaaaaaaaaaaaa"
+ /* 2 */ "aaaaaaaaaaaaaaaa"
+ /* 3 */ "aaaaaaaaaaaaaaaa"
+ /* 4 */ "aaaaaaaaaaaaaaaa"
+ /* 5 */ "faaabmmmmmmmmmmm"
+ /* 6 */ "caaabmmmmmmmmmmm"
+ /* 7 */ "caaabmmmmmmmmmmm"
+ /* 8 */ "mmmmmmmmmmmmmmmm"
+ /* 9 */ "mmmmmmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmmm"
+ /* 12 */ "maaammmmmmmmmmmm"
+ /* 13 */ "maaammmmmmmmmmmm"
+ /* 14 */ "maaammmmmmmmaaam"
+ /* 15 */ "mmmmmmmmmmmmaaam"
+
+ // Level 5
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "aaaaaaaaaaaaaaaa"
+ /* 1 */ "................"
+ /* 2 */ "................"
+ /* 3 */ "................"
+ /* 4 */ "a...aaaaaaaaaaaa"
+ /* 5 */ "agggammmmmmmmmmm"
+ /* 6 */ "aaaaammmmmmmmmmm"
+ /* 7 */ "aaaaammmmmmmmmmm"
+ /* 8 */ "caaabmmmmmmmmmmm"
+ /* 9 */ "caaabmmmmmmmmmmm"
+ /* 10 */ "mmmmmmmmmmmmmmmm"
+ /* 11 */ "mmmmmmmmmmmmmmmm"
+ /* 12 */ "maaammmmmmmmmmmm"
+ /* 13 */ "maaammmmmmmmmmmm"
+ /* 14 */ "maaammmmmmmmaaam"
+ /* 15 */ "mmmmmmmmmmmmaaam"
+
+ // Level 6
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmmmaaam"
+ /* 1 */ "................"
+ /* 2 */ "................"
+ /* 3 */ "................"
+ /* 4 */ "m...mmmmmmmmaaam"
+ /* 5 */ "a...ammmmmmmmmmm"
+ /* 6 */ "a...ammmmmmmmmmm"
+ /* 7 */ "agggammmmmmmmmmm"
+ /* 8 */ "aaaaammmmmmmmmmm"
+ /* 9 */ "aaaaammmmmmmmmmm"
+ /* 10 */ "caaabmmmmmmmmmmm"
+ /* 11 */ "caaabmmmmmmmmmmm"
+ /* 12 */ "maaabmmmmmmmmmmm"
+ /* 13 */ "maaabmmmmmmmmmmm"
+ /* 14 */ "maaafmmmmmmmaaam"
+ /* 15 */ "mmmmmmmmmmmmaaam"
+
+ // Level 7
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmmmaaam"
+ /* 1 */ "................"
+ /* 2 */ "................"
+ /* 3 */ "................"
+ /* 4 */ "m...mmmmmmmmaaam"
+ /* 5 */ "m...mmmmmmmmmmmm"
+ /* 6 */ "m...mmmmmmmmmmmm"
+ /* 7 */ "a...ammmmmmmmmmm"
+ /* 8 */ "a...ammmmmmmmmmm"
+ /* 9 */ "agggammmmmmmmmmm"
+ /* 10 */ "aaaaammmmmmmmmmm"
+ /* 11 */ "aaaaaeemmmmmmmmm"
+ /* 12 */ "caaaaaammmmmmmmm"
+ /* 13 */ "caaaaaammmmmmmmm"
+ /* 14 */ "caaaaaammmmmaaam"
+ /* 15 */ "fffffffmmmmmaaam"
+
+ // Level 8
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmmmaaam"
+ /* 1 */ "mmmmmmmmmmmmmmmm"
+ /* 2 */ "mmmmmmmmmmmmmmmm"
+ /* 3 */ "mmmmmmmmmmmmmmmm"
+ /* 4 */ "m...mmmmmmmmaaam"
+ /* 5 */ "m...mmmmmmmmmmmm"
+ /* 6 */ "m...mmmmmmmmmmmm"
+ /* 7 */ "m...mmmmmmmmmmmm"
+ /* 8 */ "m...mmmmmmmmmmmm"
+ /* 9 */ "a...ammmmmmmmmmm"
+ /* 10 */ "a...ammmmmmmmmmm"
+ /* 11 */ "a...aaaeemmmmmmm"
+ /* 12 */ "a....gaaammmmmmm"
+ /* 13 */ "a....gaaammmmmmm"
+ /* 14 */ "a....gaaammmaaam"
+ /* 15 */ "aaaaaaaffmmmaaam"
+
+ // Level 9
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmmcaaab"
+ /* 1 */ "mmmmmmmmmmmcaaab"
+ /* 2 */ "mmmmmmmmmmmcaaab"
+ /* 3 */ "mmmmmmmmmmmcaaab"
+ /* 4 */ "mmmmmmmmmmmcaaab"
+ /* 5 */ "mmmmmmmmmmmcaaab"
+ /* 6 */ "m...mmmmmmmcaaab"
+ /* 7 */ "m...mmmmmmmcaaab"
+ /* 8 */ "m...mmmmmmmcaaab"
+ /* 9 */ "m...mmmmmmmcaaab"
+ /* 10 */ "m...mmmmmmmcaaab"
+ /* 11 */ "m...maaaaeecaaab"
+ /* 12 */ "m......gaaaaaaab"
+ /* 13 */ "m......gaaaaaaab"
+ /* 14 */ "m......gaaaaaaab"
+ /* 15 */ "mmmmmaaaafffaaab"
+
+ // Level 10
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmmaaaaa"
+ /* 1 */ "mmmmmmmmmmmaaaaa"
+ /* 2 */ "mmmmmmmmmmmaaaaa"
+ /* 3 */ "mmmmmmmmmmmaaaaa"
+ /* 4 */ "mmmmmmmmmmmaaaaa"
+ /* 5 */ "mmmmmmmmmmmaaaaa"
+ /* 6 */ "mmmmmmmmmmmaaaaa"
+ /* 7 */ "mmmmmmmmmmmaaaaa"
+ /* 8 */ "m...mmmmmmmaaaaa"
+ /* 9 */ "m...mmmmmmmaaaaa"
+ /* 10 */ "m...mmmmmmmaaaaa"
+ /* 11 */ "m...mmmaaaaaaaaa"
+ /* 12 */ "m........gaaaaaa"
+ /* 13 */ "m........gaaaaaa"
+ /* 14 */ "m........gaaaaaa"
+ /* 15 */ "mmmmmmmaaaaaaaaa"
+
+ // Level 11
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmma...a"
+ /* 1 */ "mmmmmmmmmmma...a"
+ /* 2 */ "mmmmmmmmmmma...a"
+ /* 3 */ "mmmmmmmmmmma...a"
+ /* 4 */ "mmmmmmmmmmma...a"
+ /* 5 */ "mmmmmmmmmmma...a"
+ /* 6 */ "mmmmmmmmmmma...a"
+ /* 7 */ "mmmmmmmmmmma...a"
+ /* 8 */ "mmmmmmmmmmma...a"
+ /* 9 */ "mmmmmmmmmmma...a"
+ /* 10 */ "mmmmmmmmmmma...a"
+ /* 11 */ "mmmmmmmmmaaa...a"
+ /* 12 */ "mmmm...........a"
+ /* 13 */ "mmmm...........a"
+ /* 14 */ "mmmm...........a"
+ /* 15 */ "mmmmmmmmmaaa...a"
+
+ // Level 12
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmmm...m"
+ /* 1 */ "mmmmmmmmmmmm...m"
+ /* 2 */ "mmmmmmmmmmmm...m"
+ /* 3 */ "mmmmmmmmmmmm...m"
+ /* 4 */ "mmmmmmmmmmmm...m"
+ /* 5 */ "mmmmmmmmmmmm...m"
+ /* 6 */ "mmmmmmmmmmmm...m"
+ /* 7 */ "mmmmmmmmmmmm...m"
+ /* 8 */ "mmmmmmmmmmmm...m"
+ /* 9 */ "mmmmmmmmmmmm...m"
+ /* 10 */ "mmmmmmmmmmmm...m"
+ /* 11 */ "mmmmmmmmmmmm...m"
+ /* 12 */ "mmmmmm.........m"
+ /* 13 */ "mmmmmm.........m"
+ /* 14 */ "mmmmmm.........m"
+ /* 15 */ "mmmmmmmmmmmm...m"
+
+ // Level 13
+ /* z\x* 111111 */
+ /* * 0123456789012345 */
+ /* 0 */ "mmmmmmmmmmmm...m"
+ /* 1 */ "mmmmmmmmmmmm...m"
+ /* 2 */ "mmmmmmmmmmmm...m"
+ /* 3 */ "mmmmmmmmmmmm...m"
+ /* 4 */ "mmmmmmmmmmmm...m"
+ /* 5 */ "mmmmmmmmmmmm...m"
+ /* 6 */ "mmmmmmmmmmmm...m"
+ /* 7 */ "mmmmmmmmmmmm...m"
+ /* 8 */ "mmmmmmmmmmmm...m"
+ /* 9 */ "mmmmmmmmmmmm...m"
+ /* 10 */ "mmmmmmmmmmmm...m"
+ /* 11 */ "mmmmmmmmmmmm...m"
+ /* 12 */ "mmmmmmmm.......m"
+ /* 13 */ "mmmmmmmm.......m"
+ /* 14 */ "mmmmmmmm.......m"
+ /* 15 */ "mmmmmmmmmmmm...m",
+
+ // Connectors:
+ "0: 13, 11, 0: 2\n" /* Type 0, direction Z- */
+ "0: 13, 11, 15: 3\n" /* Type 0, direction Z+ */
+ "0: 0, 5, 2: 4\n" /* Type 0, direction X- */
+ "0: 15, 5, 2: 5\n" /* Type 0, direction X+ */,
+
+ // AllowedRotations:
+ 7, /* 1, 2, 3 CCW rotation allowed */
+
+ // Merge strategy:
+ cBlockArea::msSpongePrint,
+
+ // ShouldExtendFloor:
+ true,
+
+ // DefaultWeight:
+ 20,
+
+ // DepthWeight:
+ "",
+
+ // AddWeightIfSame:
+ 0,
+
+ // MoveToGround:
+ false,
+ }, // SlabbedBridgeStairs
+
+
+
+ ////////////////////////////////////////////////////////////////////////////////
// StairsToOpen1:
// The data has been exported from the gallery Nether, area index 27, ID 277, created by Aloe_vera
{
@@ -4460,7 +5175,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// StairsToOpen2:
// The data has been exported from the gallery Nether, area index 8, ID 35, created by xoft
{
@@ -4606,7 +5321,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Tee2x4:
// The data has been exported from the gallery Nether, area index 40, ID 291, created by Aloe_vera
{
@@ -4726,7 +5441,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Tee4x4:
// The data has been exported from the gallery Nether, area index 41, ID 292, created by Aloe_vera
{
@@ -4858,7 +5573,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// TinyCorridorCorner:
// The data has been exported from the gallery Nether, area index 66, ID 331, created by xoft
{
@@ -4957,7 +5672,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// TinyCorridorCornerChest:
// The data has been exported from the gallery Nether, area index 67, ID 332, created by Aloe_vera
{
@@ -5057,7 +5772,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// TinyCorridorCrossing:
// The data has been exported from the gallery Nether, area index 64, ID 329, created by xoft
{
@@ -5159,7 +5874,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Turret:
// The data has been exported from the gallery Nether, area index 7, ID 34, created by xoft
{
@@ -5283,7 +5998,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
const cPrefab::sDef g_NetherFortStartingPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CentralRoom:
// The data has been exported from the gallery Nether, area index 22, ID 164, created by Aloe_vera
{
diff --git a/src/Generating/Prefabs/PlainsVillagePrefabs.cpp b/src/Generating/Prefabs/PlainsVillagePrefabs.cpp
index bad8dae74..4613f76e2 100644
--- a/src/Generating/Prefabs/PlainsVillagePrefabs.cpp
+++ b/src/Generating/Prefabs/PlainsVillagePrefabs.cpp
@@ -15,7 +15,7 @@
const cPrefab::sDef g_PlainsVillagePrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BigPlantBed:
// The data has been exported from the gallery Plains, area index 26, ID 70, created by Taugrammaton
{
@@ -195,7 +195,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CobbleHouse10x5Library:
// The data has been exported from the gallery Plains, area index 23, ID 66, created by xoft
{
@@ -336,7 +336,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// DoublePlantBed:
// The data has been exported from the gallery Plains, area index 5, ID 20, created by tonibm1999
{
@@ -356,8 +356,8 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
"e: 8: 0\n" /* water */
"f: 50: 5\n" /* torch */
"g: 59: 7\n" /* crops */
- "h: 59: 0\n" /* crops */
- "i: 59: 1\n" /* crops */
+ "h: 59: 3\n" /* crops */
+ "i: 59: 5\n" /* crops */
"m: 19: 0\n" /* sponge */,
// Block data:
@@ -368,7 +368,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 1 */ "aaaaaaaaaaaaaaa"
/* 2 */ "aaaaaaaaaaaaaaa"
/* 3 */ "aaaaaaaaaaaaaaa"
- /* 4 */ "aaaaaaaaaaaaaaa"
+ /* 4 */ "aaaaaaabaaaaaaa"
/* 5 */ "aaaaaaabaaaaaaa"
/* 6 */ "aaaaaaabaaaaaaa"
/* 7 */ "aaaaaaabaaaaaaa"
@@ -405,12 +405,12 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* * 012345678901234 */
/* 0 */ "f.....f.f.....f"
/* 1 */ ".gg.gg...gg.gg."
- /* 2 */ ".gh.hg...gg.gg."
- /* 3 */ ".gh.ih...gg.gg."
- /* 4 */ ".gg.hg...gg.gg."
- /* 5 */ ".gg.hg...gg.gg."
- /* 6 */ ".ig.hg...gg.gg."
- /* 7 */ ".hg.gh...gg.gg."
+ /* 2 */ ".gg.hg...gg.gg."
+ /* 3 */ ".gg.gi...gg.gg."
+ /* 4 */ ".gg.gg...gg.gg."
+ /* 5 */ ".gg.gg...gg.gg."
+ /* 6 */ ".gg.gg...gg.gg."
+ /* 7 */ ".gg.gg...gg.gg."
/* 8 */ "f.....f.f.....f"
// Level 4
@@ -492,7 +492,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Forge:
// The data has been exported from the gallery Plains, area index 51, ID 102, created by Aloe_vera
{
@@ -692,7 +692,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// LampPost:
// The data has been exported from the gallery Plains, area index 28, ID 73, created by STR_Warrior
{
@@ -784,7 +784,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MineshaftCorridor:
// The data has been exported from the gallery Plains, area index 139, ID 447, created by STR_Warrior
{
@@ -861,7 +861,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MineshaftCrossing:
// The data has been exported from the gallery Plains, area index 171, ID 578, created by Aloe_vera
{
@@ -946,7 +946,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MineshaftCrossing:
// The data has been exported from the gallery Plains, area index 193, ID 657, created by Aloe_vera
{
@@ -1064,7 +1064,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MineshaftDoubleCrossing:
// The data has been exported from the gallery Plains, area index 172, ID 579, created by Aloe_vera
{
@@ -1189,7 +1189,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MineshaftSpiral:
// The data has been exported from the gallery Plains, area index 198, ID 662, created by Aloe_vera
{
@@ -1370,7 +1370,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MineshaftStairs:
// The data has been exported from the gallery Plains, area index 195, ID 659, created by Aloe_vera
{
@@ -1469,7 +1469,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MineshaftStairsCrossing:
// The data has been exported from the gallery Plains, area index 199, ID 663, created by Aloe_vera
{
@@ -1719,7 +1719,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MineshaftTee:
// The data has been exported from the gallery Plains, area index 194, ID 658, created by Aloe_vera
{
@@ -1819,7 +1819,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MineshaftsCorridor5:
// The data has been exported from the gallery Plains, area index 200, ID 664, created by Aloe_vera
{
@@ -1898,7 +1898,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Scarecrow:
// The data has been exported from the gallery Plains, area index 150, ID 494, created by STR_Warrior
{
@@ -1983,7 +1983,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// SinglePlantBed:
// The data has been exported from the gallery Plains, area index 17, ID 60, created by Aloe_vera
{
@@ -2108,7 +2108,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenChurchMid:
// The data has been exported from the gallery Plains, area index 58, ID 109, created by Aloe_vera
{
@@ -2418,7 +2418,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenGranary:
// The data has been exported from the gallery Plains, area index 54, ID 105, created by Aloe_vera
{
@@ -2560,7 +2560,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouse10x7Library:
// The data has been exported from the gallery Plains, area index 47, ID 98, created by Aloe_vera
{
@@ -2729,7 +2729,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouse5x5:
// The data has been exported from the gallery Plains, area index 49, ID 100, created by Aloe_vera
{
@@ -2856,7 +2856,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouse7x5:
// The data has been exported from the gallery Plains, area index 40, ID 91, created by xoft
{
@@ -2983,7 +2983,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouse9x5:
// The data has been exported from the gallery Plains, area index 41, ID 92, created by xoft
{
@@ -3117,7 +3117,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouse9x5Fence:
// The data has been exported from the gallery Plains, area index 9, ID 26, created by Aloe_vera
{
@@ -3287,7 +3287,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouse9x5Library:
// The data has been exported from the gallery Plains, area index 46, ID 97, created by Aloe_vera
{
@@ -3428,7 +3428,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouse9x7:
// The data has been exported from the gallery Plains, area index 52, ID 103, created by Aloe_vera
{
@@ -3590,7 +3590,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouse9x7Butcher:
// The data has been exported from the gallery Plains, area index 48, ID 99, created by Aloe_vera
{
@@ -3603,8 +3603,8 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
// Block definitions:
".: 0: 0\n" /* air */
- "a: 2: 0\n" /* grass */
- "b: 3: 0\n" /* dirt */
+ "a: 3: 0\n" /* dirt */
+ "b: 2: 0\n" /* grass */
"c: 4: 0\n" /* cobblestone */
"d: 67: 0\n" /* stairs */
"e: 67: 2\n" /* stairs */
@@ -3629,19 +3629,19 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
// Level 0
/* z\x* 1 */
/* * 01234567890 */
- /* 0 */ "aaaabbbaaaa"
- /* 1 */ "abbbbbbbbba"
- /* 2 */ "abbbbbbbbba"
- /* 3 */ "abbbbbbbbba"
- /* 4 */ "abbbbbbbbba"
- /* 5 */ "abbbbbbbbba"
- /* 6 */ "abbbbbbbbba"
- /* 7 */ "abbbbbbbbba"
- /* 8 */ "aabbbbbbbaa"
- /* 9 */ "aabbbbbbbaa"
- /* 10 */ "aabbbbbbbaa"
- /* 11 */ "aabbbbbbbaa"
- /* 12 */ "aabbbbbbbaa"
+ /* 0 */ "aaaaaaaaaaa"
+ /* 1 */ "aaaaaaaaaaa"
+ /* 2 */ "aaaaaaaaaaa"
+ /* 3 */ "aaaaaaaaaaa"
+ /* 4 */ "aaaaaaaaaab"
+ /* 5 */ "baaaaaaaaab"
+ /* 6 */ "aaaaaaaaaaa"
+ /* 7 */ "baaaaaaaaaa"
+ /* 8 */ "baaaaaaaaaa"
+ /* 9 */ "baaaaaaaaab"
+ /* 10 */ "aaaaaaaaaaa"
+ /* 11 */ "aaaaaaaaaba"
+ /* 12 */ "aaaaaaaaaba"
// Level 1
/* z\x* 1 */
@@ -3654,11 +3654,11 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 5 */ "mcccccccccm"
/* 6 */ "mcccccccccm"
/* 7 */ "mcccccccccm"
- /* 8 */ "mmbbbbbbbmm"
- /* 9 */ "mmbbbbbbbmm"
- /* 10 */ "mmbbbbbbbmm"
- /* 11 */ "mmbbbbbbbmm"
- /* 12 */ "mmbbbbbbbmm"
+ /* 8 */ "mmaaaaaaamm"
+ /* 9 */ "mmaaaaaaamm"
+ /* 10 */ "mmaaaaaaamm"
+ /* 11 */ "mmaaaaaaamm"
+ /* 12 */ "mmaaaaaaamm"
// Level 2
/* z\x* 1 */
@@ -3671,11 +3671,11 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 5 */ ".cggggcccc."
/* 6 */ ".cggggcccc."
/* 7 */ ".ccccccccc."
- /* 8 */ "..aaaaaaa.."
- /* 9 */ "..aaaaaaa.."
- /* 10 */ "..aaaaaaa.."
- /* 11 */ "..aaaaaaa.."
- /* 12 */ "..aaaaaaa.."
+ /* 8 */ "..bbbbbbb.."
+ /* 9 */ "mmbbbbbbbmm"
+ /* 10 */ "mmbbbbbbbmm"
+ /* 11 */ "mmbbbbbbbmm"
+ /* 12 */ "mmbbbbbbbmm"
// Level 3
/* z\x* 1 */
@@ -3689,10 +3689,10 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 6 */ ".i.......i."
/* 7 */ ".hiiijiiih."
/* 8 */ "..l.....l.."
- /* 9 */ "..l.....l.."
- /* 10 */ "..l.....l.."
- /* 11 */ "..l.....l.."
- /* 12 */ "..lllllll.."
+ /* 9 */ "mml.....lmm"
+ /* 10 */ "mml.....lmm"
+ /* 11 */ "mml.....lmm"
+ /* 12 */ "mmlllllllmm"
// Level 4
/* z\x* 1 */
@@ -3706,10 +3706,10 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 6 */ ".o.......o."
/* 7 */ ".hooipiooh."
/* 8 */ "..........."
- /* 9 */ "..........."
- /* 10 */ "..........."
- /* 11 */ "..........."
- /* 12 */ "..........."
+ /* 9 */ "mm.......mm"
+ /* 10 */ "mm.......mm"
+ /* 11 */ "mm.......mm"
+ /* 12 */ "mm.......mm"
// Level 5
/* z\x* 1 */
@@ -3723,10 +3723,10 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 6 */ ".i.......i."
/* 7 */ "uiiiiiiiiiu"
/* 8 */ "kkkkkkkkkkk"
- /* 9 */ "..........."
- /* 10 */ "..........."
- /* 11 */ "..........."
- /* 12 */ "..........."
+ /* 9 */ "mm.......mm"
+ /* 10 */ "mm.......mm"
+ /* 11 */ "mm.......mm"
+ /* 12 */ "mm.......mm"
// Level 6
/* z\x* 1 */
@@ -3740,10 +3740,10 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 6 */ "uiiiiiiiiiu"
/* 7 */ "kkkkkkkkkkk"
/* 8 */ "..........."
- /* 9 */ "..........."
- /* 10 */ "..........."
- /* 11 */ "..........."
- /* 12 */ "..........."
+ /* 9 */ "mm.......mm"
+ /* 10 */ "mm.......mm"
+ /* 11 */ "mm.......mm"
+ /* 12 */ "mm.......mm"
// Level 7
/* z\x* 1 */
@@ -3757,10 +3757,10 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 6 */ "kkkkkkkkkkk"
/* 7 */ "..........."
/* 8 */ "..........."
- /* 9 */ "..........."
- /* 10 */ "..........."
- /* 11 */ "..........."
- /* 12 */ "..........."
+ /* 9 */ "mm.......mm"
+ /* 10 */ "mm.......mm"
+ /* 11 */ "mm.......mm"
+ /* 12 */ "mm.......mm"
// Level 8
/* z\x* 1 */
@@ -3774,10 +3774,10 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 6 */ "..........."
/* 7 */ "..........."
/* 8 */ "..........."
- /* 9 */ "..........."
- /* 10 */ "..........."
- /* 11 */ "..........."
- /* 12 */ "...........",
+ /* 9 */ "mm.......mm"
+ /* 10 */ "mm.......mm"
+ /* 11 */ "mm.......mm"
+ /* 12 */ "mm.......mm",
// Connectors:
"-1: 5, 2, 0: 2\n" /* Type -1, direction Z- */,
@@ -3806,7 +3806,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouse9x7DoubleDoor:
// The data has been exported from the gallery Plains, area index 38, ID 87, created by Aloe_vera
{
@@ -3971,7 +3971,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouseL13x14:
// The data has been exported from the gallery Plains, area index 39, ID 90, created by STR_Warrior
{
@@ -4223,7 +4223,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouseL14x14:
// The data has been exported from the gallery Plains, area index 0, ID 4, created by Aloe_vera
{
@@ -4237,30 +4237,29 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
// Block definitions:
".: 0: 0\n" /* air */
"a: 4: 0\n" /* cobblestone */
- "b: 2: 0\n" /* grass */
- "c: 67: 0\n" /* stairs */
- "d: 67: 2\n" /* stairs */
- "e: 67: 1\n" /* stairs */
- "f: 5: 0\n" /* wood */
- "g: 67: 3\n" /* stairs */
- "h: 17: 0\n" /* tree */
- "i: 64: 7\n" /* wooddoorblock */
- "j: 64: 5\n" /* wooddoorblock */
- "k:102: 0\n" /* glasspane */
- "l: 64:12\n" /* wooddoorblock */
+ "b: 67: 0\n" /* stairs */
+ "c: 67: 2\n" /* stairs */
+ "d: 67: 1\n" /* stairs */
+ "e: 5: 0\n" /* wood */
+ "f: 67: 3\n" /* stairs */
+ "g: 17: 0\n" /* tree */
+ "h: 64: 7\n" /* wooddoorblock */
+ "i: 64: 5\n" /* wooddoorblock */
+ "j:102: 0\n" /* glasspane */
+ "k: 64:12\n" /* wooddoorblock */
+ "l: 53: 2\n" /* woodstairs */
"m: 19: 0\n" /* sponge */
- "n: 53: 2\n" /* woodstairs */
- "o: 53: 1\n" /* woodstairs */
- "p: 53: 7\n" /* woodstairs */
- "q: 53: 6\n" /* woodstairs */
- "r: 53: 3\n" /* woodstairs */
- "s: 53: 0\n" /* woodstairs */
- "t: 53: 5\n" /* woodstairs */
- "u: 53: 4\n" /* woodstairs */
- "v: 50: 3\n" /* torch */
- "w: 50: 2\n" /* torch */
- "x: 50: 4\n" /* torch */
- "y: 50: 1\n" /* torch */,
+ "n: 53: 1\n" /* woodstairs */
+ "o: 53: 7\n" /* woodstairs */
+ "p: 53: 6\n" /* woodstairs */
+ "q: 53: 3\n" /* woodstairs */
+ "r: 53: 0\n" /* woodstairs */
+ "s: 53: 5\n" /* woodstairs */
+ "t: 53: 4\n" /* woodstairs */
+ "u: 50: 3\n" /* torch */
+ "v: 50: 2\n" /* torch */
+ "w: 50: 4\n" /* torch */
+ "x: 50: 1\n" /* torch */,
// Block data:
// Level 0
@@ -4274,134 +4273,134 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 5 */ "maaaaaaaaaaaaaam"
/* 6 */ "maaaaaaaaaaaaaam"
/* 7 */ "maaaaaaaaaaaaaam"
- /* 8 */ "bbbbbaaaaaaaaaam"
- /* 9 */ "bbbbbbbbaaaaaaam"
- /* 10 */ "bbbbbbbbaaaaaaam"
- /* 11 */ "bbbbbbbbaaaaaaam"
- /* 12 */ "bbbbbbbbaaaaaaam"
- /* 13 */ "bbbbbbbbaaaaaaam"
- /* 14 */ "bbbbbbbbaaaaaaam"
- /* 15 */ "bbbbbbbbmmmmmmmm"
+ /* 8 */ "mmmmmaaaaaaaaaam"
+ /* 9 */ "mmmmmmmmaaaaaaam"
+ /* 10 */ "mmmmmmmmaaaaaaam"
+ /* 11 */ "mmmmmmmmaaaaaaam"
+ /* 12 */ "mmmmmmmmaaaaaaam"
+ /* 13 */ "mmmmmmmmaaaaaaam"
+ /* 14 */ "mmmmmmmmaaaaaaam"
+ /* 15 */ "mmmmmmmmmmmmmmmm"
// Level 1
/* z\x* 111111 */
/* * 0123456789012345 */
- /* 0 */ "........cde....."
+ /* 0 */ "........bcd....."
/* 1 */ ".aaaaaaaaaaaaaa."
- /* 2 */ ".affffffffffffa."
- /* 3 */ ".affffffffffffa."
- /* 4 */ ".affffffffffffa."
- /* 5 */ ".affffffffffffa."
- /* 6 */ ".affffffffffffa."
- /* 7 */ ".aaaaaaaafffffa."
- /* 8 */ ".....cgeafffffa."
- /* 9 */ "........afffffa."
- /* 10 */ "........afffffa."
- /* 11 */ "........afffffa."
- /* 12 */ "........afffffa."
- /* 13 */ "........afffffa."
- /* 14 */ "........aaaaaaa."
- /* 15 */ "................"
+ /* 2 */ ".aeeeeeeeeeeeea."
+ /* 3 */ ".aeeeeeeeeeeeea."
+ /* 4 */ ".aeeeeeeeeeeeea."
+ /* 5 */ ".aeeeeeeeeeeeea."
+ /* 6 */ ".aeeeeeeeeeeeea."
+ /* 7 */ ".aaaaaaaaeeeeea."
+ /* 8 */ ".....bfdaeeeeea."
+ /* 9 */ "mmmm....aeeeeea."
+ /* 10 */ "mmmmmmm.aeeeeea."
+ /* 11 */ "mmmmmmm.aeeeeea."
+ /* 12 */ "mmmmmmm.aeeeeea."
+ /* 13 */ "mmmmmmm.aeeeeea."
+ /* 14 */ "mmmmmmm.aaaaaaa."
+ /* 15 */ "mmmmmmm........."
// Level 2
/* z\x* 111111 */
/* * 0123456789012345 */
/* 0 */ "................"
- /* 1 */ ".hffffffhihfffh."
- /* 2 */ ".f............f."
- /* 3 */ ".f............f."
- /* 4 */ ".f............f."
- /* 5 */ ".f............f."
- /* 6 */ ".f............f."
- /* 7 */ ".hffffjfh.....f."
- /* 8 */ "........f.....f."
- /* 9 */ "........f.....f."
- /* 10 */ "........f.....f."
- /* 11 */ "........f.....f."
- /* 12 */ "........f.....f."
- /* 13 */ "........f.....f."
- /* 14 */ "........hfffffh."
- /* 15 */ "................"
+ /* 1 */ ".geeeeeeghgeeeg."
+ /* 2 */ ".e............e."
+ /* 3 */ ".e............e."
+ /* 4 */ ".e............e."
+ /* 5 */ ".e............e."
+ /* 6 */ ".e............e."
+ /* 7 */ ".geeeeieg.....e."
+ /* 8 */ "........e.....e."
+ /* 9 */ "mmmm....e.....e."
+ /* 10 */ "mmmmmmm.e.....e."
+ /* 11 */ "mmmmmmm.e.....e."
+ /* 12 */ "mmmmmmm.e.....e."
+ /* 13 */ "mmmmmmm.e.....e."
+ /* 14 */ "mmmmmmm.geeeeeg."
+ /* 15 */ "mmmmmmm........."
// Level 3
/* z\x* 111111 */
/* * 0123456789012345 */
/* 0 */ "................"
- /* 1 */ ".hfkkfkkhlhkkfh."
- /* 2 */ ".k............f."
- /* 3 */ ".k............k."
- /* 4 */ ".k............k."
- /* 5 */ ".k............f."
- /* 6 */ ".k............k."
- /* 7 */ ".hfkkflfh.....k."
- /* 8 */ "........f.....f."
- /* 9 */ "........k.....k."
- /* 10 */ "........k.....k."
- /* 11 */ "........f.....f."
- /* 12 */ "........k.....k."
- /* 13 */ "........k.....k."
- /* 14 */ "........hkkkkkh."
- /* 15 */ "................"
+ /* 1 */ ".gejjejjgkgjjeg."
+ /* 2 */ ".j............e."
+ /* 3 */ ".j............j."
+ /* 4 */ ".j............j."
+ /* 5 */ ".j............e."
+ /* 6 */ ".j............j."
+ /* 7 */ ".gejjekeg.....j."
+ /* 8 */ "........e.....e."
+ /* 9 */ "mmmm....j.....j."
+ /* 10 */ "mmmmmmm.j.....j."
+ /* 11 */ "mmmmmmm.e.....e."
+ /* 12 */ "mmmmmmm.j.....j."
+ /* 13 */ "mmmmmmm.j.....j."
+ /* 14 */ "mmmmmmm.gjjjjjg."
+ /* 15 */ "mmmmmmm........."
// Level 4
/* z\x* 111111 */
/* * 0123456789012345 */
- /* 0 */ "nnnnnnnnnnnnnnno"
- /* 1 */ "phffffffhfhfffho"
- /* 2 */ ".f............fo"
- /* 3 */ ".f............fo"
- /* 4 */ ".f............fo"
- /* 5 */ ".f............fo"
- /* 6 */ ".f............fo"
- /* 7 */ "qhffffffh.....fo"
- /* 8 */ "rrrrrrrsf.....fo"
- /* 9 */ ".......sf.....fo"
- /* 10 */ ".......sf.....fo"
- /* 11 */ ".......sf.....fo"
- /* 12 */ ".......sf.....fo"
- /* 13 */ ".......sf.....fo"
- /* 14 */ ".......shfffffho"
- /* 15 */ ".......st.....uo"
+ /* 0 */ "llllllllllllllln"
+ /* 1 */ "ogeeeeeegegeeegn"
+ /* 2 */ ".e............en"
+ /* 3 */ ".e............en"
+ /* 4 */ ".e............en"
+ /* 5 */ ".e............en"
+ /* 6 */ ".e............en"
+ /* 7 */ "pgeeeeeeg.....en"
+ /* 8 */ "qqqqqqqre.....en"
+ /* 9 */ "mmmm...re.....en"
+ /* 10 */ "mmmmmmmre.....en"
+ /* 11 */ "mmmmmmmre.....en"
+ /* 12 */ "mmmmmmmre.....en"
+ /* 13 */ "mmmmmmmre.....en"
+ /* 14 */ "mmmmmmmrgeeeeegn"
+ /* 15 */ "mmmmmmmrs.....tn"
// Level 5
/* z\x* 111111 */
/* * 0123456789012345 */
/* 0 */ "................"
- /* 1 */ "nnnnnnnnnnnnnnn."
- /* 2 */ "pfffffffffffffo."
- /* 3 */ ".f.........v.fo."
- /* 4 */ ".f..........wfo."
- /* 5 */ ".f......x....fo."
- /* 6 */ "qfffffffff...fo."
- /* 7 */ "rrrrrrrrsfy..fo."
- /* 8 */ "........sf...fo."
- /* 9 */ "........sf...fo."
- /* 10 */ "........sf...fo."
- /* 11 */ "........sf...fo."
- /* 12 */ "........sf...fo."
- /* 13 */ "........sf...fo."
- /* 14 */ "........sfffffo."
- /* 15 */ "........st...uo."
+ /* 1 */ "lllllllllllllll."
+ /* 2 */ "oeeeeeeeeeeeeen."
+ /* 3 */ ".e.........u.en."
+ /* 4 */ ".e..........ven."
+ /* 5 */ ".e......w....en."
+ /* 6 */ "peeeeeeeee...en."
+ /* 7 */ "qqqqqqqqrex..en."
+ /* 8 */ "........re...en."
+ /* 9 */ "mmmm....re...en."
+ /* 10 */ "mmmmmmm.re...en."
+ /* 11 */ "mmmmmmm.re...en."
+ /* 12 */ "mmmmmmm.re...en."
+ /* 13 */ "mmmmmmm.re...en."
+ /* 14 */ "mmmmmmm.reeeeen."
+ /* 15 */ "mmmmmmm.rs...tn."
// Level 6
/* z\x* 111111 */
/* * 0123456789012345 */
/* 0 */ "................"
/* 1 */ "................"
- /* 2 */ "nnnnnnnnnnnnno.."
- /* 3 */ "pffffffffffffo.."
- /* 4 */ ".fy.........fo.."
- /* 5 */ "qffffffffff.fo.."
- /* 6 */ "rrrrrrrrrsf.fo.."
- /* 7 */ ".........sf.fo.."
- /* 8 */ ".........sf.fo.."
- /* 9 */ ".........sf.fo.."
- /* 10 */ ".........sf.fo.."
- /* 11 */ ".........sf.fo.."
- /* 12 */ ".........sf.fo.."
- /* 13 */ ".........sfxfo.."
- /* 14 */ ".........sfffo.."
- /* 15 */ ".........st.uo.."
+ /* 2 */ "llllllllllllln.."
+ /* 3 */ "oeeeeeeeeeeeen.."
+ /* 4 */ ".ex.........en.."
+ /* 5 */ "peeeeeeeeee.en.."
+ /* 6 */ "qqqqqqqqqre.en.."
+ /* 7 */ ".........re.en.."
+ /* 8 */ ".........re.en.."
+ /* 9 */ "mmmm.....re.en.."
+ /* 10 */ "mmmmmmm..re.en.."
+ /* 11 */ "mmmmmmm..re.en.."
+ /* 12 */ "mmmmmmm..re.en.."
+ /* 13 */ "mmmmmmm..rewen.."
+ /* 14 */ "mmmmmmm..reeen.."
+ /* 15 */ "mmmmmmm..rs.tn.."
// Level 7
/* z\x* 111111 */
@@ -4409,19 +4408,19 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
/* 0 */ "................"
/* 1 */ "................"
/* 2 */ "................"
- /* 3 */ "nnnnnnnnnnnnn..."
- /* 4 */ "ffffffffffffo..."
- /* 5 */ "rrrrrrrrrrsfo..."
- /* 6 */ "..........sfo..."
- /* 7 */ "..........sfo..."
- /* 8 */ "..........sfo..."
- /* 9 */ "..........sfo..."
- /* 10 */ "..........sfo..."
- /* 11 */ "..........sfo..."
- /* 12 */ "..........sfo..."
- /* 13 */ "..........sfo..."
- /* 14 */ "..........sfo..."
- /* 15 */ "..........sfo...",
+ /* 3 */ "lllllllllllll..."
+ /* 4 */ "eeeeeeeeeeeen..."
+ /* 5 */ "qqqqqqqqqqren..."
+ /* 6 */ "..........ren..."
+ /* 7 */ "..........ren..."
+ /* 8 */ "..........ren..."
+ /* 9 */ "mmmm......ren..."
+ /* 10 */ "mmmmmmm...ren..."
+ /* 11 */ "mmmmmmm...ren..."
+ /* 12 */ "mmmmmmm...ren..."
+ /* 13 */ "mmmmmmm...ren..."
+ /* 14 */ "mmmmmmm...ren..."
+ /* 15 */ "mmmmmmm...ren...",
// Connectors:
"-1: 9, 1, 0: 2\n" /* Type -1, direction Z- */,
@@ -4450,7 +4449,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouseL9x9:
// The data has been exported from the gallery Plains, area index 42, ID 93, created by xoft
{
@@ -4619,7 +4618,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenHouseU13x9:
// The data has been exported from the gallery Plains, area index 43, ID 94, created by xoft
{
@@ -4786,7 +4785,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenMill5x5:
// The data has been exported from the gallery Plains, area index 60, ID 111, created by Aloe_vera
{
@@ -5121,7 +5120,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WoodenStables:
// The data has been exported from the gallery Plains, area index 55, ID 106, created by Aloe_vera
{
@@ -5307,7 +5306,7 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
const cPrefab::sDef g_PlainsVillageStartingPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CobbleWell4x4:
// The data has been exported from the gallery Plains, area index 1, ID 5, created by Aloe_vera
{
@@ -5448,7 +5447,7 @@ const cPrefab::sDef g_PlainsVillageStartingPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MineEntrance:
// The data has been exported from the gallery Plains, area index 138, ID 446, created by STR_Warrior
{
@@ -5897,7 +5896,7 @@ const cPrefab::sDef g_PlainsVillageStartingPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// RoofedWell:
// The data has been exported from the gallery Plains, area index 119, ID 271, created by STR_Warrior
{
diff --git a/src/Generating/Prefabs/RainbowRoadPrefabs.cpp b/src/Generating/Prefabs/RainbowRoadPrefabs.cpp
index 1a3765c5a..bf7b1b096 100644
--- a/src/Generating/Prefabs/RainbowRoadPrefabs.cpp
+++ b/src/Generating/Prefabs/RainbowRoadPrefabs.cpp
@@ -15,7 +15,7 @@
const cPrefab::sDef g_RainbowRoadPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CurveDouble:
// The data has been exported from the gallery Cube, area index 89, ID 467, created by Aloe_vera
{
@@ -85,7 +85,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CurveDownFromTopSingle:
// The data has been exported from the gallery Cube, area index 100, ID 478, created by Aloe_vera
{
@@ -255,7 +255,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CurveSingle:
// The data has been exported from the gallery Cube, area index 84, ID 462, created by Aloe_vera
{
@@ -320,7 +320,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CurveSingleLeft:
// The data has been exported from the gallery Cube, area index 97, ID 475, created by Aloe_vera
{
@@ -385,7 +385,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CurveUpDouble:
// The data has been exported from the gallery Cube, area index 92, ID 470, created by Aloe_vera
{
@@ -581,7 +581,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CurveUpSingle:
// The data has been exported from the gallery Cube, area index 87, ID 465, created by Aloe_vera
{
@@ -751,7 +751,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// SlopeDownFromTopSingle:
// The data has been exported from the gallery Cube, area index 98, ID 476, created by Aloe_vera
{
@@ -881,7 +881,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// SlopeUpDouble:
// The data has been exported from the gallery Cube, area index 90, ID 468, created by Aloe_vera
{
@@ -1061,7 +1061,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// SlopeUpSingle:
// The data has been exported from the gallery Cube, area index 85, ID 463, created by Aloe_vera
{
@@ -1191,7 +1191,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// SplitTee:
// The data has been exported from the gallery Cube, area index 93, ID 471, created by Aloe_vera
{
@@ -1261,7 +1261,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// StraightDouble:
// The data has been exported from the gallery Cube, area index 88, ID 466, created by Aloe_vera
{
@@ -1335,7 +1335,7 @@ const cPrefab::sDef g_RainbowRoadPrefabs[] =
const cPrefab::sDef g_RainbowRoadStartingPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// StraightSingle:
// The data has been exported from the gallery Cube, area index 83, ID 461, created by Aloe_vera
{
diff --git a/src/Generating/Prefabs/SandFlatRoofVillagePrefabs.cpp b/src/Generating/Prefabs/SandFlatRoofVillagePrefabs.cpp
index 44e947952..3328ee210 100644
--- a/src/Generating/Prefabs/SandFlatRoofVillagePrefabs.cpp
+++ b/src/Generating/Prefabs/SandFlatRoofVillagePrefabs.cpp
@@ -15,7 +15,7 @@
const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Forge:
// The data has been exported from the gallery Desert, area index 32, ID 173, created by Aloe_vera
{
@@ -162,7 +162,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House11x7:
// The data has been exported from the gallery Desert, area index 31, ID 172, created by Aloe_vera
{
@@ -301,7 +301,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House5x4:
// The data has been exported from the gallery Desert, area index 25, ID 166, created by Aloe_vera
{
@@ -412,7 +412,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House5x5:
// The data has been exported from the gallery Desert, area index 26, ID 167, created by Aloe_vera
{
@@ -530,7 +530,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House7x5:
// The data has been exported from the gallery Desert, area index 27, ID 168, created by Aloe_vera
{
@@ -648,7 +648,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House8x5:
// The data has been exported from the gallery Desert, area index 28, ID 169, created by Aloe_vera
{
@@ -772,7 +772,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House8x7:
// The data has been exported from the gallery Desert, area index 29, ID 170, created by Aloe_vera
{
@@ -910,7 +910,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House9x7:
// The data has been exported from the gallery Desert, area index 30, ID 171, created by Aloe_vera
{
@@ -1049,7 +1049,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseL13x12:
// The data has been exported from the gallery Desert, area index 53, ID 345, created by jakibaki
{
@@ -1220,7 +1220,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// MarketStall:
// The data has been exported from the gallery Desert, area index 34, ID 175, created by Aloe_vera
{
@@ -1330,7 +1330,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Marketplace:
// The data has been exported from the gallery Desert, area index 38, ID 261, created by Aloe_vera
{
@@ -1472,7 +1472,7 @@ const cPrefab::sDef g_SandFlatRoofVillagePrefabs[] =
const cPrefab::sDef g_SandFlatRoofVillageStartingPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Well:
// The data has been exported from the gallery Desert, area index 44, ID 275, created by Aloe_vera
{
diff --git a/src/Generating/Prefabs/SandVillagePrefabs.cpp b/src/Generating/Prefabs/SandVillagePrefabs.cpp
index 72881a678..c63f8161b 100644
--- a/src/Generating/Prefabs/SandVillagePrefabs.cpp
+++ b/src/Generating/Prefabs/SandVillagePrefabs.cpp
@@ -15,7 +15,7 @@
const cPrefab::sDef g_SandVillagePrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// DoubleField:
// The data has been exported from the gallery Desert, area index 5, ID 75, created by tonibm1999
{
@@ -102,7 +102,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House11x7:
// The data has been exported from the gallery Desert, area index 6, ID 81, created by Aloe_vera
{
@@ -236,7 +236,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House11x9:
// The data has been exported from the gallery Desert, area index 11, ID 115, created by xoft
{
@@ -395,7 +395,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House13x7:
// The data has been exported from the gallery Desert, area index 15, ID 125, created by Aloe_vera
{
@@ -527,7 +527,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House13x9:
// The data has been exported from the gallery Desert, area index 12, ID 116, created by xoft
{
@@ -686,7 +686,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House15x9:
// The data has been exported from the gallery Desert, area index 13, ID 118, created by xoft
{
@@ -845,7 +845,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House16x9:
// The data has been exported from the gallery Desert, area index 16, ID 126, created by Aloe_vera
{
@@ -1004,7 +1004,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House7x7:
// The data has been exported from the gallery Desert, area index 8, ID 112, created by Aloe_vera
{
@@ -1128,7 +1128,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House9x7:
// The data has been exported from the gallery Desert, area index 9, ID 113, created by xoft
{
@@ -1253,7 +1253,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// House9x9:
// The data has been exported from the gallery Desert, area index 10, ID 114, created by xoft
{
@@ -1404,7 +1404,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseL14x12:
// The data has been exported from the gallery Desert, area index 14, ID 124, created by Aloe_vera
{
@@ -1592,7 +1592,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// HouseL14x12:
// The data has been exported from the gallery Desert, area index 7, ID 82, created by Aloe_vera
{
@@ -1763,7 +1763,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// SingleField:
// The data has been exported from the gallery Desert, area index 17, ID 127, created by Aloe_vera
{
@@ -1844,7 +1844,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// SmallHut:
// The data has been exported from the gallery Desert, area index 4, ID 68, created by tonibm1999
{
@@ -1955,7 +1955,7 @@ const cPrefab::sDef g_SandVillagePrefabs[] =
const cPrefab::sDef g_SandVillageStartingPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// RoofedWell:
// The data has been exported from the gallery Desert, area index 43, ID 274, created by Aloe_vera
{
@@ -2155,7 +2155,7 @@ const cPrefab::sDef g_SandVillageStartingPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Well:
// The data has been exported from the gallery Desert, area index 0, ID 1, created by Aloe_vera
{
diff --git a/src/Generating/Prefabs/TestRailsPrefabs.cpp b/src/Generating/Prefabs/TestRailsPrefabs.cpp
index 3444cb1fa..f58b95225 100644
--- a/src/Generating/Prefabs/TestRailsPrefabs.cpp
+++ b/src/Generating/Prefabs/TestRailsPrefabs.cpp
@@ -15,7 +15,7 @@
const cPrefab::sDef g_TestRailsPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// ActivatorRail:
// The data has been exported from the gallery Plains, area index 251, ID 746, created by Aloe_vera
{
@@ -104,7 +104,7 @@ const cPrefab::sDef g_TestRailsPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// DetectorRail:
// The data has been exported from the gallery Plains, area index 250, ID 745, created by Aloe_vera
{
@@ -193,7 +193,7 @@ const cPrefab::sDef g_TestRailsPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// PowerRail:
// The data has been exported from the gallery Plains, area index 248, ID 743, created by Aloe_vera
{
@@ -284,7 +284,7 @@ const cPrefab::sDef g_TestRailsPrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// RegularRail:
// The data has been exported from the gallery Plains, area index 247, ID 742, created by Aloe_vera
{
@@ -383,7 +383,7 @@ const cPrefab::sDef g_TestRailsPrefabs[] =
const cPrefab::sDef g_TestRailsStartingPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CentralPiece:
// The data has been exported from the gallery Plains, area index 249, ID 744, created by Aloe_vera
{
diff --git a/src/Generating/Prefabs/UnderwaterBasePrefabs.cpp b/src/Generating/Prefabs/UnderwaterBasePrefabs.cpp
index 691d8aa9d..1655f50b9 100644
--- a/src/Generating/Prefabs/UnderwaterBasePrefabs.cpp
+++ b/src/Generating/Prefabs/UnderwaterBasePrefabs.cpp
@@ -15,7 +15,7 @@
const cPrefab::sDef g_UnderwaterBasePrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// BrokenRoom:
// The data has been exported from the gallery Water, area index 49, ID 680, created by STR_Warrior
{
@@ -178,7 +178,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// Corridor16:
// The data has been exported from the gallery Water, area index 25, ID 566, created by xoft
{
@@ -265,7 +265,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CorridorCorner:
// The data has been exported from the gallery Water, area index 26, ID 569, created by xoft
{
@@ -380,7 +380,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CorridorCrossing:
// The data has been exported from the gallery Water, area index 31, ID 581, created by LO1ZB
{
@@ -526,7 +526,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CorridorStairs:
// The data has been exported from the gallery Water, area index 32, ID 582, created by LO1ZB
{
@@ -656,7 +656,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CorridorTee:
// The data has been exported from the gallery Water, area index 29, ID 576, created by LO1ZB
{
@@ -775,7 +775,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// ViewingCorner:
// The data has been exported from the gallery Water, area index 40, ID 613, created by LO1ZB
{
@@ -958,7 +958,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// ViewingCorridor:
// The data has been exported from the gallery Water, area index 27, ID 571, created by LO1ZB
{
@@ -1065,7 +1065,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// ViewingCorridorBulge:
// The data has been exported from the gallery Water, area index 42, ID 615, created by LO1ZB
{
@@ -1280,7 +1280,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// ViewingCrossing:
// The data has been exported from the gallery Water, area index 38, ID 611, created by LO1ZB
{
@@ -1483,7 +1483,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// ViewingEnd:
// The data has been exported from the gallery Water, area index 41, ID 614, created by LO1ZB
{
@@ -1648,7 +1648,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// ViewingTee:
// The data has been exported from the gallery Water, area index 39, ID 612, created by LO1ZB
{
@@ -1850,7 +1850,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// WaterfallRoom:
// The data has been exported from the gallery Water, area index 50, ID 681, created by Aloe_vera
{
@@ -2059,7 +2059,7 @@ const cPrefab::sDef g_UnderwaterBasePrefabs[] =
const cPrefab::sDef g_UnderwaterBaseStartingPrefabs[] =
{
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
// CentralRoom:
// The data has been exported from the gallery Water, area index 24, ID 564, created by xoft
{
diff --git a/src/Generating/RainbowRoadsGen.cpp b/src/Generating/RainbowRoadsGen.cpp
index 3b0ff7df8..c3c07cdec 100644
--- a/src/Generating/RainbowRoadsGen.cpp
+++ b/src/Generating/RainbowRoadsGen.cpp
@@ -18,7 +18,7 @@ static cPrefabPiecePool g_RainbowRoads(g_RainbowRoadPrefabs, g_RainbowRoadPrefab
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cRainbowRoadsGen::cRainbowRoads:
class cRainbowRoadsGen::cRainbowRoads :
@@ -86,7 +86,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cRainbowRoadsGen:
diff --git a/src/Generating/Ravines.cpp b/src/Generating/Ravines.cpp
index 24f2cc3ab..70b9d0b62 100644
--- a/src/Generating/Ravines.cpp
+++ b/src/Generating/Ravines.cpp
@@ -77,7 +77,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenRavines:
cStructGenRavines::cStructGenRavines(int a_Seed, int a_Size) :
@@ -101,7 +101,7 @@ cGridStructGen::cStructurePtr cStructGenRavines::CreateStructure(int a_GridX, in
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenRavines::cRavine
cStructGenRavines::cRavine::cRavine(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_Size, cNoise & a_Noise) :
@@ -283,38 +283,38 @@ void cStructGenRavines::cRavine::FinishLinear(void)
AString cStructGenRavines::cRavine::ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) const
{
AString SVG;
- AppendPrintf(SVG, "<path style=\"fill:none;stroke:#%06x;stroke-width:1px;\"\nd=\"", a_Color);
- char Prefix = 'M'; // The first point needs "M" prefix, all the others need "L"
- for (cRavDefPoints::const_iterator itr = m_Points.begin(); itr != m_Points.end(); ++itr)
- {
- AppendPrintf(SVG, "%c %d,%d ", Prefix, a_OffsetX + itr->m_BlockX, a_OffsetZ + itr->m_BlockZ);
+ AppendPrintf(SVG, "<path style=\"fill:none;stroke:#%06x;stroke-width:1px;\"\nd=\"", a_Color);
+ char Prefix = 'M'; // The first point needs "M" prefix, all the others need "L"
+ for (cRavDefPoints::const_iterator itr = m_Points.begin(); itr != m_Points.end(); ++itr)
+ {
+ AppendPrintf(SVG, "%c %d, %d ", Prefix, a_OffsetX + itr->m_BlockX, a_OffsetZ + itr->m_BlockZ);
Prefix = 'L';
- }
- SVG.append("\"/>\n");
-
- // Base point highlight:
- AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
+ }
+ SVG.append("\"/>\n");
+
+ // Base point highlight:
+ AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d, %d L %d, %d\"/>\n",
a_OffsetX + m_OriginX - 5, a_OffsetZ + m_OriginZ, a_OffsetX + m_OriginX + 5, a_OffsetZ + m_OriginZ
);
- AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
+ AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d, %d L %d, %d\"/>\n",
a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ - 5, a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ + 5
);
// A gray line from the base point to the first point of the ravine, for identification:
- AppendPrintf(SVG, "<path style=\"fill:none;stroke:#cfcfcf;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
+ AppendPrintf(SVG, "<path style=\"fill:none;stroke:#cfcfcf;stroke-width:1px;\"\nd=\"M %d, %d L %d, %d\"/>\n",
a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ, a_OffsetX + m_Points.front().m_BlockX, a_OffsetZ + m_Points.front().m_BlockZ
);
// Offset guides:
if (a_OffsetX > 0)
{
- AppendPrintf(SVG, "<path style=\"fill:none;stroke:#0000ff;stroke-width:1px;\"\nd=\"M %d,0 L %d,1024\"/>\n",
+ AppendPrintf(SVG, "<path style=\"fill:none;stroke:#0000ff;stroke-width:1px;\"\nd=\"M %d, 0 L %d, 1024\"/>\n",
a_OffsetX, a_OffsetX
);
}
if (a_OffsetZ > 0)
{
- AppendPrintf(SVG, "<path style=\"fill:none;stroke:#0000ff;stroke-width:1px;\"\nd=\"M 0,%d L 1024,%d\"/>\n",
+ AppendPrintf(SVG, "<path style=\"fill:none;stroke:#0000ff;stroke-width:1px;\"\nd=\"M 0, %d L 1024, %d\"/>\n",
a_OffsetZ, a_OffsetZ
);
}
diff --git a/src/Generating/RoughRavines.cpp b/src/Generating/RoughRavines.cpp
new file mode 100644
index 000000000..2ee3704b3
--- /dev/null
+++ b/src/Generating/RoughRavines.cpp
@@ -0,0 +1,300 @@
+
+// RoughRavines.cpp
+
+// Implements the cRoughRavines class representing the rough ravine generator
+
+#include "Globals.h"
+
+#include "RoughRavines.h"
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cRoughRavine:
+
+class cRoughRavine :
+ public cGridStructGen::cStructure
+{
+ typedef cGridStructGen::cStructure super;
+
+public:
+ cRoughRavine(
+ int a_Seed, int a_Size,
+ float a_CenterWidth, float a_Roughness,
+ float a_FloorHeightEdge1, float a_FloorHeightEdge2, float a_FloorHeightCenter,
+ float a_CeilingHeightEdge1, float a_CeilingHeightEdge2, float a_CeilingHeightCenter,
+ int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ
+ ) :
+ super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
+ m_Seed(a_Seed + 100),
+ m_Noise(a_Seed + 100),
+ m_Roughness(a_Roughness)
+ {
+ // Create the basic structure - 2 lines meeting at the centerpoint:
+ int Max = 2 * a_Size;
+ int Half = a_Size; // m_DefPoints[Half] will be the centerpoint
+ m_DefPoints.resize(Max + 1);
+ int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7;
+ float Len = (float)a_Size;
+ float Angle = (float)rnd; // Angle is in radians, will be wrapped in the "sin" and "cos" operations
+ float OfsX = sin(Angle) * Len;
+ float OfsZ = cos(Angle) * Len;
+ m_DefPoints[0].Set (a_OriginX - OfsX, a_OriginZ - OfsZ, 1, a_CeilingHeightEdge1, a_FloorHeightEdge1);
+ m_DefPoints[Half].Set((float)a_OriginX, (float)a_OriginZ, a_CenterWidth, a_CeilingHeightCenter, a_FloorHeightCenter);
+ m_DefPoints[Max].Set (a_OriginX + OfsX, a_OriginZ + OfsZ, 1, a_CeilingHeightEdge2, a_FloorHeightEdge2);
+
+ // Calculate the points in between, recursively:
+ SubdivideLine(0, Half);
+ SubdivideLine(Half, Max);
+
+ // Initialize the per-height radius modifiers:
+ InitPerHeightRadius(a_GridX, a_GridZ);
+ }
+
+protected:
+ struct sRavineDefPoint
+ {
+ float m_X;
+ float m_Z;
+ float m_Radius;
+ float m_Top;
+ float m_Bottom;
+
+ void Set(float a_X, float a_Z, float a_Radius, float a_Top, float a_Bottom)
+ {
+ m_X = a_X;
+ m_Z = a_Z;
+ m_Radius = a_Radius;
+ m_Top = a_Top;
+ m_Bottom = a_Bottom;
+ }
+ };
+ typedef std::vector<sRavineDefPoint> sRavineDefPoints;
+
+ int m_Seed;
+
+ cNoise m_Noise;
+
+ int m_MaxSize;
+
+ sRavineDefPoints m_DefPoints;
+
+ float m_Roughness;
+
+ /** Number to add to the radius based on the height. This creates the "ledges" in the ravine walls. */
+ float m_PerHeightRadius[cChunkDef::Height];
+
+
+ /** Recursively subdivides the line between the points of the specified index.
+ Sets the midpoint to the center of the line plus or minus a random offset, then calls itself for each half
+ of the new line. */
+ void SubdivideLine(int a_Idx1, int a_Idx2)
+ {
+ // Calculate the midpoint:
+ const sRavineDefPoint & p1 = m_DefPoints[a_Idx1];
+ const sRavineDefPoint & p2 = m_DefPoints[a_Idx2];
+ float MidX = (p1.m_X + p2.m_X) / 2;
+ float MidZ = (p1.m_Z + p2.m_Z) / 2;
+ float MidR = (p1.m_Radius + p2.m_Radius) / 2 + 0.1f;
+ float MidT = (p1.m_Top + p2.m_Top) / 2;
+ float MidB = (p1.m_Bottom + p2.m_Bottom) / 2;
+
+ // Adjust the midpoint by a small amount of perpendicular vector in a random one of its two directions:
+ float dx = p2.m_X - p1.m_X;
+ float dz = p2.m_Z - p1.m_Z;
+ if ((m_Noise.IntNoise2DInt((int)MidX, (int)MidZ) / 11) % 2 == 0)
+ {
+ MidX += dz * m_Roughness;
+ MidZ -= dx * m_Roughness;
+ }
+ else
+ {
+ MidX -= dz * m_Roughness;
+ MidZ += dx * m_Roughness;
+ }
+ int MidIdx = (a_Idx1 + a_Idx2) / 2;
+ m_DefPoints[MidIdx].Set(MidX, MidZ, MidR, MidT, MidB);
+
+ // Recurse the two halves, if they are worth recursing:
+ if (MidIdx - a_Idx1 > 1)
+ {
+ SubdivideLine(a_Idx1, MidIdx);
+ }
+ if (a_Idx2 - MidIdx > 1)
+ {
+ SubdivideLine(MidIdx, a_Idx2);
+ }
+ }
+
+
+ void InitPerHeightRadius(int a_GridX, int a_GridZ)
+ {
+ int h = 0;
+ while (h < cChunkDef::Height)
+ {
+ m_Noise.SetSeed(m_Seed + h);
+ int rnd = m_Noise.IntNoise2DInt(a_GridX, a_GridZ) / 13;
+ int NumBlocks = (rnd % 3) + 2;
+ rnd = rnd / 4;
+ float Val = (float)(rnd % 256) / 128 - 1; // Random float in range [-1, +1]
+ if (h + NumBlocks > cChunkDef::Height)
+ {
+ NumBlocks = cChunkDef::Height - h;
+ }
+ for (int i = 0; i < NumBlocks; i++)
+ {
+ m_PerHeightRadius[h + i] = Val;
+ }
+ h += NumBlocks;
+ }
+ }
+
+
+ virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override
+ {
+ int BlockStartX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
+ int BlockStartZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
+ int BlockEndX = BlockStartX + cChunkDef::Width;
+ int BlockEndZ = BlockStartZ + cChunkDef::Width;
+ for (sRavineDefPoints::const_iterator itr = m_DefPoints.begin(), end = m_DefPoints.end(); itr != end; ++itr)
+ {
+ if (
+ (ceilf (itr->m_X + itr->m_Radius + 2) < BlockStartX) ||
+ (floorf(itr->m_X - itr->m_Radius - 2) > BlockEndX) ||
+ (ceilf (itr->m_Z + itr->m_Radius + 2) < BlockStartZ) ||
+ (floorf(itr->m_Z - itr->m_Radius - 2) > BlockEndZ)
+ )
+ {
+ // Cannot intersect, bail out early
+ continue;
+ }
+
+ // Carve out a cylinder around the xz point, up to (m_Radius + 2) in diameter, from Bottom to Top:
+ // On each height level, use m_PerHeightRadius[] to modify the actual radius used
+ // EnlargedRadiusSq is the square of the radius enlarged by the maximum m_PerHeightRadius offset - anything outside it will never be touched.
+ float RadiusSq = (itr->m_Radius + 2) * (itr->m_Radius + 2);
+ float DifX = BlockStartX - itr->m_X; // substitution for faster calc
+ float DifZ = BlockStartZ - itr->m_Z; // substitution for faster calc
+ for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++)
+ {
+ #ifdef _DEBUG
+ // DEBUG: Make the roughravine shapepoints visible on a single layer (so that we can see with Minutor what's going on)
+ if ((DifX + x == 0) && (DifZ + z == 0))
+ {
+ a_ChunkDesc.SetBlockType(x, 4, z, E_BLOCK_LAPIS_ORE);
+ }
+ #endif // _DEBUG
+
+ // If the column is outside the enlarged radius, bail out completely
+ float DistSq = (DifX + x) * (DifX + x) + (DifZ + z) * (DifZ + z);
+ if (DistSq > RadiusSq)
+ {
+ continue;
+ }
+
+ int Top = std::min((int)ceilf(itr->m_Top), +cChunkDef::Height);
+ for (int y = std::max((int)floorf(itr->m_Bottom), 1); y <= Top; y++)
+ {
+ if ((itr->m_Radius + m_PerHeightRadius[y]) * (itr->m_Radius + m_PerHeightRadius[y]) < DistSq)
+ {
+ continue;
+ }
+
+ if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z)))
+ {
+ a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR);
+ }
+ } // for y
+ } // for x, z - a_BlockTypes
+ } // for itr - m_Points[]
+ }
+};
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cRoughRavines:
+
+cRoughRavines::cRoughRavines(
+ int a_Seed,
+ int a_MaxSize, int a_MinSize,
+ float a_MaxCenterWidth, float a_MinCenterWidth,
+ float a_MaxRoughness, float a_MinRoughness,
+ float a_MaxFloorHeightEdge, float a_MinFloorHeightEdge,
+ float a_MaxFloorHeightCenter, float a_MinFloorHeightCenter,
+ float a_MaxCeilingHeightEdge, float a_MinCeilingHeightEdge,
+ float a_MaxCeilingHeightCenter, float a_MinCeilingHeightCenter,
+ int a_GridSize, int a_MaxOffset
+) :
+ super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 64),
+ m_Seed(a_Seed),
+ m_MaxSize(a_MaxSize),
+ m_MinSize(a_MinSize),
+ m_MaxCenterWidth(a_MaxCenterWidth),
+ m_MinCenterWidth(a_MinCenterWidth),
+ m_MaxRoughness(a_MaxRoughness),
+ m_MinRoughness(a_MinRoughness),
+ m_MaxFloorHeightEdge(a_MaxFloorHeightEdge),
+ m_MinFloorHeightEdge(a_MinFloorHeightEdge),
+ m_MaxFloorHeightCenter(a_MaxFloorHeightCenter),
+ m_MinFloorHeightCenter(a_MinFloorHeightCenter),
+ m_MaxCeilingHeightEdge(a_MaxCeilingHeightEdge),
+ m_MinCeilingHeightEdge(a_MinCeilingHeightEdge),
+ m_MaxCeilingHeightCenter(a_MaxCeilingHeightCenter),
+ m_MinCeilingHeightCenter(a_MinCeilingHeightCenter)
+{
+ if (m_MinSize > m_MaxSize)
+ {
+ std::swap(m_MinSize, m_MaxSize);
+ std::swap(a_MinSize, a_MaxSize);
+ }
+ if (m_MaxSize < 16)
+ {
+ m_MaxSize = 16;
+ LOGWARNING("RoughRavines: MaxSize too small, adjusting request from %d to %d", a_MaxSize, m_MaxSize);
+ }
+ if (m_MinSize < 16)
+ {
+ m_MinSize = 16;
+ LOGWARNING("RoughRavines: MinSize too small, adjusting request from %d to %d", a_MinSize, m_MinSize);
+ }
+ if (m_MinSize == m_MaxSize)
+ {
+ m_MaxSize = m_MinSize + 1;
+ }
+}
+
+
+
+
+
+cGridStructGen::cStructurePtr cRoughRavines::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
+{
+ // Pick a random value for each of the ravine's parameters:
+ int Size = m_MinSize + (m_Noise.IntNoise2DInt(a_GridX, a_GridZ) / 7) % (m_MaxSize - m_MinSize); // Random int from m_MinSize to m_MaxSize
+ float CenterWidth = m_Noise.IntNoise2DInRange(a_GridX + 10, a_GridZ, m_MinCenterWidth, m_MaxCenterWidth);
+ float Roughness = m_Noise.IntNoise2DInRange(a_GridX + 20, a_GridZ, m_MinRoughness, m_MaxRoughness);
+ float FloorHeightEdge1 = m_Noise.IntNoise2DInRange(a_GridX + 30, a_GridZ, m_MinFloorHeightEdge, m_MaxFloorHeightEdge);
+ float FloorHeightEdge2 = m_Noise.IntNoise2DInRange(a_GridX + 40, a_GridZ, m_MinFloorHeightEdge, m_MaxFloorHeightEdge);
+ float FloorHeightCenter = m_Noise.IntNoise2DInRange(a_GridX + 50, a_GridZ, m_MinFloorHeightCenter, m_MaxFloorHeightCenter);
+ float CeilingHeightEdge1 = m_Noise.IntNoise2DInRange(a_GridX + 60, a_GridZ, m_MinCeilingHeightEdge, m_MaxCeilingHeightEdge);
+ float CeilingHeightEdge2 = m_Noise.IntNoise2DInRange(a_GridX + 70, a_GridZ, m_MinCeilingHeightEdge, m_MaxCeilingHeightEdge);
+ float CeilingHeightCenter = m_Noise.IntNoise2DInRange(a_GridX + 80, a_GridZ, m_MinCeilingHeightCenter, m_MaxCeilingHeightCenter);
+
+ // Create a ravine:
+ return cStructurePtr(new cRoughRavine(
+ m_Seed,
+ Size, CenterWidth, Roughness,
+ FloorHeightEdge1, FloorHeightEdge2, FloorHeightCenter,
+ CeilingHeightEdge1, CeilingHeightEdge2, CeilingHeightCenter,
+ a_GridX, a_GridZ, a_OriginX, a_OriginZ
+ ));
+}
+
+
+
+
diff --git a/src/Generating/RoughRavines.h b/src/Generating/RoughRavines.h
new file mode 100644
index 000000000..4c905b641
--- /dev/null
+++ b/src/Generating/RoughRavines.h
@@ -0,0 +1,86 @@
+
+// RoughRavines.h
+
+// Declares the cRoughRavines class representing the rough ravine generator
+
+
+
+
+#pragma once
+
+#include "GridStructGen.h"
+
+
+
+
+
+class cRoughRavines :
+ public cGridStructGen
+{
+ typedef cGridStructGen super;
+
+public:
+ cRoughRavines(
+ int a_Seed,
+ int a_MaxSize, int a_MinSize,
+ float a_MaxCenterWidth, float a_MinCenterWidth,
+ float a_MaxRoughness, float a_MinRoughness,
+ float a_MaxFloorHeightEdge, float a_MinFloorHeightEdge,
+ float a_MaxFloorHeightCenter, float a_MinFloorHeightCenter,
+ float a_MaxCeilingHeightEdge, float a_MinCeilingHeightEdge,
+ float a_MaxCeilingHeightCenter, float a_MinCeilingHeightCenter,
+ int a_GridSize, int a_MaxOffset
+ );
+
+protected:
+ int m_Seed;
+
+ /** Maximum size of the ravine, in each of the X / Z axis */
+ int m_MaxSize;
+
+ /** Minimum size of the ravine */
+ int m_MinSize;
+
+ /** Maximum width of the ravine's center, in blocks */
+ float m_MaxCenterWidth;
+
+ /** Minimum width of the ravine's center, in blocks */
+ float m_MinCenterWidth;
+
+ /** Maximum roughness of the ravine */
+ float m_MaxRoughness;
+
+ /** Minimum roughness of the ravine */
+ float m_MinRoughness;
+
+ /** Maximum floor height at the ravine's edge */
+ float m_MaxFloorHeightEdge;
+
+ /** Minimum floor height at the ravine's edge */
+ float m_MinFloorHeightEdge;
+
+ /** Maximum floor height at the ravine's center */
+ float m_MaxFloorHeightCenter;
+
+ /** Minimum floor height at the ravine's center */
+ float m_MinFloorHeightCenter;
+
+ /** Maximum ceiling height at the ravine's edge */
+ float m_MaxCeilingHeightEdge;
+
+ /** Minimum ceiling height at the ravine's edge */
+ float m_MinCeilingHeightEdge;
+
+ /** Maximum ceiling height at the ravine's center */
+ float m_MaxCeilingHeightCenter;
+
+ /** Minimum ceiling height at the ravine's center */
+ float m_MinCeilingHeightCenter;
+
+ // cGridStructGen overrides:
+ virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override;
+};
+
+
+
+
diff --git a/src/Generating/StructGen.cpp b/src/Generating/StructGen.cpp
index 636364e17..731324b0d 100644
--- a/src/Generating/StructGen.cpp
+++ b/src/Generating/StructGen.cpp
@@ -12,46 +12,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cStructGenOreNests configuration:
-
-const int MAX_HEIGHT_COAL = 127;
-const int NUM_NESTS_COAL = 50;
-const int NEST_SIZE_COAL = 10;
-
-const int MAX_HEIGHT_IRON = 64;
-const int NUM_NESTS_IRON = 14;
-const int NEST_SIZE_IRON = 6;
-
-const int MAX_HEIGHT_REDSTONE = 16;
-const int NUM_NESTS_REDSTONE = 4;
-const int NEST_SIZE_REDSTONE = 6;
-
-const int MAX_HEIGHT_GOLD = 32;
-const int NUM_NESTS_GOLD = 2;
-const int NEST_SIZE_GOLD = 6;
-
-const int MAX_HEIGHT_DIAMOND = 15;
-const int NUM_NESTS_DIAMOND = 1;
-const int NEST_SIZE_DIAMOND = 4;
-
-const int MAX_HEIGHT_LAPIS = 30;
-const int NUM_NESTS_LAPIS = 2;
-const int NEST_SIZE_LAPIS = 5;
-
-const int MAX_HEIGHT_DIRT = 127;
-const int NUM_NESTS_DIRT = 20;
-const int NEST_SIZE_DIRT = 32;
-
-const int MAX_HEIGHT_GRAVEL = 70;
-const int NUM_NESTS_GRAVEL = 15;
-const int NEST_SIZE_GRAVEL = 32;
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenTrees:
void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc)
@@ -151,7 +112,7 @@ void cStructGenTrees::GenerateSingleTree(
sSetBlockVector TreeLogs, TreeOther;
GetTreeImageByBiome(
a_ChunkX * cChunkDef::Width + x, Height + 1, a_ChunkZ * cChunkDef::Width + z,
- m_Noise, a_Seq,
+ m_Noise, a_Seq,
a_ChunkDesc.GetBiome(x, z),
TreeLogs, TreeOther
);
@@ -181,7 +142,7 @@ void cStructGenTrees::GenerateSingleTree(
}
ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeOther, a_OutsideOther);
- ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeLogs, a_OutsideLogs);
+ ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeLogs, a_OutsideLogs);
}
@@ -303,7 +264,7 @@ int cStructGenTrees::GetNumTrees(
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenOreNests:
void cStructGenOreNests::GenFinish(cChunkDesc & a_ChunkDesc)
@@ -311,14 +272,15 @@ void cStructGenOreNests::GenFinish(cChunkDesc & a_ChunkDesc)
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
cChunkDef::BlockTypes & BlockTypes = a_ChunkDesc.GetBlockTypes();
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_COAL_ORE, MAX_HEIGHT_COAL, NUM_NESTS_COAL, NEST_SIZE_COAL, BlockTypes, 1);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_IRON_ORE, MAX_HEIGHT_IRON, NUM_NESTS_IRON, NEST_SIZE_IRON, BlockTypes, 2);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_REDSTONE_ORE, MAX_HEIGHT_REDSTONE, NUM_NESTS_REDSTONE, NEST_SIZE_REDSTONE, BlockTypes, 3);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_GOLD_ORE, MAX_HEIGHT_GOLD, NUM_NESTS_GOLD, NEST_SIZE_GOLD, BlockTypes, 4);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_DIAMOND_ORE, MAX_HEIGHT_DIAMOND, NUM_NESTS_DIAMOND, NEST_SIZE_DIAMOND, BlockTypes, 5);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_LAPIS_ORE, MAX_HEIGHT_LAPIS, NUM_NESTS_LAPIS, NEST_SIZE_LAPIS, BlockTypes, 6);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_DIRT, MAX_HEIGHT_DIRT, NUM_NESTS_DIRT, NEST_SIZE_DIRT, BlockTypes, 10);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_GRAVEL, MAX_HEIGHT_GRAVEL, NUM_NESTS_GRAVEL, NEST_SIZE_GRAVEL, BlockTypes, 11);
+
+ int seq = 1;
+
+ // Generate the ores from the ore list.
+ for (OreList::const_iterator itr = m_OreList.begin(); itr != m_OreList.end(); ++itr)
+ {
+ GenerateOre(ChunkX, ChunkZ, itr->BlockType, itr->MaxHeight, itr->NumNests, itr->NestSize, BlockTypes, seq);
+ seq++;
+ }
}
@@ -376,7 +338,7 @@ void cStructGenOreNests::GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_Ore
}
int Index = cChunkDef::MakeIndexNoCheck(BlockX, BlockY, BlockZ);
- if (a_BlockTypes[Index] == E_BLOCK_STONE)
+ if (a_BlockTypes[Index] == m_ToReplace)
{
a_BlockTypes[Index] = a_OreType;
}
@@ -410,7 +372,7 @@ void cStructGenOreNests::GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_Ore
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenLakes:
void cStructGenLakes::GenFinish(cChunkDesc & a_ChunkDesc)
@@ -484,7 +446,6 @@ void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a
const int BubbleY = 4 + (Rnd & 0x01); // 4 .. 5
Rnd >>= 1;
const int BubbleZ = BubbleR + (Rnd % Range);
- Rnd >>= 4;
const int HalfR = BubbleR / 2; // 1 .. 2
const int RSquared = BubbleR * BubbleR;
for (int y = -HalfR; y <= HalfR; y++)
@@ -500,7 +461,7 @@ void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a
continue;
}
int IdxYZ = BubbleX + IdxY + (BubbleZ + z) * 16;
- for (int x = -BubbleR; x <= BubbleR; x++)
+ for (int x = -BubbleR; x <= BubbleR; x++)
{
if (x * x + DistYZ < RSquared)
{
@@ -511,10 +472,10 @@ void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a
} // for y
} // for i - bubbles
- // Turn air in the bottom half into liquid:
+ // Turn air in the bottom half into liquid:
for (int y = 0; y < 4; y++)
{
- for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
+ for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
{
if (BlockTypes[x + z * 16 + y * 16 * 16] == E_BLOCK_AIR)
{
@@ -532,7 +493,7 @@ void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenDirectOverhangs:
cStructGenDirectOverhangs::cStructGenDirectOverhangs(int a_Seed) :
@@ -573,8 +534,8 @@ void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
// Interpolate the lowest floor:
for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++)
{
- FloorLo[INTERPOL_X * x + 17 * INTERPOL_Z * z] =
- m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, BaseY, BaseZ + INTERPOL_Z * z) *
+ FloorLo[INTERPOL_X * x + 17 * INTERPOL_Z * z] =
+ m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, BaseY, BaseZ + INTERPOL_Z * z) *
m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, BaseY, BaseZ + INTERPOL_Z * z) /
256;
} // for x, z - FloorLo[]
@@ -586,10 +547,10 @@ void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
// First update the high floor:
for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++)
{
- FloorHi[INTERPOL_X * x + 17 * INTERPOL_Z * z] =
+ FloorHi[INTERPOL_X * x + 17 * INTERPOL_Z * z] = (
m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) *
- m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) /
- 256;
+ m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) / 256
+ );
} // for x, z - FloorLo[]
LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorHi);
@@ -648,7 +609,7 @@ bool cStructGenDirectOverhangs::HasWantedBiome(cChunkDesc & a_ChunkDesc) const
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cStructGenDistortedMembraneOverhangs:
cStructGenDistortedMembraneOverhangs::cStructGenDistortedMembraneOverhangs(int a_Seed) :
diff --git a/src/Generating/StructGen.h b/src/Generating/StructGen.h
index 9176bc192..55d5bc1c7 100644
--- a/src/Generating/StructGen.h
+++ b/src/Generating/StructGen.h
@@ -76,11 +76,29 @@ class cStructGenOreNests :
public cFinishGen
{
public:
- cStructGenOreNests(int a_Seed) : m_Noise(a_Seed), m_Seed(a_Seed) {}
-
+ struct OreInfo
+ {
+ BLOCKTYPE BlockType; // The type of the nest.
+ int MaxHeight; // The highest possible a nest can occur
+ int NumNests; // How many nests per chunk
+ int NestSize; // The amount of blocks a nest can have.
+ };
+
+ typedef std::vector<OreInfo> OreList;
+
+ cStructGenOreNests(int a_Seed, OreList a_OreList, BLOCKTYPE a_ToReplace) :
+ m_Noise(a_Seed),
+ m_Seed(a_Seed),
+ m_OreList(a_OreList),
+ m_ToReplace(a_ToReplace)
+ {}
+
protected:
- cNoise m_Noise;
- int m_Seed;
+ cNoise m_Noise;
+ int m_Seed;
+
+ OreList m_OreList; // A list of possible ores.
+ BLOCKTYPE m_ToReplace;
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
diff --git a/src/Generating/TestRailsGen.cpp b/src/Generating/TestRailsGen.cpp
index c40c1a9b6..66ab8b33f 100644
--- a/src/Generating/TestRailsGen.cpp
+++ b/src/Generating/TestRailsGen.cpp
@@ -18,7 +18,7 @@ static cPrefabPiecePool g_TestRails(g_TestRailsPrefabs, g_TestRailsPrefabsCount,
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cTestRailsGen::cTestRails:
class cTestRailsGen::cTestRails :
@@ -86,7 +86,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cTestRailsGen:
diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp
index 522f45148..1b0f2dc14 100644
--- a/src/Generating/Trees.cpp
+++ b/src/Generating/Trees.cpp
@@ -10,13 +10,6 @@
-// DEBUG:
-int gTotalLargeJungleTrees = 0;
-int gOversizeLargeJungleTrees = 0;
-
-
-
-
typedef struct
{
@@ -41,49 +34,49 @@ static const sCoords Corners[] =
static const sCoords BigO1[] =
{
- {0, -1},
- {-1, 0}, {1, 0},
- {0, 1},
+ /* -1 */ {0, -1},
+ /* 0 */ {-1, 0}, {1, 0},
+ /* 1 */ {0, 1},
} ;
static const sCoords BigO2[] =
{
- {-1, -2}, {0, -2}, {1, -2},
- {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1},
- {-2, 0}, {-1, 0}, {1, 0}, {2, 0},
- {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1},
- {-1, 2}, {0, 2}, {1, 2},
+ /* -2 */ {-1, -2}, {0, -2}, {1, -2},
+ /* -1 */ {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1},
+ /* 0 */ {-2, 0}, {-1, 0}, {1, 0}, {2, 0},
+ /* 1 */ {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1},
+ /* 2 */ {-1, 2}, {0, 2}, {1, 2},
} ;
static const sCoords BigO3[] =
{
- {-2, -3}, {-1, -3}, {0, -3}, {1, -3}, {2, -3},
- {-3, -2}, {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, {3, -2},
- {-3, -1}, {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1},
- {-3, 0}, {-2, 0}, {-1, 0}, {1, 0}, {2, 0}, {3, 0},
- {-3, 1}, {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, {3, 1},
- {-3, 2}, {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2}, {3, 2},
- {-2, 3}, {-1, 3}, {0, 3}, {1, 3}, {2, 3},
+ /* -3 */ {-2, -3}, {-1, -3}, {0, -3}, {1, -3}, {2, -3},
+ /* -2 */ {-3, -2}, {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, {3, -2},
+ /* -1 */ {-3, -1}, {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1},
+ /* 0 */ {-3, 0}, {-2, 0}, {-1, 0}, {1, 0}, {2, 0}, {3, 0},
+ /* 1 */ {-3, 1}, {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, {3, 1},
+ /* 2 */ {-3, 2}, {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2}, {3, 2},
+ /* 3 */ {-2, 3}, {-1, 3}, {0, 3}, {1, 3}, {2, 3},
} ;
-static const sCoords BigO4[] = // Part of Big Jungle tree
+static const sCoords BigO4[] = // Part of Big Jungle tree
{
- {-2, -4}, {-1, -4}, {0, -4}, {1, -4}, {2, -4},
- {-3, -3}, {-2, -3}, {-1, -3}, {0, -3}, {1, -3}, {2, -3}, {3, -3},
- {-4, -2}, {-3, -2}, {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, {3, -2}, {4, -2},
- {-4, -1}, {-3, -1}, {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1}, {4, -1},
- {-4, 0}, {-3, 0}, {-2, 0}, {-1, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0},
- {-4, 1}, {-3, 1}, {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1},
- {-4, 2}, {-3, 2}, {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2},
- {-3, 3}, {-2, 3}, {-1, 3}, {0, 3}, {1, 3}, {2, 3}, {3, 3},
- {-2, 4}, {-1, 4}, {0, 4}, {1, 4}, {2, 4},
+ /* -4 */ {-2, -4}, {-1, -4}, {0, -4}, {1, -4}, {2, -4},
+ /* -3 */ {-3, -3}, {-2, -3}, {-1, -3}, {0, -3}, {1, -3}, {2, -3}, {3, -3},
+ /* -2 */ {-4, -2}, {-3, -2}, {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, {3, -2}, {4, -2},
+ /* -1 */ {-4, -1}, {-3, -1}, {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, {3, -1}, {4, -1},
+ /* 0 */ {-4, 0}, {-3, 0}, {-2, 0}, {-1, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0},
+ /* 1 */ {-4, 1}, {-3, 1}, {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1},
+ /* 2 */ {-4, 2}, {-3, 2}, {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2},
+ /* 3 */ {-3, 3}, {-2, 3}, {-1, 3}, {0, 3}, {1, 3}, {2, 3}, {3, 3},
+ /* 4 */ {-2, 4}, {-1, 4}, {0, 4}, {1, 4}, {2, 4},
} ;
-typedef struct
+typedef struct
{
const sCoords * Coords;
size_t Count;
@@ -113,6 +106,7 @@ inline void PushCoordBlocks(int a_BlockX, int a_Height, int a_BlockZ, sSetBlockV
+
inline void PushCornerBlocks(int a_BlockX, int a_Height, int a_BlockZ, int a_Seq, cNoise & a_Noise, int a_Chance, sSetBlockVector & a_Blocks, int a_CornersDist, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
{
for (size_t i = 0; i < ARRAYCOUNT(Corners); i++)
@@ -187,6 +181,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
return;
}
+ case biSwamplandM:
case biSwampland:
{
// Swamp trees:
@@ -203,7 +198,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
{
GetAppleBushImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
}
- else
+ else
{
GetJungleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
}
@@ -224,7 +219,6 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
return;
}
- case biRoofedForest:
case biColdTaiga:
case biColdTaigaHills:
case biMegaTaiga:
@@ -240,11 +234,9 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
case biExtremeHillsM:
case biFlowerForest:
case biTaigaM:
- case biSwamplandM:
case biIcePlainsSpikes:
case biJungleM:
case biJungleEdgeM:
- case biRoofedForestM:
case biColdTaigaM:
case biMegaSpruceTaiga:
case biMegaSpruceTaigaHills:
@@ -259,6 +251,13 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
return;
}
+
+ case biRoofedForest:
+ case biRoofedForestM:
+ {
+ GetDarkoakTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
+ return;
+ }
case biDesert:
case biDesertHills:
@@ -413,7 +412,60 @@ void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noi
void GetDarkoakTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks)
{
- // TODO
+ // Pick a height
+ int Height = 5 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 11) % 4;
+
+ // Create the trunk
+ for (int i = 0; i < Height; i++)
+ {
+ a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD));
+ a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD));
+ a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD));
+ a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD));
+ }
+
+ // Create branches
+ for (int i = 0; i < 3; i++)
+ {
+ int x = (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY * i, a_BlockZ + 32 * a_Seq) % 3) - 1;
+ int z = (a_Noise.IntNoise3DInt(a_BlockX - 32 * a_Seq, a_BlockY * i, a_BlockZ - 32 * a_Seq) % 3) - 1;
+
+ // The branches would end up in the trunk.
+ if ((x >= a_BlockX) && (x <= a_BlockX + 1) && (z >= a_BlockZ) && (z <= a_BlockZ + 1))
+ {
+ NOISE_DATATYPE Val1 = a_Noise.IntNoise2D(x, z);
+ if (Val1 < 0)
+ {
+ x = a_BlockX + ((Val1 < -0.5) ? -1 : 3);
+ }
+ else
+ {
+ z = a_BlockZ + ((Val1 < 0.5) ? -1 : 3);
+ }
+ }
+
+ int y = Height - (a_Noise.IntNoise3DInt(a_BlockX + x, a_BlockY * i, a_BlockZ - z) % (Height - (Height / 4)));
+
+ for (int Y = y; Y < Height; Y++)
+ {
+ a_LogBlocks.push_back(sSetBlock(a_BlockX + x, a_BlockY + Y, a_BlockZ + z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD));
+ }
+ }
+
+ int hei = a_BlockY + Height - 2;
+
+ // The lower two leaves layers are BigO4 with log in the middle and possibly corners:
+ for (int i = 0; i < 2; i++)
+ {
+ PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO4, ARRAYCOUNT(BigO4), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD);
+ PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD);
+ hei++;
+ } // for i < 2
+
+ // The top leaves layer is a BigO3 with leaves in the middle and possibly corners:
+ PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD);
+ PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD);
+ a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD));
}
@@ -598,11 +650,11 @@ void GetPineTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise
}
int h = a_BlockY + TrunkHeight + 2;
- // Top layer - just a single leaves block:
+ // Top layer - just a single leaves block:
a_OtherBlocks.push_back(sSetBlock(a_BlockX, h, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER));
h--;
- // One more layer is above the trunk, push the central leaves:
+ // One more layer is above the trunk, push the central leaves:
a_OtherBlocks.push_back(sSetBlock(a_BlockX, h, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER));
// Layers expanding in size, then collapsing again:
@@ -773,10 +825,10 @@ void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise &
a_LogBlocks.reserve(Height);
a_OtherBlocks.reserve(
- 2 * ARRAYCOUNT(BigO3) + // O3 layer, 2x
- 2 * ARRAYCOUNT(BigO2) + // O2 layer, 2x
- ARRAYCOUNT(BigO1) + 1 + // Plus on the top
- Height * ARRAYCOUNT(Vines) + // Vines
+ 2 * ARRAYCOUNT(BigO3) + // O3 layer, 2x
+ 2 * ARRAYCOUNT(BigO2) + // O2 layer, 2x
+ ARRAYCOUNT(BigO1) + 1 + // Plus on the top
+ Height * ARRAYCOUNT(Vines) + // Vines
50 // some safety
);
diff --git a/src/Generating/Trees.h b/src/Generating/Trees.h
index 00f343a3d..c9eb7de80 100644
--- a/src/Generating/Trees.h
+++ b/src/Generating/Trees.h
@@ -28,6 +28,7 @@ logs can overwrite others(leaves), but others shouldn't overwrite logs. This is
#define CASE_TREE_ALLOWED_BLOCKS \
case E_BLOCK_AIR: \
case E_BLOCK_LEAVES: \
+ case E_BLOCK_NEW_LEAVES: \
case E_BLOCK_SNOW: \
case E_BLOCK_TALL_GRASS: \
case E_BLOCK_DEAD_BUSH: \
@@ -40,6 +41,7 @@ logs can overwrite others(leaves), but others shouldn't overwrite logs. This is
/* case E_BLOCK_LEAVES: LEAVES are a special case, they can be overwritten only by log. Handled in cChunkMap::ReplaceTreeBlocks(). */ \
case E_BLOCK_SNOW: \
case E_BLOCK_TALL_GRASS: \
+ case E_BLOCK_BIG_FLOWER: \
case E_BLOCK_DEAD_BUSH: \
case E_BLOCK_SAPLING: \
case E_BLOCK_VINES
@@ -70,7 +72,7 @@ void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noi
void GetDarkoakTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks);
/// Generates an image of a random large birch tree
-void GetTallBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks,sSetBlockVector & a_OtherBlocks);
+void GetTallBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks);
/// Generates an image of a random conifer tree
void GetConiferTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks);
diff --git a/src/Generating/UnderwaterBaseGen.cpp b/src/Generating/UnderwaterBaseGen.cpp
index d3abae9b7..9278ea546 100644
--- a/src/Generating/UnderwaterBaseGen.cpp
+++ b/src/Generating/UnderwaterBaseGen.cpp
@@ -18,7 +18,7 @@ static cPrefabPiecePool g_UnderwaterBase(g_UnderwaterBasePrefabs, g_UnderwaterBa
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cUnderwaterBaseGen::cUnderwaterBase:
class cUnderwaterBaseGen::cUnderwaterBase :
@@ -86,7 +86,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cUnderwaterBaseGen:
diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp
index 2b7ecc837..a7f66b75e 100644
--- a/src/Generating/VillageGen.cpp
+++ b/src/Generating/VillageGen.cpp
@@ -95,7 +95,7 @@ public:
return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
}
-} ;
+};
@@ -168,7 +168,7 @@ protected:
/** The density for this village. Used to refrain from populating all house connectors. Range [0, 100] */
int m_Density;
- /** Borders of the vilalge - no item may reach out of this cuboid. */
+ /** Borders of the village - no item may reach out of this cuboid. */
cCuboid m_Borders;
/** Prefabs to use for buildings */
@@ -333,7 +333,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cVillageGen:
static cVillagePiecePool g_SandVillage(g_SandVillagePrefabs, g_SandVillagePrefabsCount, g_SandVillageStartingPrefabs, g_SandVillageStartingPrefabsCount);
diff --git a/src/Globals.h b/src/Globals.h
index 0c11429bd..de1024010 100644
--- a/src/Globals.h
+++ b/src/Globals.h
@@ -14,18 +14,18 @@
#pragma warning(disable:4481)
// Disable some warnings that we don't care about:
- #pragma warning(disable:4100) // Unreferenced formal parameter
-
- // Useful warnings from warning level 4:
- #pragma warning(3 : 4127) // Conditional expression is constant
- #pragma warning(3 : 4189) // Local variable is initialized but not referenced
- #pragma warning(3 : 4245) // Conversion from 'type1' to 'type2', signed/unsigned mismatch
- #pragma warning(3 : 4310) // Cast truncates constant value
- #pragma warning(3 : 4389) // Signed/unsigned mismatch
- #pragma warning(3 : 4505) // Unreferenced local function has been removed
- #pragma warning(3 : 4701) // Potentially unitialized local variable used
- #pragma warning(3 : 4702) // Unreachable code
- #pragma warning(3 : 4706) // Assignment within conditional expression
+ #pragma warning(disable:4100) // Unreferenced formal parameter
+
+ // Useful warnings from warning level 4:
+ #pragma warning(3 : 4127) // Conditional expression is constant
+ #pragma warning(3 : 4189) // Local variable is initialized but not referenced
+ #pragma warning(3 : 4245) // Conversion from 'type1' to 'type2', signed/unsigned mismatch
+ #pragma warning(3 : 4310) // Cast truncates constant value
+ #pragma warning(3 : 4389) // Signed/unsigned mismatch
+ #pragma warning(3 : 4505) // Unreferenced local function has been removed
+ #pragma warning(3 : 4701) // Potentially unitialized local variable used
+ #pragma warning(3 : 4702) // Unreachable code
+ #pragma warning(3 : 4706) // Assignment within conditional expression
// Disabling this warning, because we know what we're doing when we're doing this:
#pragma warning(disable: 4355) // 'this' used in initializer list
@@ -34,7 +34,7 @@
#pragma warning(disable: 4512) // 'class': assignment operator could not be generated - reported for each class that has a reference-type member
// 2014_01_06 xoft: Disabled this warning because MSVC is stupid and reports it in obviously wrong places
- // #pragma warning(3 : 4244) // Conversion from 'type1' to 'type2', possible loss of data
+ // #pragma warning(3 : 4244) // Conversion from 'type1' to 'type2', possible loss of data
#define OBSOLETE __declspec(deprecated)
@@ -58,8 +58,8 @@
// override is part of c++11
#if __cplusplus < 201103L
- #define override
- #endif
+ #define override
+ #endif
#define OBSOLETE __attribute__((deprecated))
@@ -145,7 +145,7 @@ class SizeChecker;
template <typename T, size_t Size>
class SizeChecker<T, Size, true>
{
- T v;
+ T v;
};
template class SizeChecker<Int64, 8>;
@@ -156,11 +156,11 @@ template class SizeChecker<UInt64, 8>;
template class SizeChecker<UInt32, 4>;
template class SizeChecker<UInt16, 2>;
-// A macro to disallow the copy constructor and operator= functions
+// A macro to disallow the copy constructor and operator = functions
// This should be used in the private: declarations for any class that shouldn't allow copying itself
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName &); \
- void operator=(const TypeName &)
+ void operator =(const TypeName &)
// A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc
#define UNUSED(X) (void)(X)
@@ -249,10 +249,10 @@ template class SizeChecker<UInt16, 2>;
#include "OSSupport/Event.h"
#include "OSSupport/Thread.h"
#include "OSSupport/File.h"
- #include "MCLogger.h"
+ #include "Logger.h"
#else
// Logging functions
-void inline LOGERROR(const char* a_Format, ...) FORMATSTRING(1,2);
+void inline LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2);
void inline LOGERROR(const char* a_Format, ...)
{
@@ -272,12 +272,12 @@ void inline LOGERROR(const char* a_Format, ...)
/// Evaluates to the number of elements in an array (compile-time!)
#define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X)))
-/// Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)" )
+/// Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)")
#define KiB * 1024
#define MiB * 1024 * 1024
/// Faster than (int)floorf((float)x / (float)div)
-#define FAST_FLOOR_DIV( x, div ) (((x) - (((x) < 0) ? ((div) - 1) : 0)) / (div))
+#define FAST_FLOOR_DIV( x, div) (((x) - (((x) < 0) ? ((div) - 1) : 0)) / (div))
// Own version of assert() that writes failed assertions to the log for review
#ifdef TEST_GLOBALS
@@ -309,19 +309,19 @@ void inline LOGERROR(const char* a_Format, ...)
}
#endif
#define ASSERT(x) do { if (!(x)) { throw cAssertFailure();} } while (0)
- #define testassert(x) do { if(!(x)) { REPORT_ERROR("Test failure: %s, file %s, line %d\n", #x, __FILE__, __LINE__); exit(1); } } while (0)
+ #define testassert(x) do { if (!(x)) { REPORT_ERROR("Test failure: %s, file %s, line %d\n", #x, __FILE__, __LINE__); exit(1); } } while (0)
#define CheckAsserts(x) do { try {x} catch (cAssertFailure) { break; } REPORT_ERROR("Test failure: assert didn't fire for %s, file %s, line %d\n", #x, __FILE__, __LINE__); exit(1); } while (0)
#else
#ifdef _DEBUG
- #define ASSERT( x ) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), assert(0), 0 ) )
+ #define ASSERT( x) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__), assert(0), 0))
#else
#define ASSERT(x) ((void)(x))
#endif
#endif
// Pretty much the same as ASSERT() but stays in Release builds
-#define VERIFY( x ) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), exit(1), 0 ) )
+#define VERIFY( x) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), exit(1), 0))
// Same as assert but in all Self test builds
#ifdef SELF_TEST
@@ -383,6 +383,5 @@ T Clamp(T a_Value, T a_Min, T a_Max)
#include "BiomeDef.h"
#include "BlockID.h"
#include "BlockInfo.h"
-#include "Entities/Effects.h"
diff --git a/src/Group.cpp b/src/Group.cpp
index 725740905..def585618 100644
--- a/src/Group.cpp
+++ b/src/Group.cpp
@@ -7,7 +7,7 @@
-void cGroup::AddCommand( const AString & a_Command )
+void cGroup::AddCommand( const AString & a_Command)
{
m_Commands[ a_Command ] = true;
}
@@ -16,7 +16,7 @@ void cGroup::AddCommand( const AString & a_Command )
-void cGroup::AddPermission( const AString & a_Permission )
+void cGroup::AddPermission( const AString & a_Permission)
{
m_Permissions[ a_Permission ] = true;
}
@@ -25,10 +25,10 @@ void cGroup::AddPermission( const AString & a_Permission )
-void cGroup::InheritFrom( cGroup* a_Group )
+void cGroup::InheritFrom( cGroup* a_Group)
{
- m_Inherits.remove( a_Group );
- m_Inherits.push_back( a_Group );
+ m_Inherits.remove( a_Group);
+ m_Inherits.push_back( a_Group);
}
diff --git a/src/Group.h b/src/Group.h
index 47088d50d..5816f8a06 100644
--- a/src/Group.h
+++ b/src/Group.h
@@ -5,18 +5,22 @@
-class cGroup // tolua_export
-{ // tolua_export
-public: // tolua_export
+// tolua_begin
+class cGroup
+{
+public:
+ // tolua_end
cGroup() {}
~cGroup() {}
- void SetName( const AString & a_Name ) { m_Name = a_Name; } // tolua_export
- const AString & GetName() const { return m_Name; } // tolua_export
- void SetColor( const AString & a_Color ) { m_Color = a_Color; } // tolua_export
- void AddCommand( const AString & a_Command ); // tolua_export
- void AddPermission( const AString & a_Permission ); // tolua_export
- void InheritFrom( cGroup* a_Group ); // tolua_export
+ // tolua_begin
+ void SetName( const AString & a_Name) { m_Name = a_Name; }
+ const AString & GetName() const { return m_Name; }
+ void SetColor( const AString & a_Color) { m_Color = a_Color; }
+ void AddCommand( const AString & a_Command);
+ void AddPermission( const AString & a_Permission);
+ void InheritFrom( cGroup* a_Group);
+ // tolua_end
typedef std::map< AString, bool > PermissionMap;
const PermissionMap & GetPermissions() const { return m_Permissions; }
@@ -26,7 +30,7 @@ public: // tolua_export
typedef std::map< AString, bool > CommandMap;
const CommandMap & GetCommands() const { return m_Commands; }
- const AString & GetColor() const { return m_Color; } // tolua_export
+ const AString & GetColor() const { return m_Color; } // tolua_export
typedef std::list< cGroup* > GroupList;
const GroupList & GetInherits() const { return m_Inherits; }
@@ -37,4 +41,4 @@ private:
PermissionMap m_Permissions;
CommandMap m_Commands;
GroupList m_Inherits;
-};// tolua_export
+}; // tolua_export
diff --git a/src/GroupManager.cpp b/src/GroupManager.cpp
index 11e62c223..4c3dfc6f0 100644
--- a/src/GroupManager.cpp
+++ b/src/GroupManager.cpp
@@ -27,7 +27,7 @@ struct cGroupManager::sGroupManagerState
cGroupManager::~cGroupManager()
{
- for( GroupMap::iterator itr = m_pState->Groups.begin(); itr != m_pState->Groups.end(); ++itr )
+ for (GroupMap::iterator itr = m_pState->Groups.begin(); itr != m_pState->Groups.end(); ++itr)
{
delete itr->second;
itr->second = NULL;
@@ -43,7 +43,7 @@ cGroupManager::~cGroupManager()
cGroupManager::cGroupManager()
- : m_pState( new sGroupManagerState )
+ : m_pState( new sGroupManagerState)
{
LOGD("-- Loading Groups --");
@@ -125,7 +125,7 @@ bool cGroupManager::LoadGroups()
IniFile.SetValue("Owner", "Permissions", "*", true);
IniFile.SetValue("Owner", "Color", "2", true);
- IniFile.SetValue("Moderator", "Permissions", "core.time,core.item,core.tpa,core.tpaccept,core.ban,core.unban,core.save-all,core.toggledownfall");
+ IniFile.SetValue("Moderator", "Permissions", "core.time, core.item, core.tpa, core.tpaccept, core.ban, core.unban, core.save-all, core.toggledownfall");
IniFile.SetValue("Moderator", "Color", "2", true);
IniFile.SetValue("Moderator", "Inherits", "Player", true);
@@ -133,7 +133,7 @@ bool cGroupManager::LoadGroups()
IniFile.SetValue("Player", "Color", "f", true);
IniFile.SetValue("Player", "Inherits", "Default", true);
- IniFile.SetValue("Default", "Permissions", "core.help,core.plugins,core.spawn,core.worlds,core.back,core.motd,core.build,core.locate,core.viewdistance", true);
+ IniFile.SetValue("Default", "Permissions", "core.help, core.plugins, core.spawn, core.worlds, core.back, core.motd, core.build, core.locate, core.viewdistance", true);
IniFile.SetValue("Default", "Color", "f", true);
IniFile.WriteFile("groups.ini");
@@ -145,7 +145,7 @@ bool cGroupManager::LoadGroups()
AString KeyName = IniFile.GetKeyName(i);
cGroup * Group = GetGroup(KeyName.c_str());
- Group->ClearPermission(); // Needed in case the groups are reloaded.
+ Group->ClearPermission(); // Needed in case the groups are reloaded.
LOGD("Loading group %s", KeyName.c_str());
@@ -153,7 +153,7 @@ bool cGroupManager::LoadGroups()
AString Color = IniFile.GetValue(KeyName, "Color", "-");
if ((Color != "-") && (Color.length() >= 1))
{
- Group->SetColor(cChatColor::Color + Color[0]);
+ Group->SetColor(AString(cChatColor::Delimiter) + Color[0]);
}
else
{
@@ -198,20 +198,20 @@ bool cGroupManager::LoadGroups()
-bool cGroupManager::ExistsGroup( const AString & a_Name )
+bool cGroupManager::ExistsGroup( const AString & a_Name)
{
- GroupMap::iterator itr = m_pState->Groups.find( a_Name );
- return ( itr != m_pState->Groups.end() );
+ GroupMap::iterator itr = m_pState->Groups.find( a_Name);
+ return ( itr != m_pState->Groups.end());
}
-cGroup* cGroupManager::GetGroup( const AString & a_Name )
+cGroup* cGroupManager::GetGroup( const AString & a_Name)
{
- GroupMap::iterator itr = m_pState->Groups.find( a_Name );
- if( itr != m_pState->Groups.end() )
+ GroupMap::iterator itr = m_pState->Groups.find( a_Name);
+ if (itr != m_pState->Groups.end())
{
return itr->second;
}
diff --git a/src/HTTPServer/CMakeLists.txt b/src/HTTPServer/CMakeLists.txt
index dc894368d..b0efc810d 100644
--- a/src/HTTPServer/CMakeLists.txt
+++ b/src/HTTPServer/CMakeLists.txt
@@ -4,9 +4,26 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ EnvelopeParser.cpp
+ HTTPConnection.cpp
+ HTTPFormParser.cpp
+ HTTPMessage.cpp
+ HTTPServer.cpp
+ MultipartParser.cpp
+ NameValueParser.cpp
+ SslHTTPConnection.cpp)
-add_library(HTTPServer ${SOURCE})
+SET (HDRS
+ EnvelopeParser.h
+ HTTPConnection.h
+ HTTPFormParser.h
+ HTTPMessage.h
+ HTTPServer.h
+ MultipartParser.h
+ NameValueParser.h
+ SslHTTPConnection.h)
+
+if(NOT MSVC)
+ add_library(HTTPServer ${SRCS} ${HDRS})
+endif()
diff --git a/src/HTTPServer/HTTPConnection.cpp b/src/HTTPServer/HTTPConnection.cpp
index 21ff14373..b9c762e7c 100644
--- a/src/HTTPServer/HTTPConnection.cpp
+++ b/src/HTTPServer/HTTPConnection.cpp
@@ -100,7 +100,7 @@ void cHTTPConnection::AwaitNextRequest(void)
{
case wcsRecvHeaders:
{
- // Nothing has been received yet, or a special response was given (SendStatusAndReason() or SendNeedAuth() )
+ // Nothing has been received yet, or a special response was given (SendStatusAndReason() or SendNeedAuth())
break;
}
diff --git a/src/HTTPServer/HTTPMessage.cpp b/src/HTTPServer/HTTPMessage.cpp
index 44feda469..65d73fd87 100644
--- a/src/HTTPServer/HTTPMessage.cpp
+++ b/src/HTTPServer/HTTPMessage.cpp
@@ -20,7 +20,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cHTTPMessage:
cHTTPMessage::cHTTPMessage(eKind a_Kind) :
@@ -35,8 +35,7 @@ cHTTPMessage::cHTTPMessage(eKind a_Kind) :
void cHTTPMessage::AddHeader(const AString & a_Key, const AString & a_Value)
{
- AString Key = a_Key;
- StrToLower(Key);
+ AString Key = StrToLower(a_Key);
cNameValueMap::iterator itr = m_Headers.find(Key);
if (itr == m_Headers.end())
{
@@ -64,7 +63,7 @@ void cHTTPMessage::AddHeader(const AString & a_Key, const AString & a_Value)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cHTTPRequest:
cHTTPRequest::cHTTPRequest(void) :
@@ -139,7 +138,7 @@ AString cHTTPRequest::GetBareURL(void) const
size_t cHTTPRequest::ParseRequestLine(const char * a_Data, size_t a_Size)
-{
+{
m_IncomingHeaderData.append(a_Data, a_Size);
size_t IdxEnd = m_IncomingHeaderData.size();
@@ -248,7 +247,7 @@ void cHTTPRequest::OnHeaderLine(const AString & a_Key, const AString & a_Value)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cHTTPResponse:
cHTTPResponse::cHTTPResponse(void) :
diff --git a/src/HTTPServer/HTTPMessage.h b/src/HTTPServer/HTTPMessage.h
index dab942136..c0667030f 100644
--- a/src/HTTPServer/HTTPMessage.h
+++ b/src/HTTPServer/HTTPMessage.h
@@ -18,7 +18,7 @@
class cHTTPMessage
{
public:
- enum
+ enum eStatus
{
HTTP_OK = 200,
HTTP_BAD_REQUEST = 400,
@@ -33,7 +33,7 @@ public:
cHTTPMessage(eKind a_Kind);
// Force a virtual destructor in all descendants
- virtual ~cHTTPMessage() {};
+ virtual ~cHTTPMessage() {}
/** Adds a header into the internal map of headers. Recognizes special headers: Content-Type and Content-Length */
void AddHeader(const AString & a_Key, const AString & a_Value);
diff --git a/src/HTTPServer/HTTPServer.cpp b/src/HTTPServer/HTTPServer.cpp
index 036b2e042..8eabe5cb2 100644
--- a/src/HTTPServer/HTTPServer.cpp
+++ b/src/HTTPServer/HTTPServer.cpp
@@ -118,12 +118,12 @@ class cDebugCallbacks :
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cHTTPServer:
cHTTPServer::cHTTPServer(void) :
- m_ListenThreadIPv4(*this, cSocket::IPv4, "WebServer IPv4"),
- m_ListenThreadIPv6(*this, cSocket::IPv6, "WebServer IPv6"),
+ m_ListenThreadIPv4(*this, cSocket::IPv4, "WebServer"),
+ m_ListenThreadIPv6(*this, cSocket::IPv6, "WebServer"),
m_Callbacks(NULL)
{
}
diff --git a/src/HTTPServer/MultipartParser.cpp b/src/HTTPServer/MultipartParser.cpp
index 309495dd7..09732c5f7 100644
--- a/src/HTTPServer/MultipartParser.cpp
+++ b/src/HTTPServer/MultipartParser.cpp
@@ -21,7 +21,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// self-test:
#if 0
@@ -87,7 +87,7 @@ ThisIsIgnoredEpilogue";
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cMultipartParser:
diff --git a/src/HTTPServer/NameValueParser.cpp b/src/HTTPServer/NameValueParser.cpp
index f16ea1915..b345fef88 100644
--- a/src/HTTPServer/NameValueParser.cpp
+++ b/src/HTTPServer/NameValueParser.cpp
@@ -69,7 +69,7 @@ public:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cNameValueParser:
cNameValueParser::cNameValueParser(bool a_AllowsKeyOnly) :
diff --git a/src/Inventory.cpp b/src/Inventory.cpp
index bce882c88..8da3dea5f 100644
--- a/src/Inventory.cpp
+++ b/src/Inventory.cpp
@@ -102,13 +102,17 @@ int cInventory::AddItem(const cItem & a_Item, bool a_AllowNewStacks, bool a_tryT
{
cItem ToAdd(a_Item);
int res = 0;
+
+ // When the item is a armor, try to set it directly to the armor slot.
if (ItemCategory::IsArmor(a_Item.m_ItemType))
{
- res = m_ArmorSlots.AddItem(ToAdd, a_AllowNewStacks);
- ToAdd.m_ItemCount -= res;
- if (ToAdd.m_ItemCount == 0)
+ for (size_t i = 0; i < (size_t)m_ArmorSlots.GetNumSlots(); i++)
{
- return res;
+ if (m_ArmorSlots.GetSlot(i).IsEmpty() && cSlotAreaArmor::CanPlaceArmorInSlot(i, a_Item))
+ {
+ m_ArmorSlots.SetSlot(i, a_Item);
+ return a_Item.m_ItemCount;
+ }
}
}
@@ -151,6 +155,24 @@ int cInventory::AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks, bool a
+int cInventory::RemoveItem(const cItem & a_ItemStack)
+{
+ int RemovedItems = m_HotbarSlots.RemoveItem(a_ItemStack);
+
+ if (RemovedItems < a_ItemStack.m_ItemCount)
+ {
+ cItem Temp(a_ItemStack);
+ Temp.m_ItemCount -= RemovedItems;
+ RemovedItems += m_InventorySlots.RemoveItem(Temp);
+ }
+
+ return RemovedItems;
+}
+
+
+
+
+
bool cInventory::RemoveOneEquippedItem(void)
{
if (m_HotbarSlots.GetSlot(m_EquippedSlotNum).IsEmpty())
@@ -204,12 +226,6 @@ void cInventory::SetSlot(int a_SlotNum, const cItem & a_Item)
return;
}
Grid->SetSlot(GridSlotNum, a_Item);
-
- // Broadcast the Equipped Item, if the Slot is changed.
- if ((Grid == &m_HotbarSlots) && (m_EquippedSlotNum == (a_SlotNum - invHotbarOffset)))
- {
- m_Owner.GetWorld()->BroadcastEntityEquipment(m_Owner, 0, a_Item, m_Owner.GetClientHandle());
- }
}
@@ -375,6 +391,10 @@ bool cInventory::DamageItem(int a_SlotNum, short a_Amount)
LOGWARNING("%s: requesting an invalid slot index: %d out of %d", __FUNCTION__, a_SlotNum, invNumSlots - 1);
return false;
}
+ if (a_Amount <= 0)
+ {
+ return false;
+ }
int GridSlotNum = 0;
cItemGrid * Grid = GetGridForSlotNum(a_SlotNum, GridSlotNum);
@@ -479,21 +499,21 @@ int cInventory::ArmorSlotNumToEntityEquipmentID(short a_ArmorSlotNum)
#if 0
-bool cInventory::AddToBar( cItem & a_Item, const int a_Offset, const int a_Size, bool* a_bChangedSlots, int a_Mode /* = 0 */ )
+bool cInventory::AddToBar( cItem & a_Item, const int a_Offset, const int a_Size, bool* a_bChangedSlots, int a_Mode /* = 0 */)
{
// Fill already present stacks
- if( a_Mode < 2 )
+ if (a_Mode < 2)
{
int MaxStackSize = cItemHandler::GetItemHandler(a_Item.m_ItemType)->GetMaxStackSize();
- for(int i = 0; i < a_Size; i++)
+ for (int i = 0; i < a_Size; i++)
{
- if( m_Slots[i + a_Offset].m_ItemType == a_Item.m_ItemType && m_Slots[i + a_Offset].m_ItemCount < MaxStackSize && m_Slots[i + a_Offset].m_ItemDamage == a_Item.m_ItemDamage )
+ if (m_Slots[i + a_Offset].m_ItemType == a_Item.m_ItemType && m_Slots[i + a_Offset].m_ItemCount < MaxStackSize && m_Slots[i + a_Offset].m_ItemDamage == a_Item.m_ItemDamage)
{
int NumFree = MaxStackSize - m_Slots[i + a_Offset].m_ItemCount;
- if( NumFree >= a_Item.m_ItemCount )
+ if (NumFree >= a_Item.m_ItemCount)
{
- //printf("1. Adding %i items ( free: %i )\n", a_Item.m_ItemCount, NumFree );
+ // printf("1. Adding %i items ( free: %i)\n", a_Item.m_ItemCount, NumFree);
m_Slots[i + a_Offset].m_ItemCount += a_Item.m_ItemCount;
a_Item.m_ItemCount = 0;
a_bChangedSlots[i + a_Offset] = true;
@@ -501,7 +521,7 @@ bool cInventory::AddToBar( cItem & a_Item, const int a_Offset, const int a_Size,
}
else
{
- //printf("2. Adding %i items\n", NumFree );
+ // printf("2. Adding %i items\n", NumFree);
m_Slots[i + a_Offset].m_ItemCount += (char)NumFree;
a_Item.m_ItemCount -= (char)NumFree;
a_bChangedSlots[i + a_Offset] = true;
@@ -510,12 +530,12 @@ bool cInventory::AddToBar( cItem & a_Item, const int a_Offset, const int a_Size,
}
}
- if( a_Mode > 0 )
+ if (a_Mode > 0)
{
// If we got more left, find first empty slot
- for(int i = 0; i < a_Size && a_Item.m_ItemCount > 0; i++)
+ for (int i = 0; i < a_Size && a_Item.m_ItemCount > 0; i++)
{
- if( m_Slots[i + a_Offset].m_ItemType == -1 )
+ if (m_Slots[i + a_Offset].m_ItemType == -1)
{
m_Slots[i + a_Offset] = a_Item;
a_Item.m_ItemCount = 0;
@@ -695,6 +715,12 @@ void cInventory::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
m_ArmorSlots.GetSlot(a_SlotNum), m_Owner.GetClientHandle()
);
}
+
+ // Broadcast the Equipped Item, if the Slot is changed.
+ if ((a_ItemGrid == &m_HotbarSlots) && (m_EquippedSlotNum == a_SlotNum))
+ {
+ m_Owner.GetWorld()->BroadcastEntityEquipment(m_Owner, 0, GetEquippedItem(), m_Owner.GetClientHandle());
+ }
// Convert the grid-local a_SlotNum to our global SlotNum:
int Base = 0;
diff --git a/src/Inventory.h b/src/Inventory.h
index 39aef1538..5628fb0da 100644
--- a/src/Inventory.h
+++ b/src/Inventory.h
@@ -39,8 +39,8 @@ public:
enum
{
invArmorCount = 4,
- invInventoryCount = 9 * 3,
- invHotbarCount = 9,
+ invInventoryCount = 9 * 3,
+ invHotbarCount = 9,
invArmorOffset = 0,
invInventoryOffset = invArmorOffset + invArmorCount,
@@ -86,6 +86,10 @@ public:
*/
int AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks, bool a_tryToFillEquippedFirst);
+ /** Removes the specified item from the inventory, as many as possible, up to a_ItemStack.m_ItemCount.
+ Returns the number of items that were removed. */
+ int RemoveItem(const cItem & a_ItemStack);
+
/** Removes one item out of the currently equipped item stack, returns true if successful, false if empty-handed */
bool RemoveOneEquippedItem(void);
@@ -165,7 +169,7 @@ public:
bool LoadFromJson(Json::Value & a_Value);
protected:
- bool AddToBar( cItem & a_Item, const int a_Offset, const int a_Size, bool* a_bChangedSlots, int a_Mode = 0 );
+ bool AddToBar( cItem & a_Item, const int a_Offset, const int a_Size, bool* a_bChangedSlots, int a_Mode = 0);
cItemGrid m_ArmorSlots;
cItemGrid m_InventorySlots;
@@ -183,7 +187,7 @@ protected:
// cItemGrid::cListener override:
virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override;
-}; // tolua_export
+}; // tolua_export
diff --git a/src/Item.cpp b/src/Item.cpp
index 56ceae0b7..2c5deaddf 100644
--- a/src/Item.cpp
+++ b/src/Item.cpp
@@ -41,33 +41,33 @@ short cItem::GetMaxDamage(void) const
switch (m_ItemType)
{
case E_ITEM_BOW: return 384;
- case E_ITEM_DIAMOND_AXE: return 1563;
- case E_ITEM_DIAMOND_HOE: return 1563;
- case E_ITEM_DIAMOND_PICKAXE: return 1563;
- case E_ITEM_DIAMOND_SHOVEL: return 1563;
- case E_ITEM_DIAMOND_SWORD: return 1563;
- case E_ITEM_FLINT_AND_STEEL: return 65;
+ case E_ITEM_DIAMOND_AXE: return 1561;
+ case E_ITEM_DIAMOND_HOE: return 1561;
+ case E_ITEM_DIAMOND_PICKAXE: return 1561;
+ case E_ITEM_DIAMOND_SHOVEL: return 1561;
+ case E_ITEM_DIAMOND_SWORD: return 1561;
+ case E_ITEM_FLINT_AND_STEEL: return 64;
case E_ITEM_GOLD_AXE: return 32;
case E_ITEM_GOLD_HOE: return 32;
case E_ITEM_GOLD_PICKAXE: return 32;
case E_ITEM_GOLD_SHOVEL: return 32;
case E_ITEM_GOLD_SWORD: return 32;
- case E_ITEM_IRON_AXE: return 251;
- case E_ITEM_IRON_HOE: return 251;
- case E_ITEM_IRON_PICKAXE: return 251;
- case E_ITEM_IRON_SHOVEL: return 251;
- case E_ITEM_IRON_SWORD: return 251;
- case E_ITEM_SHEARS: return 251;
- case E_ITEM_STONE_AXE: return 132;
- case E_ITEM_STONE_HOE: return 132;
- case E_ITEM_STONE_PICKAXE: return 132;
- case E_ITEM_STONE_SHOVEL: return 132;
- case E_ITEM_STONE_SWORD: return 132;
- case E_ITEM_WOODEN_AXE: return 60;
- case E_ITEM_WOODEN_HOE: return 60;
- case E_ITEM_WOODEN_PICKAXE: return 60;
- case E_ITEM_WOODEN_SHOVEL: return 60;
- case E_ITEM_WOODEN_SWORD: return 60;
+ case E_ITEM_IRON_AXE: return 250;
+ case E_ITEM_IRON_HOE: return 250;
+ case E_ITEM_IRON_PICKAXE: return 250;
+ case E_ITEM_IRON_SHOVEL: return 250;
+ case E_ITEM_IRON_SWORD: return 250;
+ case E_ITEM_SHEARS: return 250;
+ case E_ITEM_STONE_AXE: return 131;
+ case E_ITEM_STONE_HOE: return 131;
+ case E_ITEM_STONE_PICKAXE: return 131;
+ case E_ITEM_STONE_SHOVEL: return 131;
+ case E_ITEM_STONE_SWORD: return 131;
+ case E_ITEM_WOODEN_AXE: return 59;
+ case E_ITEM_WOODEN_HOE: return 59;
+ case E_ITEM_WOODEN_PICKAXE: return 59;
+ case E_ITEM_WOODEN_SHOVEL: return 59;
+ case E_ITEM_WOODEN_SWORD: return 59;
}
return 0;
}
@@ -86,7 +86,7 @@ bool cItem::DamageItem(short a_Amount)
}
m_ItemDamage += a_Amount;
- return (m_ItemDamage >= MaxDamage);
+ return (m_ItemDamage > MaxDamage);
}
@@ -162,11 +162,11 @@ void cItem::GetJson(Json::Value & a_OutValue) const
void cItem::FromJson(const Json::Value & a_Value)
{
- m_ItemType = (ENUM_ITEM_ID)a_Value.get("ID", -1 ).asInt();
+ m_ItemType = (ENUM_ITEM_ID)a_Value.get("ID", -1).asInt();
if (m_ItemType > 0)
{
- m_ItemCount = (char)a_Value.get("Count", -1 ).asInt();
- m_ItemDamage = (short)a_Value.get("Health", -1 ).asInt();
+ m_ItemCount = (char)a_Value.get("Count", -1).asInt();
+ m_ItemDamage = (short)a_Value.get("Health", -1).asInt();
m_Enchantments.Clear();
m_Enchantments.AddFromString(a_Value.get("ench", "").asString());
m_CustomName = a_Value.get("Name", "").asString();
@@ -193,17 +193,29 @@ void cItem::FromJson(const Json::Value & a_Value)
bool cItem::IsEnchantable(short item)
{
if ((item >= 256) && (item <= 259))
+ {
return true;
+ }
if ((item >= 267) && (item <= 279))
+ {
return true;
- if ((item >= 283) && (item <= 286))
+ }
+ if ((item >= 283) && (item <= 286))
+ {
return true;
+ }
if ((item >= 290) && (item <= 294))
+ {
return true;
+ }
if ((item >= 298) && (item <= 317))
+ {
return true;
+ }
if ((item == 346) || (item == 359) || (item == 261))
+ {
return true;
+ }
return false;
}
@@ -363,7 +375,7 @@ bool cItem::EnchantByXPLevels(int a_NumXPLevels)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cItems:
cItem * cItems::Get(int a_Idx)
diff --git a/src/Item.h b/src/Item.h
index acbc880dc..d8b9e78a0 100644
--- a/src/Item.h
+++ b/src/Item.h
@@ -150,7 +150,7 @@ public:
bool IsCustomNameEmpty(void) const { return (m_CustomName.empty()); }
- bool IsLoreEmpty(void) const { return (m_Lore.empty()); }
+ bool IsLoreEmpty(void) const { return (m_Lore.empty()); }
/** Returns a copy of this item with m_ItemCount set to 1. Useful to preserve enchantments etc. on stacked items */
cItem CopyOne(void) const;
@@ -184,14 +184,14 @@ public:
void FromJson(const Json::Value & a_Value);
/** Returns true if the specified item type is enchantable (as per 1.2.5 protocol requirements) */
- static bool IsEnchantable(short a_ItemType); // tolua_export
+ static bool IsEnchantable(short a_ItemType); // tolua_export
/** Returns the enchantability of the item. When the item hasn't a enchantability, it will returns 0 */
- int GetEnchantability(); // tolua_export
+ int GetEnchantability(); // tolua_export
/** Enchants the item using the specified number of XP levels.
Returns true if item enchanted, false if not. */
- bool EnchantByXPLevels(int a_NumXPLevels); // tolua_export
+ bool EnchantByXPLevels(int a_NumXPLevels); // tolua_export
// tolua_begin
diff --git a/src/ItemGrid.cpp b/src/ItemGrid.cpp
index cd36b1f2a..2344dc0a5 100644
--- a/src/ItemGrid.cpp
+++ b/src/ItemGrid.cpp
@@ -269,7 +269,7 @@ int cItemGrid::AddItemToSlot(const cItem & a_ItemStack, int a_Slot, int a_Num, i
int cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_PrioritarySlot)
{
int NumLeft = a_ItemStack.m_ItemCount;
- int MaxStack = ItemHandler(a_ItemStack.m_ItemType)->GetMaxStackSize();
+ int MaxStack = a_ItemStack.GetMaxStackSize();
// Try prioritarySlot first:
if (
@@ -284,7 +284,7 @@ int cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_Priorit
}
// Scan existing stacks:
- for (int i = m_NumSlots - 1; i >= 0; i--)
+ for (int i = 0; i < m_NumSlots; i++)
{
if (m_Slots[i].IsEqual(a_ItemStack))
{
@@ -302,7 +302,7 @@ int cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_Priorit
return (a_ItemStack.m_ItemCount - NumLeft);
}
- for (int i = m_NumSlots - 1; i >= 0; i--)
+ for (int i = 0; i < m_NumSlots; i++)
{
if (m_Slots[i].IsEmpty())
{
@@ -345,6 +345,39 @@ int cItemGrid::AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks, int a_P
+int cItemGrid::RemoveItem(const cItem & a_ItemStack)
+{
+ int NumLeft = a_ItemStack.m_ItemCount;
+
+ for (int i = 0; i < m_NumSlots; i++)
+ {
+ if (NumLeft <= 0)
+ {
+ break;
+ }
+
+ if (m_Slots[i].IsEqual(a_ItemStack))
+ {
+ int NumToRemove = std::min(NumLeft, (int)m_Slots[i].m_ItemCount);
+ NumLeft -= NumToRemove;
+ m_Slots[i].m_ItemCount -= NumToRemove;
+
+ if (m_Slots[i].m_ItemCount <= 0)
+ {
+ m_Slots[i].Empty();
+ }
+
+ TriggerListeners(i);
+ }
+ }
+
+ return (a_ItemStack.m_ItemCount - NumLeft);
+}
+
+
+
+
+
int cItemGrid::ChangeSlotCount(int a_SlotNum, int a_AddToCount)
{
if ((a_SlotNum < 0) || (a_SlotNum >= m_NumSlots))
diff --git a/src/ItemGrid.h b/src/ItemGrid.h
index c34d5e9e2..8d6544792 100644
--- a/src/ItemGrid.h
+++ b/src/ItemGrid.h
@@ -96,6 +96,10 @@ public:
Returns the total number of items that fit.
*/
int AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks = true, int a_PrioritarySlot = -1);
+
+ /** Removes the specified item from the grid, as many as possible, up to a_ItemStack.m_ItemCount.
+ Returns the number of items that were removed. */
+ int RemoveItem(const cItem & a_ItemStack);
/** Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot.
If the slot is empty, ignores the call.
diff --git a/src/Items/CMakeLists.txt b/src/Items/CMakeLists.txt
index a6fe6ea70..12a467672 100644
--- a/src/Items/CMakeLists.txt
+++ b/src/Items/CMakeLists.txt
@@ -4,9 +4,53 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ ItemHandler.cpp)
-add_library(Items ${SOURCE})
+SET (HDRS
+ ItemArmor.h
+ ItemBed.h
+ ItemBoat.h
+ ItemBow.h
+ ItemBrewingStand.h
+ ItemBucket.h
+ ItemCake.h
+ ItemCauldron.h
+ ItemCloth.h
+ ItemComparator.h
+ ItemDoor.h
+ ItemDye.h
+ ItemEmptyMap.h
+ ItemFishingRod.h
+ ItemFlowerPot.h
+ ItemFood.h
+ ItemHandler.h
+ ItemHoe.h
+ ItemItemFrame.h
+ ItemLeaves.h
+ ItemLighter.h
+ ItemLilypad.h
+ ItemMap.h
+ ItemMilk.h
+ ItemMinecart.h
+ ItemMobHead.h
+ ItemNetherWart.h
+ ItemPainting.h
+ ItemPickaxe.h
+ ItemPotion.h
+ ItemRedstoneDust.h
+ ItemRedstoneRepeater.h
+ ItemSapling.h
+ ItemSeeds.h
+ ItemShears.h
+ ItemShovel.h
+ ItemSign.h
+ ItemSpawnEgg.h
+ ItemString.h
+ ItemSugarcane.h
+ ItemSword.h
+ ItemThrowable.h)
+
+if(NOT MSVC)
+ add_library(Items ${SRCS} ${HDRS})
+endif()
diff --git a/src/Items/ItemBed.h b/src/Items/ItemBed.h
index f23d69731..94a14cf16 100644
--- a/src/Items/ItemBed.h
+++ b/src/Items/ItemBed.h
@@ -26,7 +26,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemBow.h b/src/Items/ItemBow.h
index 185f17fee..fdc24689c 100644
--- a/src/Items/ItemBow.h
+++ b/src/Items/ItemBow.h
@@ -57,6 +57,12 @@ public:
}
Force = std::min(Force, 1.0);
+ // Does the player have an arrow?
+ if (!a_Player->IsGameModeCreative() && !a_Player->GetInventory().HasItems(cItem(E_ITEM_ARROW)))
+ {
+ return;
+ }
+
// Create the arrow entity:
cArrowEntity * Arrow = new cArrowEntity(*a_Player, Force * 2);
if (Arrow == NULL)
@@ -70,9 +76,13 @@ public:
return;
}
- a_Player->GetWorld()->BroadcastSoundEffect("random.bow", (int)a_Player->GetPosX() * 8, (int)a_Player->GetPosY() * 8, (int)a_Player->GetPosZ() * 8, 0.5, (float)Force);
+ a_Player->GetWorld()->BroadcastSoundEffect("random.bow", a_Player->GetPosX(), a_Player->GetPosY(), a_Player->GetPosZ(), 0.5, (float)Force);
if (!a_Player->IsGameModeCreative())
{
+ if (a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchInfinity) == 0)
+ {
+ a_Player->GetInventory().RemoveItem(cItem(E_ITEM_ARROW));
+ }
a_Player->UseEquippedItem();
}
}
diff --git a/src/Items/ItemBrewingStand.h b/src/Items/ItemBrewingStand.h
index d5eefb855..7be57763c 100644
--- a/src/Items/ItemBrewingStand.h
+++ b/src/Items/ItemBrewingStand.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemBucket.h b/src/Items/ItemBucket.h
index 68c89dd85..a17c4838b 100644
--- a/src/Items/ItemBucket.h
+++ b/src/Items/ItemBucket.h
@@ -41,7 +41,7 @@ public:
bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{
- if (a_BlockFace > 0)
+ if (a_BlockFace != BLOCK_FACE_NONE)
{
return false;
}
@@ -49,7 +49,7 @@ public:
Vector3i BlockPos;
if (!GetBlockFromTrace(a_World, a_Player, BlockPos))
{
- return false; // Nothing in range.
+ return false; // Nothing in range.
}
if (a_World->GetBlockMeta(BlockPos.x, BlockPos.y, BlockPos.z) != 0)
@@ -94,30 +94,16 @@ public:
bool PlaceFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_FluidBlock)
- {
- if (a_BlockFace < 0)
+ {
+ if (a_BlockFace != BLOCK_FACE_NONE)
{
return false;
}
- BLOCKTYPE CurrentBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- bool CanWashAway = cFluidSimulator::CanWashAway(CurrentBlock);
- if (!CanWashAway)
+ BLOCKTYPE CurrentBlock;
+ Vector3i BlockPos;
+ if (!GetPlacementCoordsFromTrace(a_World, a_Player, BlockPos, CurrentBlock))
{
- // The block pointed at cannot be washed away, so put fluid on top of it / on its sides
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
- CurrentBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- }
- if (
- !CanWashAway &&
- (CurrentBlock != E_BLOCK_AIR) &&
- (CurrentBlock != E_BLOCK_WATER) &&
- (CurrentBlock != E_BLOCK_STATIONARY_WATER) &&
- (CurrentBlock != E_BLOCK_LAVA) &&
- (CurrentBlock != E_BLOCK_STATIONARY_LAVA)
- )
- {
- // Cannot place water here
return false;
}
@@ -131,14 +117,14 @@ public:
return false;
}
cItem Item(E_ITEM_BUCKET, 1);
- if (!a_Player->GetInventory().AddItem(Item,true,true))
+ if (!a_Player->GetInventory().AddItem(Item, true, true))
{
return false;
}
}
// Wash away anything that was there prior to placing:
- if (CanWashAway)
+ if (cFluidSimulator::CanWashAway(CurrentBlock))
{
cBlockHandler * Handler = BlockHandler(CurrentBlock);
if (Handler->DoesDropOnUnsuitable())
@@ -149,13 +135,13 @@ public:
}
}
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_FluidBlock, 0);
+ a_World->SetBlock(BlockPos.x, BlockPos.y, BlockPos.z, a_FluidBlock, 0);
return true;
}
- bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & BlockPos)
+ bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos)
{
class cCallbacks :
public cBlockTracer::cCallbacks
@@ -174,7 +160,7 @@ public:
{
if (IsBlockWater(a_BlockType) || IsBlockLava(a_BlockType))
{
- if (a_BlockMeta != 0) // GetBlockFromTrace is called for scooping up fluids; the hit block should be a source
+ if (a_BlockMeta != 0) // GetBlockFromTrace is called for scooping up fluids; the hit block should be a source
{
return false;
}
@@ -198,8 +184,49 @@ public:
}
- BlockPos.Set(Callbacks.m_Pos.x, Callbacks.m_Pos.y, Callbacks.m_Pos.z);
+ a_BlockPos = Callbacks.m_Pos;
return true;
}
+
+
+ bool GetPlacementCoordsFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos, BLOCKTYPE & a_BlockType)
+ {
+ class cCallbacks :
+ public cBlockTracer::cCallbacks
+ {
+ public:
+ Vector3i m_Pos;
+ BLOCKTYPE m_ReplacedBlock;
+
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
+ {
+ if (a_BlockType != E_BLOCK_AIR)
+ {
+ m_ReplacedBlock = a_BlockType;
+ if (!cFluidSimulator::CanWashAway(a_BlockType) && !IsBlockLiquid(a_BlockType))
+ {
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, (eBlockFace)a_EntryFace); // Was an unwashawayable block, can't overwrite it!
+ }
+ m_Pos.Set(a_BlockX, a_BlockY, a_BlockZ); // (Block could be washed away, replace it)
+ return true; // Abort tracing
+ }
+ return false;
+ }
+ } Callbacks;
+ cLineBlockTracer Tracer(*a_World, Callbacks);
+ Vector3d Start(a_Player->GetEyePosition());
+ Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
+
+ // cTracer::Trace returns true when whole line was traversed. By returning true when we hit something, we ensure that this never happens if liquid could be placed
+ // Use this to judge whether the position is valid
+ if (!Tracer.Trace(Start.x, Start.y, Start.z, End.x, End.y, End.z))
+ {
+ a_BlockPos = Callbacks.m_Pos;
+ a_BlockType = Callbacks.m_ReplacedBlock;
+ return true;
+ }
+
+ return false;
+ }
};
diff --git a/src/Items/ItemCake.h b/src/Items/ItemCake.h
index 48e23ed59..d1cb091b6 100644
--- a/src/Items/ItemCake.h
+++ b/src/Items/ItemCake.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemCauldron.h b/src/Items/ItemCauldron.h
index 07ae12660..9617c30ef 100644
--- a/src/Items/ItemCauldron.h
+++ b/src/Items/ItemCauldron.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemComparator.h b/src/Items/ItemComparator.h
index 60d9c3648..fc843c186 100644
--- a/src/Items/ItemComparator.h
+++ b/src/Items/ItemComparator.h
@@ -24,7 +24,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemDoor.h b/src/Items/ItemDoor.h
index f3677c28c..c1b439024 100644
--- a/src/Items/ItemDoor.h
+++ b/src/Items/ItemDoor.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -33,8 +33,8 @@ public:
a_BlockType = (m_ItemType == E_ITEM_WOODEN_DOOR) ? E_BLOCK_WOODEN_DOOR : E_BLOCK_IRON_DOOR;
cChunkInterface ChunkInterface(a_World->GetChunkMap());
bool Meta = BlockHandler(a_BlockType)->GetPlacementBlockTypeMeta(
- ChunkInterface, a_Player,
- a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
+ ChunkInterface, a_Player,
+ a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
a_CursorX, a_CursorY, a_CursorZ,
a_BlockType, a_BlockMeta
);
diff --git a/src/Items/ItemFishingRod.h b/src/Items/ItemFishingRod.h
index 3b1ad1717..6350a38ba 100644
--- a/src/Items/ItemFishingRod.h
+++ b/src/Items/ItemFishingRod.h
@@ -17,13 +17,15 @@
-/////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////
// cFloaterCallback
class cFloaterCallback :
public cEntityCallback
{
public:
- cFloaterCallback(void) :
+ cFloaterCallback(void) :
m_CanPickup(false),
m_AttachedMobID(-1)
{
@@ -49,14 +51,19 @@ protected:
Vector3d m_Pos;
} ;
-////////////////////////////////////////////////////////////////////////////
-// cSweepEntityCallback
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cSweepEntityCallback:
+
class cSweepEntityCallback :
public cEntityCallback
{
public:
cSweepEntityCallback(Vector3d a_PlayerPos) :
- m_PlayerPos(a_PlayerPos)
+ m_PlayerPos(a_PlayerPos)
{
}
@@ -73,6 +80,8 @@ protected:
+
+
class cItemFishingRodHandler :
public cItemHandler
{
@@ -106,19 +115,19 @@ public:
{
cItems Drops;
int ItemCategory = a_World->GetTickRandomNumber(99);
- if (ItemCategory <= 4) // Treasures 5%
+ if (ItemCategory <= 4) // Treasures 5%
{
int Treasure = a_World->GetTickRandomNumber(5);
switch (Treasure)
{
case 0:
{
- Drops.Add(cItem(E_ITEM_BOW)); // TODO: Enchantments
+ Drops.Add(cItem(E_ITEM_BOW)); // TODO: Enchantments
break;
}
case 1:
{
- Drops.Add(cItem(E_ITEM_BOOK)); // TODO: Enchanted book
+ Drops.Add(cItem(E_ITEM_BOOK)); // TODO: Enchanted book
break;
}
case 2:
@@ -201,7 +210,7 @@ public:
if (FishType <= 1) // Clownfish has a 2% chance of spawning
{
Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_CLOWNFISH));
- }
+ }
else if (FishType <= 12) // Pufferfish has a 13% chance of spawning
{
Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_CLOWNFISH));
@@ -237,3 +246,7 @@ public:
return true;
}
} ;
+
+
+
+
diff --git a/src/Items/ItemFlowerPot.h b/src/Items/ItemFlowerPot.h
index 60bf87985..320dce997 100644
--- a/src/Items/ItemFlowerPot.h
+++ b/src/Items/ItemFlowerPot.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemFood.h b/src/Items/ItemFood.h
index 961cf482d..98050cad8 100644
--- a/src/Items/ItemFood.h
+++ b/src/Items/ItemFood.h
@@ -26,36 +26,76 @@ public:
virtual FoodInfo GetFoodInfo(void) override
{
- switch(m_ItemType)
+ switch (m_ItemType)
{
// Please keep alpha-sorted.
case E_ITEM_BAKED_POTATO: return FoodInfo(6, 7.2);
case E_ITEM_BREAD: return FoodInfo(5, 6);
// Carrots handled in ItemSeeds
case E_ITEM_COOKED_CHICKEN: return FoodInfo(6, 7.2);
- case E_ITEM_COOKED_FISH: return FoodInfo(5, 6);
+ case E_ITEM_COOKED_FISH: return FoodInfo(5, 6); // TODO: Add other fish types
case E_ITEM_COOKED_PORKCHOP: return FoodInfo(8, 12.8);
case E_ITEM_COOKIE: return FoodInfo(2, 0.4);
- case E_ITEM_GOLDEN_APPLE: return FoodInfo(4, 9.6);
+ // Golden apple handled in ItemGoldenApple
case E_ITEM_GOLDEN_CARROT: return FoodInfo(6, 14.4);
case E_ITEM_MELON_SLICE: return FoodInfo(2, 1.2);
case E_ITEM_MUSHROOM_SOUP: return FoodInfo(6, 7.2);
- case E_ITEM_POISONOUS_POTATO: return FoodInfo(2, 1.2, 60);
+ case E_ITEM_POISONOUS_POTATO: return FoodInfo(2, 1.2);
// Potatoes handled in ItemSeeds
case E_ITEM_PUMPKIN_PIE: return FoodInfo(8, 4.8);
case E_ITEM_RAW_BEEF: return FoodInfo(3, 1.8);
- case E_ITEM_RAW_CHICKEN: return FoodInfo(2, 1.2, 30);
+ case E_ITEM_RAW_CHICKEN: return FoodInfo(2, 1.2);
case E_ITEM_RAW_FISH: return FoodInfo(2, 1.2);
case E_ITEM_RAW_PORKCHOP: return FoodInfo(3, 1.8);
case E_ITEM_RED_APPLE: return FoodInfo(4, 2.4);
- case E_ITEM_ROTTEN_FLESH: return FoodInfo(4, 0.8, 80);
- case E_ITEM_SPIDER_EYE: return FoodInfo(2, 3.2, 100);
+ case E_ITEM_ROTTEN_FLESH: return FoodInfo(4, 0.8);
+ case E_ITEM_SPIDER_EYE: return FoodInfo(2, 3.2);
case E_ITEM_STEAK: return FoodInfo(8, 12.8);
}
LOGWARNING("%s: Unknown food item (%d), returning zero nutrition", __FUNCTION__, m_ItemType);
return FoodInfo(0, 0.f);
}
-
+
+ virtual bool GetEatEffect(cEntityEffect::eType & a_EffectType, int & a_EffectDurationTicks, short & a_EffectIntensity, float & a_Chance) override
+ {
+ switch (m_ItemType)
+ {
+ case E_ITEM_RAW_CHICKEN:
+ {
+ a_EffectType = cEntityEffect::effHunger;
+ a_EffectDurationTicks = 600;
+ a_EffectIntensity = 0;
+ a_Chance = 0.3f;
+ return true;
+ }
+ case E_ITEM_ROTTEN_FLESH:
+ {
+ a_EffectType = cEntityEffect::effHunger;
+ a_EffectDurationTicks = 600;
+ a_EffectIntensity = 0;
+ a_Chance = 0.8f;
+ return true;
+ }
+ case E_ITEM_SPIDER_EYE:
+ {
+ a_EffectType = cEntityEffect::effPoison;
+ a_EffectDurationTicks = 100;
+ a_EffectIntensity = 0;
+ a_Chance = 1.0f;
+ return true;
+ }
+ case E_ITEM_POISONOUS_POTATO:
+ {
+ a_EffectType = cEntityEffect::effPoison;
+ a_EffectDurationTicks = 100;
+ a_EffectIntensity = 0;
+ a_Chance = 0.6f;
+ return true;
+ }
+ }
+ return false;
+ }
+
};
diff --git a/src/Items/ItemGoldenApple.h b/src/Items/ItemGoldenApple.h
new file mode 100644
index 000000000..02ac0202c
--- /dev/null
+++ b/src/Items/ItemGoldenApple.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include "ItemFood.h"
+
+
+
+
+
+class cItemGoldenAppleHandler :
+ public cItemFoodHandler
+{
+ typedef cItemFoodHandler super;
+
+public:
+ cItemGoldenAppleHandler()
+ : super(E_ITEM_GOLDEN_APPLE)
+ {
+ }
+
+
+ virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) override
+ {
+ // Feed the player:
+ FoodInfo Info = GetFoodInfo();
+ a_Player->Feed(Info.FoodLevel, Info.Saturation);
+
+ // Add the effects:
+ a_Player->AddEntityEffect(cEntityEffect::effAbsorption, 2400, 0);
+ a_Player->AddEntityEffect(cEntityEffect::effRegeneration, 100, 1);
+
+ // When the apple is a 'notch apple', give extra effects:
+ if (a_Item->m_ItemDamage >= E_META_GOLDEN_APPLE_ENCHANTED)
+ {
+ a_Player->AddEntityEffect(cEntityEffect::effRegeneration, 600, 4);
+ a_Player->AddEntityEffect(cEntityEffect::effResistance, 6000, 0);
+ a_Player->AddEntityEffect(cEntityEffect::effFireResistance, 6000, 0);
+ }
+
+ return true;
+ }
+
+
+ virtual FoodInfo GetFoodInfo(void) override
+ {
+ return FoodInfo(4, 9.6);
+ }
+
+
+ virtual bool GetEatEffect(cEntityEffect::eType & a_EffectType, int & a_EffectDurationTicks, short & a_EffectIntensity, float & a_Chance) override
+ {
+ return false;
+ }
+
+};
+
+
+
+
diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index 423039cf4..bceedaf69 100644
--- a/src/Items/ItemHandler.cpp
+++ b/src/Items/ItemHandler.cpp
@@ -19,11 +19,13 @@
#include "ItemCloth.h"
#include "ItemComparator.h"
#include "ItemDoor.h"
+#include "ItemMilk.h"
#include "ItemDye.h"
#include "ItemEmptyMap.h"
#include "ItemFishingRod.h"
#include "ItemFlowerPot.h"
#include "ItemFood.h"
+#include "ItemGoldenApple.h"
#include "ItemItemFrame.h"
#include "ItemHoe.h"
#include "ItemLeaves.h"
@@ -34,6 +36,7 @@
#include "ItemNetherWart.h"
#include "ItemPainting.h"
#include "ItemPickaxe.h"
+#include "ItemPotion.h"
#include "ItemThrowable.h"
#include "ItemRedstoneDust.h"
#include "ItemRedstoneRepeater.h"
@@ -63,7 +66,7 @@ cItemHandler * cItemHandler::m_ItemHandler[2268];
cItemHandler * cItemHandler::GetItemHandler(int a_ItemType)
{
- if ((a_ItemType < 0) || ((unsigned long)a_ItemType >= ARRAYCOUNT(m_ItemHandler)))
+ if ((a_ItemType < 0) || ((size_t)a_ItemType >= ARRAYCOUNT(m_ItemHandler)))
{
// Either nothing (-1), or bad value, both cases should return the air handler
if (a_ItemType < -1)
@@ -92,7 +95,7 @@ cItemHandler * cItemHandler::GetItemHandler(int a_ItemType)
cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
{
- switch(a_ItemType)
+ switch (a_ItemType)
{
default: return new cItemHandler(a_ItemType);
@@ -104,7 +107,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
case E_ITEM_BED: return new cItemBedHandler(a_ItemType);
case E_ITEM_BOAT: return new cItemBoatHandler(a_ItemType);
case E_ITEM_BOTTLE_O_ENCHANTING: return new cItemBottleOEnchantingHandler();
- case E_ITEM_BOW: return new cItemBowHandler;
+ case E_ITEM_BOW: return new cItemBowHandler();
case E_ITEM_BREWING_STAND: return new cItemBrewingStandHandler(a_ItemType);
case E_ITEM_CAKE: return new cItemCakeHandler(a_ItemType);
case E_ITEM_CAULDRON: return new cItemCauldronHandler(a_ItemType);
@@ -118,11 +121,14 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
case E_ITEM_FISHING_ROD: return new cItemFishingRodHandler(a_ItemType);
case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType);
case E_ITEM_FLOWER_POT: return new cItemFlowerPotHandler(a_ItemType);
+ case E_ITEM_GOLDEN_APPLE: return new cItemGoldenAppleHandler();
case E_BLOCK_LILY_PAD: return new cItemLilypadHandler(a_ItemType);
case E_ITEM_MAP: return new cItemMapHandler();
+ case E_ITEM_MILK: return new cItemMilkHandler();
case E_ITEM_ITEM_FRAME: return new cItemItemFrameHandler(a_ItemType);
case E_ITEM_NETHER_WART: return new cItemNetherWartHandler(a_ItemType);
case E_ITEM_PAINTING: return new cItemPaintingHandler(a_ItemType);
+ case E_ITEM_POTIONS: return new cItemPotionHandler();
case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType);
case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType);
case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType);
@@ -208,7 +214,6 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
case E_ITEM_COOKED_FISH:
case E_ITEM_COOKED_PORKCHOP:
case E_ITEM_COOKIE:
- case E_ITEM_GOLDEN_APPLE:
case E_ITEM_GOLDEN_CARROT:
case E_ITEM_MELON_SLICE:
case E_ITEM_MUSHROOM_SOUP:
@@ -259,7 +264,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
void cItemHandler::Deinit()
{
- for(int i = 0; i < 2267; i++)
+ for (int i = 0; i < 2267; i++)
{
delete m_ItemHandler[i];
m_ItemHandler[i] = NULL;
@@ -324,15 +329,25 @@ void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const
if (a_Player->IsGameModeSurvival())
{
- if (!BlockRequiresSpecialTool(Block) || CanHarvestBlock(Block))
- {
- cChunkInterface ChunkInterface(a_World->GetChunkMap());
- cBlockInServerPluginInterface PluginInterface(*a_World);
- Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ);
- }
+ cChunkInterface ChunkInterface(a_World->GetChunkMap());
+ cBlockInServerPluginInterface PluginInterface(*a_World);
+ Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ, CanHarvestBlock(Block), a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) > 0);
+ }
+
+ if (!cBlockInfo::IsOneHitDig(Block))
+ {
+ a_Player->UseEquippedItem(GetDurabilityLossByAction(dlaBreakBlock));
}
-
- a_Player->UseEquippedItem();
+}
+
+
+
+
+
+void cItemHandler::OnEntityAttack(cPlayer * a_Attacker, cEntity * a_AttackedEntity)
+{
+ UNUSED(a_AttackedEntity);
+ a_Attacker->UseEquippedItem(GetDurabilityLossByAction(dlaAttackEntity));
}
@@ -350,6 +365,20 @@ void cItemHandler::OnFoodEaten(cWorld * a_World, cPlayer * a_Player, cItem * a_I
+short cItemHandler::GetDurabilityLossByAction(eDurabilityLostAction a_Action)
+{
+ switch ((int)a_Action)
+ {
+ case dlaAttackEntity: return 2;
+ case dlaBreakBlock: return 1;
+ }
+ return 0;
+}
+
+
+
+
+
char cItemHandler::GetMaxStackSize(void)
{
if (m_ItemType < 256)
@@ -358,7 +387,7 @@ char cItemHandler::GetMaxStackSize(void)
return 64;
}
- switch (m_ItemType) //sorted by id
+ switch (m_ItemType)
{
case E_ITEM_ARROW: return 64;
case E_ITEM_BAKED_POTATO: return 64;
@@ -454,14 +483,14 @@ char cItemHandler::GetMaxStackSize(void)
bool cItemHandler::IsTool()
{
// TODO: Rewrite this to list all tools specifically
- return
- (m_ItemType >= 256 && m_ItemType <= 259)
- || (m_ItemType == 261)
- || (m_ItemType >= 267 && m_ItemType <= 279)
- || (m_ItemType >= 283 && m_ItemType <= 286)
- || (m_ItemType >= 290 && m_ItemType <= 294)
- || (m_ItemType == 325)
- || (m_ItemType == 346);
+ return
+ ((m_ItemType >= 256) && (m_ItemType <= 259)) ||
+ (m_ItemType == 261) ||
+ ((m_ItemType >= 267) && (m_ItemType <= 279)) ||
+ ((m_ItemType >= 283) && (m_ItemType <= 286)) ||
+ ((m_ItemType >= 290) && (m_ItemType <= 294)) ||
+ (m_ItemType == 325) ||
+ (m_ItemType == 346);
}
@@ -470,33 +499,17 @@ bool cItemHandler::IsTool()
bool cItemHandler::IsFood(void)
{
- switch (m_ItemType)
- {
- case E_ITEM_RED_APPLE:
- case E_ITEM_GOLDEN_APPLE:
- case E_ITEM_MUSHROOM_SOUP:
- case E_ITEM_BREAD:
- case E_ITEM_RAW_PORKCHOP:
- case E_ITEM_COOKED_PORKCHOP:
- case E_ITEM_MILK:
- case E_ITEM_RAW_FISH:
- case E_ITEM_COOKED_FISH:
- case E_ITEM_COOKIE:
- case E_ITEM_MELON_SLICE:
- case E_ITEM_RAW_BEEF:
- case E_ITEM_STEAK:
- case E_ITEM_RAW_CHICKEN:
- case E_ITEM_COOKED_CHICKEN:
- case E_ITEM_ROTTEN_FLESH:
- case E_ITEM_SPIDER_EYE:
- case E_ITEM_CARROT:
- case E_ITEM_POTATO:
- case E_ITEM_BAKED_POTATO:
- case E_ITEM_POISONOUS_POTATO:
- {
- return true;
- }
- } // switch (m_ItemType)
+ return false;
+}
+
+
+
+
+
+bool cItemHandler::IsDrinkable(short a_ItemDamage)
+{
+ UNUSED(a_ItemDamage);
+
return false;
}
@@ -517,6 +530,7 @@ bool cItemHandler::IsPlaceable(void)
bool cItemHandler::CanRepairWithRawMaterial(short a_ItemType)
{
+ UNUSED(a_ItemType);
return false;
}
@@ -526,9 +540,51 @@ bool cItemHandler::CanRepairWithRawMaterial(short a_ItemType)
bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
{
- UNUSED(a_BlockType);
-
- return false;
+ switch (a_BlockType)
+ {
+ case E_BLOCK_ANVIL:
+ case E_BLOCK_ENCHANTMENT_TABLE:
+ case E_BLOCK_FURNACE:
+ case E_BLOCK_LIT_FURNACE:
+ case E_BLOCK_COAL_ORE:
+ case E_BLOCK_STONE:
+ case E_BLOCK_COBBLESTONE:
+ case E_BLOCK_END_STONE:
+ case E_BLOCK_MOSSY_COBBLESTONE:
+ case E_BLOCK_SANDSTONE_STAIRS:
+ case E_BLOCK_SANDSTONE:
+ case E_BLOCK_STONE_BRICKS:
+ case E_BLOCK_NETHER_BRICK:
+ case E_BLOCK_NETHERRACK:
+ case E_BLOCK_STONE_SLAB:
+ case E_BLOCK_DOUBLE_STONE_SLAB:
+ case E_BLOCK_STONE_PRESSURE_PLATE:
+ case E_BLOCK_BRICK:
+ case E_BLOCK_COBBLESTONE_STAIRS:
+ case E_BLOCK_COBBLESTONE_WALL:
+ case E_BLOCK_STONE_BRICK_STAIRS:
+ case E_BLOCK_NETHER_BRICK_STAIRS:
+ case E_BLOCK_CAULDRON:
+ case E_BLOCK_OBSIDIAN:
+ case E_BLOCK_DIAMOND_BLOCK:
+ case E_BLOCK_DIAMOND_ORE:
+ case E_BLOCK_GOLD_BLOCK:
+ case E_BLOCK_GOLD_ORE:
+ case E_BLOCK_REDSTONE_ORE:
+ case E_BLOCK_REDSTONE_ORE_GLOWING:
+ case E_BLOCK_EMERALD_ORE:
+ case E_BLOCK_IRON_BLOCK:
+ case E_BLOCK_IRON_ORE:
+ case E_BLOCK_LAPIS_ORE:
+ case E_BLOCK_LAPIS_BLOCK:
+ case E_BLOCK_SNOW:
+ case E_BLOCK_VINES:
+ case E_BLOCK_PACKED_ICE:
+ {
+ return false;
+ }
+ default: return true;
+ }
}
@@ -537,7 +593,7 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
bool cItemHandler::GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
)
@@ -554,7 +610,7 @@ bool cItemHandler::GetPlacementBlockTypeMeta(
cChunkInterface ChunkInterface(a_World->GetChunkMap());
return BlockH->GetPlacementBlockTypeMeta(
ChunkInterface, a_Player,
- a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
+ a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
a_CursorX, a_CursorY, a_CursorZ,
a_BlockType, a_BlockMeta
);
@@ -564,29 +620,39 @@ bool cItemHandler::GetPlacementBlockTypeMeta(
+bool cItemHandler::GetEatEffect(cEntityEffect::eType & a_EffectType, int & a_EffectDurationTicks, short & a_EffectIntensity, float & a_Chance)
+{
+ return false;
+}
+
+
+
+
+
bool cItemHandler::EatItem(cPlayer * a_Player, cItem * a_Item)
{
UNUSED(a_Item);
-
- FoodInfo Info = GetFoodInfo();
+ FoodInfo Info = GetFoodInfo();
if ((Info.FoodLevel > 0) || (Info.Saturation > 0.f))
{
bool Success = a_Player->Feed(Info.FoodLevel, Info.Saturation);
-
- // If consumed and there's chance of foodpoisoning, do it:
- if (Success && (Info.PoisonChance > 0))
+
+ // Give effects
+ cEntityEffect::eType EffectType;
+ int EffectDurationTicks;
+ short EffectIntensity;
+ float Chance;
+ if (Success && GetEatEffect(EffectType, EffectDurationTicks, EffectIntensity, Chance))
{
cFastRandom r1;
- if ((r1.NextInt(100, a_Player->GetUniqueID()) - Info.PoisonChance) <= 0)
+ if (r1.NextFloat() < Chance)
{
- a_Player->FoodPoison(300);
+ a_Player->AddEntityEffect(EffectType, EffectDurationTicks, EffectIntensity, Chance);
}
}
-
return Success;
}
-
return false;
}
diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h
index e13198cd7..8b554ee34 100644
--- a/src/Items/ItemHandler.h
+++ b/src/Items/ItemHandler.h
@@ -3,6 +3,7 @@
#include "../Defines.h"
#include "../Item.h"
+#include "../Entities/EntityEffect.h"
@@ -19,6 +20,13 @@ class cPlayer;
class cItemHandler
{
public:
+
+ enum eDurabilityLostAction
+ {
+ dlaBreakBlock,
+ dlaAttackEntity,
+ };
+
cItemHandler(int a_ItemType);
/** Force virtual destructor */
@@ -28,7 +36,7 @@ public:
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir);
/** Called when the client sends the SHOOT status in the lclk packet */
- virtual void OnItemShoot(cPlayer *, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
+ virtual void OnItemShoot(cPlayer *, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
{
UNUSED(a_BlockX);
UNUSED(a_BlockY);
@@ -48,33 +56,40 @@ public:
virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace);
/** Called when the player destroys a block using this item. This also calls the drop function for the destroyed block */
- virtual void OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_X, int a_Y, int a_Z);
+ virtual void OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ);
+
+ /** Called when a player attacks a other entity. */
+ virtual void OnEntityAttack(cPlayer * a_Attacker, cEntity * a_AttackedEntity);
/** Called after the player has eaten this item. */
virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item);
-
+
+ /** Get the durability lost which the item will get, when a specified action was performed. */
+ virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action);
+
/** Returns the maximum stack size for a given item */
virtual char GetMaxStackSize(void);
struct FoodInfo
{
- double Saturation;
int FoodLevel;
- int PoisonChance; // 0 - 100, in percent. 0 = no chance of poisoning, 100 = sure poisoning
+ double Saturation;
FoodInfo(int a_FoodLevel, double a_Saturation, int a_PoisonChance = 0) :
- Saturation(a_Saturation),
FoodLevel(a_FoodLevel),
- PoisonChance(a_PoisonChance)
+ Saturation(a_Saturation)
{
}
} ;
- /** Returns the FoodInfo for this item. (FoodRecovery, Saturation and PoisionChance) */
+ /** Returns the FoodInfo for this item. (FoodRecovery and Saturation) */
virtual FoodInfo GetFoodInfo();
-
+
+ /** If this function returns true, it sets the arguments to a effect who will be activated when you eat the item. */
+ virtual bool GetEatEffect(cEntityEffect::eType & a_EffectType, int & a_EffectDurationTicks, short & a_EffectIntensity, float & a_Chance);
+
/** Lets the player eat a selected item. Returns true if the player ate the item */
- virtual bool EatItem(cPlayer *a_Player, cItem *a_Item);
+ virtual bool EatItem(cPlayer * a_Player, cItem * a_Item);
/** Indicates if this item is a tool */
virtual bool IsTool(void);
@@ -82,24 +97,27 @@ public:
/** Indicates if this item is food */
virtual bool IsFood(void);
+ /** Indicates if this item is drinkable */
+ virtual bool IsDrinkable(short a_ItemDamage);
+
/** Blocks simply get placed */
virtual bool IsPlaceable(void);
/** Can the anvil repair this item, when a_Item is the second input? */
virtual bool CanRepairWithRawMaterial(short a_ItemType);
- /** Called before a block is placed into a world.
+ /** Called before a block is placed into a world.
The handler should return true to allow placement, false to refuse.
Also, the handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block.
*/
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
);
- /** Returns whether this tool/item can harvest a specific block (e.g. wooden pickaxe can harvest stone, but wood can�t) DEFAULT: False */
+ /** Returns whether this tool/item can harvest a specific block (e.g. wooden pickaxe can harvest stone, but wood can't) DEFAULT: False */
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType);
static cItemHandler * GetItemHandler(int a_ItemType);
@@ -109,11 +127,11 @@ public:
protected:
int m_ItemType;
- static cItemHandler *CreateItemHandler(int m_ItemType);
+ static cItemHandler * CreateItemHandler(int m_ItemType);
static cItemHandler * m_ItemHandler[E_ITEM_LAST + 1];
- static bool m_HandlerInitialized; //used to detect if the itemhandlers are initialized
+ static bool m_HandlerInitialized; // used to detect if the itemhandlers are initialized
};
-//Short function
+// Short function
inline cItemHandler *ItemHandler(int a_ItemType) { return cItemHandler::GetItemHandler(a_ItemType); }
diff --git a/src/Items/ItemHoe.h b/src/Items/ItemHoe.h
index 29f7c83d5..8d0b71478 100644
--- a/src/Items/ItemHoe.h
+++ b/src/Items/ItemHoe.h
@@ -16,7 +16,6 @@ public:
cItemHoeHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
-
}
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
@@ -26,13 +25,18 @@ public:
if ((Block == E_BLOCK_DIRT) || (Block == E_BLOCK_GRASS))
{
a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FARMLAND, 0);
-
a_Player->UseEquippedItem();
return true;
-
}
+
return false;
}
+
+
+ virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) override
+ {
+ return 0;
+ }
} ;
diff --git a/src/Items/ItemItemFrame.h b/src/Items/ItemItemFrame.h
index b258b4aea..87e20ecf0 100644
--- a/src/Items/ItemItemFrame.h
+++ b/src/Items/ItemItemFrame.h
@@ -27,9 +27,9 @@ public:
return false;
}
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again
if (Block == E_BLOCK_AIR)
{
diff --git a/src/Items/ItemLeaves.h b/src/Items/ItemLeaves.h
index 12cb45d1c..f48126dc5 100644
--- a/src/Items/ItemLeaves.h
+++ b/src/Items/ItemLeaves.h
@@ -20,7 +20,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
@@ -31,7 +31,7 @@ public:
a_CursorX, a_CursorY, a_CursorZ,
a_BlockType, a_BlockMeta
);
- a_BlockMeta = a_BlockMeta | 0x4; //0x4 bit set means this is a player-placed leaves block, not to be decayed
+ a_BlockMeta = a_BlockMeta | 0x4; // 0x4 bit set means this is a player-placed leaves block, not to be decayed
return res;
}
} ;
diff --git a/src/Items/ItemLighter.h b/src/Items/ItemLighter.h
index 32f49cab6..9f98bf85f 100644
--- a/src/Items/ItemLighter.h
+++ b/src/Items/ItemLighter.h
@@ -52,8 +52,8 @@ public:
case E_BLOCK_TNT:
{
// Activate the TNT:
- a_World->BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 1.0f);
- a_World->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0);
+ a_World->BroadcastSoundEffect("game.tnt.primed", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0f, 1.0f);
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_World->SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5); // 80 ticks to boom
break;
}
@@ -68,7 +68,7 @@ public:
if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR)
{
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0);
- a_World->BroadcastSoundEffect("fire.ignite", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0F, 1.04F);
+ a_World->BroadcastSoundEffect("fire.ignite", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0F, 1.04F);
break;
}
}
diff --git a/src/Items/ItemLilypad.h b/src/Items/ItemLilypad.h
index bc650cdbd..b9d837384 100644
--- a/src/Items/ItemLilypad.h
+++ b/src/Items/ItemLilypad.h
@@ -25,7 +25,7 @@ public:
virtual bool IsPlaceable(void) override
{
- return false; // Set as not placeable so OnItemUse is called
+ return false; // Set as not placeable so OnItemUse is called
}
@@ -57,7 +57,7 @@ public:
{
if (IsBlockWater(a_CBBlockType))
{
- if ((a_CBBlockMeta != 0) || (a_CBEntryFace == BLOCK_FACE_NONE)) // The hit block should be a source. The FACE_NONE check is clicking whilst submerged
+ if ((a_CBBlockMeta != 0) || (a_CBEntryFace == BLOCK_FACE_NONE)) // The hit block should be a source. The FACE_NONE check is clicking whilst submerged
{
return false;
}
diff --git a/src/Items/ItemMilk.h b/src/Items/ItemMilk.h
new file mode 100644
index 000000000..db7bc13be
--- /dev/null
+++ b/src/Items/ItemMilk.h
@@ -0,0 +1,28 @@
+
+#pragma once
+
+class cItemMilkHandler:
+ public cItemHandler
+{
+ typedef cItemHandler super;
+public:
+ cItemMilkHandler():
+ super(E_ITEM_MILK)
+ {
+ }
+
+ virtual bool IsDrinkable(short a_ItemDamage) override
+ {
+ UNUSED(a_ItemDamage);
+ return true;
+ }
+
+ virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) override
+ {
+ UNUSED(a_Item);
+ a_Player->ClearEntityEffects();
+ a_Player->GetInventory().RemoveOneEquippedItem();
+ a_Player->GetInventory().AddItem(E_ITEM_BUCKET);
+ return true;
+ }
+};
diff --git a/src/Items/ItemMobHead.h b/src/Items/ItemMobHead.h
index 5ae040282..4c36fe8d8 100644
--- a/src/Items/ItemMobHead.h
+++ b/src/Items/ItemMobHead.h
@@ -26,7 +26,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemNetherWart.h b/src/Items/ItemNetherWart.h
index a6a9a286a..10a0864b5 100644
--- a/src/Items/ItemNetherWart.h
+++ b/src/Items/ItemNetherWart.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemPainting.h b/src/Items/ItemPainting.h
index e4bb76ebe..a2a77ce21 100644
--- a/src/Items/ItemPainting.h
+++ b/src/Items/ItemPainting.h
@@ -27,9 +27,9 @@ public:
return false;
}
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again
if (Block == E_BLOCK_AIR)
{
@@ -38,14 +38,14 @@ public:
// The client uses different values for painting directions and block faces. Our constants are for the block faces, so we convert them here to painting faces
switch (a_Dir)
{
- case BLOCK_FACE_ZP: break; // Initialised to zero
+ case BLOCK_FACE_ZP: break; // Initialised to zero
case BLOCK_FACE_ZM: Dir = 2; break;
case BLOCK_FACE_XM: Dir = 1; break;
case BLOCK_FACE_XP: Dir = 3; break;
default: ASSERT(!"Unhandled block face when trying spawn painting!"); return false;
}
- static const struct // Define all the possible painting titles
+ static const struct // Define all the possible painting titles
{
AString Title;
} gPaintingTitlesList[] =
diff --git a/src/Items/ItemPickaxe.h b/src/Items/ItemPickaxe.h
index 82bec52d4..17fd96822 100644
--- a/src/Items/ItemPickaxe.h
+++ b/src/Items/ItemPickaxe.h
@@ -8,6 +8,7 @@
class cItemPickaxeHandler :
public cItemHandler
{
+ typedef cItemHandler super;
public:
cItemPickaxeHandler(int a_ItemType)
: cItemHandler(a_ItemType)
@@ -17,7 +18,7 @@ public:
char PickaxeLevel()
{
- switch(m_ItemType)
+ switch (m_ItemType)
{
case E_ITEM_WOODEN_PICKAXE: return 1;
case E_ITEM_GOLD_PICKAXE: return 1;
@@ -31,7 +32,7 @@ public:
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) override
{
- switch(a_BlockType)
+ switch (a_BlockType)
{
case E_BLOCK_OBSIDIAN:
{
@@ -84,7 +85,7 @@ public:
return PickaxeLevel() >= 1;
}
}
- return false;
+ return super::CanHarvestBlock(a_BlockType);
}
virtual bool CanRepairWithRawMaterial(short a_ItemType) override
diff --git a/src/Items/ItemPotion.h b/src/Items/ItemPotion.h
new file mode 100644
index 000000000..24614cd8a
--- /dev/null
+++ b/src/Items/ItemPotion.h
@@ -0,0 +1,79 @@
+
+#pragma once
+
+#include "../Entities/EntityEffect.h"
+#include "../Entities/SplashPotionEntity.h"
+
+class cItemPotionHandler:
+ public cItemHandler
+{
+ typedef cItemHandler super;
+
+public:
+
+ cItemPotionHandler():
+ super(E_ITEM_POTION)
+ {
+ }
+
+
+ // cItemHandler overrides:
+ virtual bool IsDrinkable(short a_ItemDamage) override
+ {
+ // Drinkable potion if 13th lowest bit is set
+ // Ref.: http://minecraft.gamepedia.com/Potions#Data_value_table
+ return cEntityEffect::IsPotionDrinkable(a_ItemDamage);
+ }
+
+
+ virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
+ {
+ short PotionDamage = a_Item.m_ItemDamage;
+
+ // Do not throw non-splash potions:
+ if (cEntityEffect::IsPotionDrinkable(PotionDamage))
+ {
+ return false;
+ }
+
+ Vector3d Pos = a_Player->GetThrowStartPos();
+ Vector3d Speed = a_Player->GetLookVector() * 7;
+
+ if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity::pkSplashPotion, a_Player, &a_Player->GetEquippedItem(), &Speed) < 0)
+ {
+ return false;
+ }
+
+ if (!a_Player->IsGameModeCreative())
+ {
+ a_Player->GetInventory().RemoveOneEquippedItem();
+ }
+
+ return true;
+ }
+
+
+ virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) override
+ {
+ short PotionDamage = a_Item->m_ItemDamage;
+
+ // Do not drink undrinkable potions:
+ if (!cEntityEffect::IsPotionDrinkable(a_Item->m_ItemDamage))
+ {
+ return false;
+ }
+
+ a_Player->AddEntityEffect(
+ cEntityEffect::GetPotionEffectType(PotionDamage),
+ cEntityEffect::GetPotionEffectDuration(PotionDamage),
+ cEntityEffect::GetPotionEffectIntensity(PotionDamage)
+ );
+ a_Player->GetInventory().RemoveOneEquippedItem();
+ a_Player->GetInventory().AddItem(E_ITEM_GLASS_BOTTLE);
+ return true;
+ }
+};
+
+
+
+
diff --git a/src/Items/ItemRedstoneDust.h b/src/Items/ItemRedstoneDust.h
index 274d905a5..a2289239c 100644
--- a/src/Items/ItemRedstoneDust.h
+++ b/src/Items/ItemRedstoneDust.h
@@ -22,12 +22,12 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
- if (!cBlockInfo::FullyOccupiesVoxel(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ))) // Some solid blocks, such as cocoa beans, are not suitable for dust
+ if (!cBlockInfo::FullyOccupiesVoxel(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ))) // Some solid blocks, such as cocoa beans, are not suitable for dust
{
return false;
}
diff --git a/src/Items/ItemRedstoneRepeater.h b/src/Items/ItemRedstoneRepeater.h
index c5fb5d566..13a797d00 100644
--- a/src/Items/ItemRedstoneRepeater.h
+++ b/src/Items/ItemRedstoneRepeater.h
@@ -24,7 +24,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemSapling.h b/src/Items/ItemSapling.h
index 61b1a32be..dbcb12be5 100644
--- a/src/Items/ItemSapling.h
+++ b/src/Items/ItemSapling.h
@@ -20,7 +20,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemSeeds.h b/src/Items/ItemSeeds.h
index 7283edcee..54a1183d7 100644
--- a/src/Items/ItemSeeds.h
+++ b/src/Items/ItemSeeds.h
@@ -25,12 +25,12 @@ public:
virtual bool IsFood(void) override
{
- switch (m_ItemType) // Special cases, both a seed and food
+ switch (m_ItemType) // Special cases, both a seed and food
{
case E_ITEM_CARROT:
case E_ITEM_POTATO: return true;
default: return false;
- }
+ }
}
virtual FoodInfo GetFoodInfo(void) override
@@ -40,12 +40,12 @@ public:
case E_ITEM_CARROT: return FoodInfo(4, 4.8);
case E_ITEM_POTATO: return FoodInfo(1, 0.6);
default: return FoodInfo(0, 0);
- }
+ }
}
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemShears.h b/src/Items/ItemShears.h
index 39d2776fa..fa2794df2 100644
--- a/src/Items/ItemShears.h
+++ b/src/Items/ItemShears.h
@@ -12,6 +12,7 @@
class cItemShearsHandler :
public cItemHandler
{
+ typedef cItemHandler super;
public:
cItemShearsHandler(int a_ItemType) :
cItemHandler(a_ItemType)
@@ -30,8 +31,12 @@ public:
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if ((Block == E_BLOCK_LEAVES) || (Block == E_BLOCK_NEW_LEAVES))
{
+ NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ cBlockHandler * Handler = cBlockInfo::GetHandler(Block);
+
cItems Drops;
- Drops.push_back(cItem(Block, 1, a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x03));
+ Handler->ConvertToPickups(Drops, Meta);
+ Drops.push_back(cItem(Block, 1, Meta & 3));
a_World->SpawnItemPickups(Drops, a_BlockX, a_BlockY, a_BlockZ);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
@@ -54,7 +59,25 @@ public:
return true;
}
} // switch (a_BlockType)
- return false;
+ return super::CanHarvestBlock(a_BlockType);
+ }
+
+
+ virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) override
+ {
+ return 0;
+ }
+
+
+ virtual void OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ super::OnBlockDestroyed(a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ);
+
+ BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
+ if ((Block == E_BLOCK_TRIPWIRE) || (Block == E_BLOCK_VINES))
+ {
+ a_Player->UseEquippedItem();
+ }
}
} ;
diff --git a/src/Items/ItemShovel.h b/src/Items/ItemShovel.h
index 333ba46e8..cd235678d 100644
--- a/src/Items/ItemShovel.h
+++ b/src/Items/ItemShovel.h
@@ -14,11 +14,11 @@
class cItemShovelHandler : public cItemHandler
{
+ typedef cItemHandler super;
public:
cItemShovelHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
-
}
virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
@@ -28,7 +28,7 @@ public:
{
cChunkInterface ChunkInterface(a_World->GetChunkMap());
cBlockInServerPluginInterface PluginInterface(*a_World);
- BlockHandler(Block)->DropBlock(ChunkInterface,*a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ);
+ BlockHandler(Block)->DropBlock(ChunkInterface, *a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_Player->UseEquippedItem();
@@ -39,7 +39,11 @@ public:
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) override
{
- return (a_BlockType == E_BLOCK_SNOW);
+ if (a_BlockType == E_BLOCK_SNOW)
+ {
+ return true;
+ }
+ return super::CanHarvestBlock(a_BlockType);
}
virtual bool CanRepairWithRawMaterial(short a_ItemType) override
diff --git a/src/Items/ItemSign.h b/src/Items/ItemSign.h
index 60cf0f5f8..0fa0fa0be 100644
--- a/src/Items/ItemSign.h
+++ b/src/Items/ItemSign.h
@@ -3,7 +3,8 @@
#include "ItemHandler.h"
#include "../World.h"
-#include "../Blocks/BlockSign.h"
+#include "../Blocks/BlockSignPost.h"
+#include "../Blocks/BlockWallSign.h"
@@ -27,19 +28,19 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
if (a_BlockFace == BLOCK_FACE_TOP)
{
- a_BlockMeta = cBlockSignHandler::RotationToMetaData(a_Player->GetYaw());
+ a_BlockMeta = cBlockSignPostHandler::RotationToMetaData(a_Player->GetYaw());
a_BlockType = E_BLOCK_SIGN_POST;
}
else
{
- a_BlockMeta = cBlockSignHandler::DirectionToMetaData(a_BlockFace);
+ a_BlockMeta = cBlockWallSignHandler::DirectionToMetaData(a_BlockFace);
a_BlockType = E_BLOCK_WALLSIGN;
}
return true;
diff --git a/src/Items/ItemSugarcane.h b/src/Items/ItemSugarcane.h
index e891cc367..dd2e2ece3 100644
--- a/src/Items/ItemSugarcane.h
+++ b/src/Items/ItemSugarcane.h
@@ -23,7 +23,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
diff --git a/src/Items/ItemSword.h b/src/Items/ItemSword.h
index 44feb2d83..2b2dbfc0d 100644
--- a/src/Items/ItemSword.h
+++ b/src/Items/ItemSword.h
@@ -12,18 +12,24 @@
class cItemSwordHandler :
public cItemHandler
{
+ typedef cItemHandler super;
public:
cItemSwordHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
-
}
-
+
+
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) override
{
- return (a_BlockType == E_BLOCK_COBWEB);
+ if (a_BlockType == E_BLOCK_COBWEB)
+ {
+ return true;
+ }
+ return super::CanHarvestBlock(a_BlockType);
}
+
virtual bool CanRepairWithRawMaterial(short a_ItemType) override
{
switch (m_ItemType)
@@ -36,6 +42,17 @@ public:
}
return false;
}
+
+
+ virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) override
+ {
+ switch ((int)a_Action)
+ {
+ case dlaAttackEntity: return 1;
+ case dlaBreakBlock: return 2;
+ }
+ return 0;
+ }
} ;
diff --git a/src/Items/ItemThrowable.h b/src/Items/ItemThrowable.h
index 25935a1bc..c151c5d3a 100644
--- a/src/Items/ItemThrowable.h
+++ b/src/Items/ItemThrowable.h
@@ -33,16 +33,9 @@ public:
// Play sound
cFastRandom Random;
- a_World->BroadcastSoundEffect(
- "random.bow",
- (int)std::floor(a_Player->GetPosX() * 8.0),
- (int)std::floor((a_Player->GetPosY() - a_Player->GetHeight()) * 8.0),
- (int)std::floor(a_Player->GetPosZ() * 8.0),
- 0.5F,
- 0.4F / (Random.NextFloat(1.0F) * 0.4F + 0.8F)
- );
-
- if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed) < 0)
+ a_World->BroadcastSoundEffect("random.bow", a_Player->GetPosX(), a_Player->GetPosY() - a_Player->GetHeight(), a_Player->GetPosZ(), 0.5f, 0.4f / (Random.NextFloat(1.0f) * 0.4f + 0.8f));
+
+ if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem(), &Speed) < 0)
{
return false;
}
@@ -142,7 +135,7 @@ public:
return false;
}
- if (a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, a_Player->GetEquippedItem()) < 0)
+ if (a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem()) < 0)
{
return false;
}
diff --git a/src/LightingThread.cpp b/src/LightingThread.cpp
index 33bc08467..3fbbee6b5 100644
--- a/src/LightingThread.cpp
+++ b/src/LightingThread.cpp
@@ -84,7 +84,7 @@ public:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cLightingThread:
cLightingThread::cLightingThread(void) :
@@ -495,7 +495,7 @@ void cLightingThread::CalcLight(NIBBLETYPE * a_Light)
void cLightingThread::CalcLightStep(
- NIBBLETYPE * a_Light,
+ NIBBLETYPE * a_Light,
int a_NumSeedsIn, unsigned char * a_IsSeedIn, unsigned int * a_SeedIdxIn,
int & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut
)
@@ -582,7 +582,7 @@ void cLightingThread::QueueChunkStay(cLightingChunkStay & a_ChunkStay)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cLightingThread::cLightingChunkStay:
cLightingThread::cLightingChunkStay::cLightingChunkStay(cLightingThread & a_LightingThread, int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_CallbackAfter) :
diff --git a/src/LightingThread.h b/src/LightingThread.h
index a484fcbed..f71d2cf1a 100644
--- a/src/LightingThread.h
+++ b/src/LightingThread.h
@@ -16,7 +16,7 @@ Lighting is calculated in a flood-fill fashion:
The seeds need two fast operations:
- Check if a block at [x, y, z] is already a seed
- Get the next seed in the row
-For that reason it is stored in two arrays, one stores a bool saying a seed is in that position,
+For that reason it is stored in two arrays, one stores a bool saying a seed is in that position,
the other is an array of seed coords, encoded as a single int.
Step 2 needs two separate storages for old seeds and new seeds, so there are two actual storages for that purpose,
their content is swapped after each full step-2-cycle.
@@ -82,7 +82,7 @@ protected:
cLightingChunkStay(cLightingThread & a_LightingThread, int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_CallbackAfter);
protected:
- virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) override
+ virtual void OnChunkAvailable(int a_ChunkX, int a_ChunkZ) override
{
UNUSED(a_ChunkX);
UNUSED(a_ChunkZ);
@@ -157,7 +157,7 @@ protected:
/** Does one step in the light calculation - one seed propagation and seed recalculation */
void CalcLightStep(
- NIBBLETYPE * a_Light,
+ NIBBLETYPE * a_Light,
int a_NumSeedsIn, unsigned char * a_IsSeedIn, unsigned int * a_SeedIdxIn,
int & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut
);
@@ -166,7 +166,7 @@ protected:
void CompressLight(NIBBLETYPE * a_LightArray, NIBBLETYPE * a_ChunkLight);
inline void PropagateLight(
- NIBBLETYPE * a_Light,
+ NIBBLETYPE * a_Light,
unsigned int a_SrcIdx, unsigned int a_DstIdx,
int & a_NumSeedsOut, unsigned char * a_IsSeedOut, unsigned int * a_SeedIdxOut
)
diff --git a/src/LineBlockTracer.cpp b/src/LineBlockTracer.cpp
index b03652bab..f03e796d1 100644
--- a/src/LineBlockTracer.cpp
+++ b/src/LineBlockTracer.cpp
@@ -203,54 +203,55 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk)
m_Callbacks->OnNoChunk();
return false;
}
- if (a_Chunk->IsValid())
+
+ // Move to next block
+ if (!MoveToNextBlock())
{
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- int RelX = m_CurrentX - a_Chunk->GetPosX() * cChunkDef::Width;
- int RelZ = m_CurrentZ - a_Chunk->GetPosZ() * cChunkDef::Width;
- a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta);
- if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta, m_CurrentFace))
- {
- // The callback terminated the trace
- return false;
- }
+ // We've reached the end
+ m_Callbacks->OnNoMoreHits();
+ return true;
}
- else
+
+ if ((m_CurrentY < 0) || (m_CurrentY >= cChunkDef::Height))
{
- if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ, m_CurrentFace))
+ // We've gone out of the world, that's the end of this trace
+ double IntersectX, IntersectZ;
+ CalcXZIntersection(m_CurrentY, IntersectX, IntersectZ);
+ if (m_Callbacks->OnOutOfWorld(IntersectX, m_CurrentY, IntersectZ))
{
// The callback terminated the trace
return false;
}
- }
-
- // Move to next block
- if (!MoveToNextBlock())
- {
- // We've reached the end
m_Callbacks->OnNoMoreHits();
return true;
}
-
+
// Update the current chunk
if (a_Chunk != NULL)
{
a_Chunk = a_Chunk->GetNeighborChunk(m_CurrentX, m_CurrentZ);
}
-
- if ((m_CurrentY < 0) || (m_CurrentY >= cChunkDef::Height))
+
+ if (a_Chunk->IsValid())
{
- // We've gone out of the world, that's the end of this trace
- double IntersectX, IntersectZ;
- CalcXZIntersection(m_CurrentY, IntersectX, IntersectZ);
- if (m_Callbacks->OnOutOfWorld(IntersectX, m_CurrentY, IntersectZ))
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ int RelX = m_CurrentX - a_Chunk->GetPosX() * cChunkDef::Width;
+ int RelZ = m_CurrentZ - a_Chunk->GetPosZ() * cChunkDef::Width;
+ a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta);
+ if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta, m_CurrentFace))
+ {
+ // The callback terminated the trace
+ return false;
+ }
+ }
+ else
+ {
+ if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ, m_CurrentFace))
{
// The callback terminated the trace
return false;
}
- m_Callbacks->OnNoMoreHits();
- return true;
}
}
}
diff --git a/src/Log.cpp b/src/Log.cpp
deleted file mode 100644
index a7be04b1a..000000000
--- a/src/Log.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "Log.h"
-
-#include <fstream>
-#include <ctime>
-#include "OSSupport/IsThread.h"
-
-#if defined(ANDROID_NDK)
- #include <android/log.h>
- #include "ToJava.h"
-#endif
-
-
-
-
-cLog* cLog::s_Log = NULL;
-
-cLog::cLog(const AString & a_FileName )
- : m_File(NULL)
-{
- s_Log = this;
-
- // create logs directory
- cFile::CreateFolder(FILE_IO_PREFIX + AString("logs"));
-
- OpenLog((FILE_IO_PREFIX + AString("logs/") + a_FileName).c_str() );
-}
-
-
-
-
-
-cLog::~cLog()
-{
- CloseLog();
- s_Log = NULL;
-}
-
-
-
-
-
-cLog * cLog::GetInstance()
-{
- if (s_Log != NULL)
- {
- return s_Log;
- }
-
- new cLog("log.txt");
- return s_Log;
-}
-
-
-
-
-
-void cLog::CloseLog()
-{
- if( m_File )
- fclose (m_File);
- m_File = 0;
-}
-
-
-
-
-
-void cLog::OpenLog( const char* a_FileName )
-{
- if(m_File) fclose (m_File);
- #ifdef _MSC_VER
- fopen_s( &m_File, a_FileName, "a+" );
- #else
- m_File = fopen(a_FileName, "a+" );
- #endif
-}
-
-
-
-
-
-void cLog::ClearLog()
-{
- #ifdef _MSC_VER
- if( fopen_s( &m_File, "log.txt", "w" ) == 0)
- fclose (m_File);
- #else
- m_File = fopen("log.txt", "w" );
- if( m_File )
- fclose (m_File);
- #endif
- m_File = NULL;
-}
-
-
-
-
-
-void cLog::Log(const char * a_Format, va_list argList)
-{
- AString Message;
- AppendVPrintf(Message, a_Format, argList);
-
- time_t rawtime;
- time ( &rawtime );
-
- struct tm* timeinfo;
-#ifdef _MSC_VER
- struct tm timeinforeal;
- timeinfo = &timeinforeal;
- localtime_s(timeinfo, &rawtime );
-#else
- timeinfo = localtime( &rawtime );
-#endif
-
- AString Line;
- #ifdef _DEBUG
- Printf(Line, "[%04lx|%02d:%02d:%02d] %s", cIsThread::GetCurrentID(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, Message.c_str());
- #else
- Printf(Line, "[%02d:%02d:%02d] %s", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, Message.c_str());
- #endif
- if (m_File)
- {
- fprintf(m_File, "%s\n", Line.c_str());
- fflush(m_File);
- }
-
- // Print to console:
-#if defined(ANDROID_NDK)
- //__android_log_vprint(ANDROID_LOG_ERROR,"MCServer", a_Format, argList);
- __android_log_print(ANDROID_LOG_ERROR, "MCServer", "%s", Line.c_str() );
- //CallJavaFunction_Void_String(g_JavaThread, "AddToLog", Line );
-#else
- printf("%s", Line.c_str());
-#endif
-
- #if defined (_WIN32) && defined(_DEBUG)
- // In a Windows Debug build, output the log to debug console as well:
- OutputDebugStringA((Line + "\n").c_str());
- #endif // _WIN32
-}
-
-
-
-
-
-void cLog::Log(const char * a_Format, ...)
-{
- va_list argList;
- va_start(argList, a_Format);
- Log(a_Format, argList);
- va_end(argList);
-}
-
-
-
-
-
-void cLog::SimpleLog(const char * a_String)
-{
- Log("%s", a_String);
-}
-
-
-
-
diff --git a/src/Log.h b/src/Log.h
deleted file mode 100644
index d6a406154..000000000
--- a/src/Log.h
+++ /dev/null
@@ -1,30 +0,0 @@
-
-#pragma once
-
-
-
-
-
-class cLog
-{ // tolua_export
-private:
- FILE * m_File;
- static cLog * s_Log;
-
-public:
- cLog(const AString & a_FileName);
- ~cLog();
- void Log(const char * a_Format, va_list argList) FORMATSTRING(2, 0);
- void Log(const char * a_Format, ...) FORMATSTRING(2, 3);
- // tolua_begin
- void SimpleLog(const char * a_String);
- void OpenLog(const char * a_FileName);
- void CloseLog();
- void ClearLog();
- static cLog* GetInstance();
-};
-// tolua_end
-
-
-
-
diff --git a/src/Logger.cpp b/src/Logger.cpp
new file mode 100644
index 000000000..cb528e8ab
--- /dev/null
+++ b/src/Logger.cpp
@@ -0,0 +1,145 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "OSSupport/IsThread.h"
+#ifdef _WIN32
+ #include <time.h>
+#endif
+
+
+
+
+
+cLogger & cLogger::GetInstance(void)
+{
+ static cLogger Instance;
+ return Instance;
+}
+
+
+
+
+
+void cLogger::InitiateMultithreading()
+{
+ GetInstance();
+}
+
+
+
+
+
+void cLogger::LogSimple(AString a_Message, eLogLevel a_LogLevel)
+{
+ time_t rawtime;
+ time(&rawtime);
+
+ struct tm * timeinfo;
+ #ifdef _MSC_VER
+ struct tm timeinforeal;
+ timeinfo = &timeinforeal;
+ localtime_s(timeinfo, &rawtime);
+ #else
+ timeinfo = localtime(&rawtime);
+ #endif
+
+ AString Line;
+ #ifdef _DEBUG
+ Printf(Line, "[%04lx|%02d:%02d:%02d] %s\n", cIsThread::GetCurrentID(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str());
+ #else
+ Printf(Line, "[%02d:%02d:%02d] %s\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str());
+ #endif
+
+
+ cCSLock Lock(m_CriticalSection);
+ for (size_t i = 0; i < m_LogListeners.size(); i++)
+ {
+ m_LogListeners[i]->Log(Line, a_LogLevel);
+ }
+}
+
+
+
+
+
+void cLogger::Log(const char * a_Format, eLogLevel a_LogLevel, va_list a_ArgList)
+{
+ AString Message;
+ AppendVPrintf(Message, a_Format, a_ArgList);
+ LogSimple(Message, a_LogLevel);
+}
+
+
+
+
+
+void cLogger::AttachListener(cListener * a_Listener)
+{
+ cCSLock Lock(m_CriticalSection);
+ m_LogListeners.push_back(a_Listener);
+}
+
+
+
+
+
+void cLogger::DetachListener(cListener * a_Listener)
+{
+ cCSLock Lock(m_CriticalSection);
+ m_LogListeners.erase(std::remove(m_LogListeners.begin(), m_LogListeners.end(), a_Listener));
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Global functions
+
+void LOG(const char * a_Format, ...)
+{
+ va_list argList;
+ va_start(argList, a_Format);
+ cLogger::GetInstance().Log(a_Format, cLogger::llRegular, argList);
+ va_end(argList);
+}
+
+
+
+
+
+void LOGINFO(const char * a_Format, ...)
+{
+ va_list argList;
+ va_start(argList, a_Format);
+ cLogger::GetInstance().Log( a_Format, cLogger::llInfo, argList);
+ va_end(argList);
+}
+
+
+
+
+
+void LOGWARN(const char * a_Format, ...)
+{
+ va_list argList;
+ va_start(argList, a_Format);
+ cLogger::GetInstance().Log( a_Format, cLogger::llWarning, argList);
+ va_end(argList);
+}
+
+
+
+
+
+void LOGERROR(const char * a_Format, ...)
+{
+ va_list argList;
+ va_start(argList, a_Format);
+ cLogger::GetInstance().Log( a_Format, cLogger::llError, argList);
+ va_end(argList);
+}
+
+
+
+
diff --git a/src/Logger.h b/src/Logger.h
new file mode 100644
index 000000000..5e65de8a8
--- /dev/null
+++ b/src/Logger.h
@@ -0,0 +1,73 @@
+
+#pragma once
+
+
+class cLogger
+{
+public:
+
+ enum eLogLevel
+ {
+ llRegular,
+ llInfo,
+ llWarning,
+ llError,
+ };
+
+
+ class cListener
+ {
+ public:
+ virtual void Log(AString a_Message, eLogLevel a_LogLevel) = 0;
+
+ virtual ~cListener(){}
+ };
+
+ void Log (const char * a_Format, eLogLevel a_LogLevel, va_list a_ArgList) FORMATSTRING(2, 0);
+
+ /** Logs the simple text message at the specified log level. */
+ void LogSimple(AString a_Message, eLogLevel a_LogLevel = llRegular);
+
+ void AttachListener(cListener * a_Listener);
+ void DetachListener(cListener * a_Listener);
+
+ static cLogger & GetInstance(void);
+ // Must be called before calling GetInstance in a multithreaded context
+ static void InitiateMultithreading();
+private:
+
+ cCriticalSection m_CriticalSection;
+ std::vector<cListener *> m_LogListeners;
+
+};
+
+
+
+
+
+
+extern void LOG(const char* a_Format, ...) FORMATSTRING(1, 2);
+extern void LOGINFO(const char* a_Format, ...) FORMATSTRING(1, 2);
+extern void LOGWARN(const char* a_Format, ...) FORMATSTRING(1, 2);
+extern void LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2);
+
+
+
+
+
+// In debug builds, translate LOGD to LOG, otherwise leave it out altogether:
+#ifdef _DEBUG
+ #define LOGD LOG
+#else
+ #define LOGD(...)
+#endif // _DEBUG
+
+
+
+
+
+#define LOGWARNING LOGWARN
+
+
+
+
diff --git a/src/LoggerListeners.cpp b/src/LoggerListeners.cpp
new file mode 100644
index 000000000..836536cbd
--- /dev/null
+++ b/src/LoggerListeners.cpp
@@ -0,0 +1,322 @@
+
+#include "Globals.h"
+
+#include "LoggerListeners.h"
+
+#if defined(_WIN32)
+ #include <io.h> // Needed for _isatty(), not available on Linux
+ #include <time.h>
+#elif defined(__linux) && !defined(ANDROID_NDK)
+ #include <unistd.h> // Needed for isatty() on Linux
+#elif defined(ANDROID_NDK)
+ #include <android/log.h>
+#endif
+
+
+#if defined(_WIN32) || (defined (__linux) && !defined(ANDROID_NDK))
+ class cColouredConsoleListener
+ : public cLogger::cListener
+ {
+ protected:
+
+ virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) = 0;
+ virtual void SetDefaultLogColour() = 0;
+
+ virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
+ {
+ SetLogColour(a_LogLevel);
+ fputs(a_Message.c_str(), stdout);
+ SetDefaultLogColour();
+ }
+ };
+#endif
+
+
+
+
+
+#ifdef _WIN32
+ class cWindowsConsoleListener
+ : public cColouredConsoleListener
+ {
+ typedef cColouredConsoleListener super;
+ public:
+ cWindowsConsoleListener(HANDLE a_Console, WORD a_DefaultConsoleAttrib) :
+ m_Console(a_Console),
+ m_DefaultConsoleAttrib(a_DefaultConsoleAttrib)
+ {
+ }
+
+ #ifdef _DEBUG
+ virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
+ {
+ super::Log(a_Message, a_LogLevel);
+ // In a Windows Debug build, output the log to debug console as well:
+ OutputDebugStringA(a_Message.c_str());
+ }
+ #endif
+
+
+ virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) override
+ {
+ // by default, gray on black
+ WORD Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
+ switch (a_LogLevel)
+ {
+ case cLogger::llRegular:
+ {
+ // Gray on black
+ Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
+ break;
+ }
+ case cLogger::llInfo:
+ {
+ // Yellow on black
+ Attrib = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
+ break;
+ }
+ case cLogger::llWarning:
+ {
+ // Red on black
+ Attrib = FOREGROUND_RED | FOREGROUND_INTENSITY;
+ break;
+ }
+ case cLogger::llError:
+ {
+ // Black on red
+ Attrib = BACKGROUND_RED | BACKGROUND_INTENSITY;
+ break;
+ }
+ }
+ SetConsoleTextAttribute(m_Console, Attrib);
+ }
+
+
+ virtual void SetDefaultLogColour() override
+ {
+ SetConsoleTextAttribute(m_Console, m_DefaultConsoleAttrib);
+ }
+
+ private:
+
+ HANDLE m_Console;
+ WORD m_DefaultConsoleAttrib;
+ };
+
+
+
+#elif defined (__linux) && !defined(ANDROID_NDK)
+
+
+
+ class cLinuxConsoleListener
+ : public cColouredConsoleListener
+ {
+ public:
+ virtual void SetLogColour(cLogger::eLogLevel a_LogLevel) override
+ {
+ switch (a_LogLevel)
+ {
+ case cLogger::llRegular:
+ {
+ // Whatever the console default is
+ printf("\x1b[0m");
+ break;
+ }
+ case cLogger::llInfo:
+ {
+ // Yellow on black
+ printf("\x1b[33;1m");
+ break;
+ }
+ case cLogger::llWarning:
+ {
+ // Red on black
+ printf("\x1b[31;1m");
+ break;
+ }
+ case cLogger::llError:
+ {
+ // Yellow on red
+ printf("\x1b[1;33;41;1m");
+ break;
+ }
+ }
+ }
+
+
+ virtual void SetDefaultLogColour() override
+ {
+ // Whatever the console default is
+ printf("\x1b[0m");
+ }
+ };
+
+
+
+#elif defined(ANDROID_NDK)
+
+
+
+ class cAndroidConsoleListener
+ : public cLogger::cListener
+ {
+ public:
+ virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
+ {
+ android_LogPriority AndroidLogLevel;
+ switch (a_LogLevel)
+ {
+ case cLogger::llRegular:
+ {
+ AndroidLogLevel = ANDROID_LOG_VERBOSE;
+ break;
+ }
+ case cLogger::llInfo:
+ {
+ AndroidLogLevel = ANDROID_LOG_INFO;
+ break;
+ }
+ case cLogger::llWarning:
+ {
+ AndroidLogLevel = ANDROID_LOG_WARNING;
+ break;
+ }
+ case cLogger::llError:
+ {
+ AndroidLogLevel = ANDROID_LOG_ERROR;
+ break;
+ }
+ }
+ __android_log_print(AndroidLogLevel, "MCServer", "%s", a_Message.c_str());
+ }
+ };
+
+#endif
+
+
+
+
+
+class cVanillaCPPConsoleListener
+ : public cLogger::cListener
+{
+public:
+ virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override
+ {
+ AString LogLevelString;
+ switch (a_LogLevel)
+ {
+ case cLogger::llRegular:
+ {
+ LogLevelString = "Log";
+ break;
+ }
+ case cLogger::llInfo:
+ {
+ LogLevelString = "Info";
+ break;
+ }
+ case cLogger::llWarning:
+ {
+ LogLevelString = "Warning";
+ break;
+ }
+ case cLogger::llError:
+ {
+ LogLevelString = "Error";
+ break;
+ }
+ }
+ printf("%s: %s", LogLevelString.c_str(), a_Message.c_str());
+ }
+};
+
+
+
+
+
+cLogger::cListener * MakeConsoleListener(void)
+{
+ #ifdef _WIN32
+ // See whether we are writing to a console the default console attrib:
+ bool ShouldColorOutput = (_isatty(_fileno(stdin)) != 0);
+ if (ShouldColorOutput)
+ {
+ CONSOLE_SCREEN_BUFFER_INFO sbi;
+ HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
+ GetConsoleScreenBufferInfo(Console, &sbi);
+ WORD DefaultConsoleAttrib = sbi.wAttributes;
+ return new cWindowsConsoleListener(Console, DefaultConsoleAttrib);
+ }
+ else
+ {
+ return new cVanillaCPPConsoleListener;
+ }
+
+ #elif defined (__linux) && !defined(ANDROID_NDK)
+ // TODO: lookup terminal in terminfo
+ if (isatty(fileno(stdout)))
+ {
+ return new cLinuxConsoleListener();
+ }
+ else
+ {
+ return new cVanillaCPPConsoleListener();
+ }
+ #else
+ return new cVanillaCPPConsoleListener();
+ #endif
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cFileListener:
+
+cFileListener::cFileListener(void)
+{
+ cFile::CreateFolder(FILE_IO_PREFIX + AString("logs"));
+ AString FileName;
+ FileName = Printf("%s%sLOG_%d.txt", FILE_IO_PREFIX, "logs/", (int)time(NULL));
+ m_File.Open(FileName, cFile::fmAppend);
+}
+
+
+
+
+
+void cFileListener::Log(AString a_Message, cLogger::eLogLevel a_LogLevel)
+{
+ const char * LogLevelPrefix = "Unkn ";
+ switch (a_LogLevel)
+ {
+ case cLogger::llRegular:
+ {
+ LogLevelPrefix = " ";
+ break;
+ }
+ case cLogger::llInfo:
+ {
+ LogLevelPrefix = "info ";
+ break;
+ }
+ case cLogger::llWarning:
+ {
+ LogLevelPrefix = "Warn ";
+ break;
+ }
+ case cLogger::llError:
+ {
+ LogLevelPrefix = "Err ";
+ break;
+ }
+ }
+ m_File.Printf("%s%s", LogLevelPrefix, a_Message.c_str());
+}
+
+
+
+
diff --git a/src/LoggerListeners.h b/src/LoggerListeners.h
new file mode 100644
index 000000000..d300184b1
--- /dev/null
+++ b/src/LoggerListeners.h
@@ -0,0 +1,31 @@
+
+#include "Logger.h"
+
+
+
+
+
+class cFileListener
+ : public cLogger::cListener
+{
+public:
+
+ cFileListener();
+ cFileListener(AString a_Filename);
+
+ virtual void Log(AString a_Message, cLogger::eLogLevel a_LogLevel) override;
+
+private:
+
+ cFile m_File;
+};
+
+
+
+
+
+cLogger::cListener * MakeConsoleListener();
+
+
+
+
diff --git a/src/MCLogger.cpp b/src/MCLogger.cpp
deleted file mode 100644
index ad2029589..000000000
--- a/src/MCLogger.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include <time.h>
-#include "Log.h"
-
-
-
-
-
-cMCLogger * cMCLogger::s_MCLogger = NULL;
-
-#ifdef _WIN32
- #include <io.h> // Needed for _isatty(), not available on Linux
-
- HANDLE g_Console = GetStdHandle(STD_OUTPUT_HANDLE);
- WORD g_DefaultConsoleAttrib = 0x07;
-#elif defined (__linux) && !defined(ANDROID_NDK)
- #include <unistd.h> // Needed for isatty() on Linux
-#endif
-
-
-
-
-
-cMCLogger * cMCLogger::GetInstance(void)
-{
- return s_MCLogger;
-}
-
-
-
-
-
-cMCLogger::cMCLogger(void):
- m_ShouldColorOutput(false)
-{
- AString FileName;
- Printf(FileName, "LOG_%d.txt", (int)time(NULL));
- InitLog(FileName);
-}
-
-
-
-
-
-cMCLogger::cMCLogger(const AString & a_FileName)
-{
- InitLog(a_FileName);
-}
-
-
-
-
-
-cMCLogger::~cMCLogger()
-{
- m_Log->Log("--- Stopped Log ---\n");
- delete m_Log;
- m_Log = NULL;
- if (this == s_MCLogger)
- {
- s_MCLogger = NULL;
- }
-}
-
-
-
-
-
-void cMCLogger::InitLog(const AString & a_FileName)
-{
- m_Log = new cLog(a_FileName);
- m_Log->Log("--- Started Log ---\n");
-
- s_MCLogger = this;
-
- #ifdef _WIN32
- // See whether we are writing to a console the default console attrib:
- m_ShouldColorOutput = (_isatty(_fileno(stdin)) != 0);
- if (m_ShouldColorOutput)
- {
- CONSOLE_SCREEN_BUFFER_INFO sbi;
- GetConsoleScreenBufferInfo(g_Console, &sbi);
- g_DefaultConsoleAttrib = sbi.wAttributes;
- }
- #elif defined (__linux) && !defined(ANDROID_NDK)
- m_ShouldColorOutput = isatty(fileno(stdout));
- // TODO: Check if the terminal supports colors, somehow?
- #endif
-}
-
-
-
-
-
-void cMCLogger::LogSimple(const char * a_Text, eLogLevel a_LogLevel)
-{
- switch (a_LogLevel)
- {
- case llRegular:
- {
- LOG("%s", a_Text);
- break;
- }
- case llInfo:
- {
- LOGINFO("%s", a_Text);
- break;
- }
- case llWarning:
- {
- LOGWARN("%s", a_Text);
- break;
- }
- case llError:
- {
- LOGERROR("%s", a_Text);
- break;
- }
- }
-}
-
-
-
-
-
-void cMCLogger::Log(const char * a_Format, va_list a_ArgList)
-{
- cCSLock Lock(m_CriticalSection);
- SetColor(csRegular);
- m_Log->Log(a_Format, a_ArgList);
- ResetColor();
- puts("");
-}
-
-
-
-
-
-void cMCLogger::Info(const char * a_Format, va_list a_ArgList)
-{
- cCSLock Lock(m_CriticalSection);
- SetColor(csInfo);
- m_Log->Log(a_Format, a_ArgList);
- ResetColor();
- puts("");
-}
-
-
-
-
-
-void cMCLogger::Warn(const char * a_Format, va_list a_ArgList)
-{
- cCSLock Lock(m_CriticalSection);
- SetColor(csWarning);
- m_Log->Log(a_Format, a_ArgList);
- ResetColor();
- puts("");
-}
-
-
-
-
-
-void cMCLogger::Error(const char * a_Format, va_list a_ArgList)
-{
- cCSLock Lock(m_CriticalSection);
- SetColor(csError);
- m_Log->Log(a_Format, a_ArgList);
- ResetColor();
- puts("");
-}
-
-
-
-
-
-void cMCLogger::SetColor(eColorScheme a_Scheme)
-{
- if (!m_ShouldColorOutput)
- {
- return;
- }
- #ifdef _WIN32
- WORD Attrib = 0x07; // by default, gray on black
- switch (a_Scheme)
- {
- case csRegular: Attrib = 0x07; break; // Gray on black
- case csInfo: Attrib = 0x0e; break; // Yellow on black
- case csWarning: Attrib = 0x0c; break; // Read on black
- case csError: Attrib = 0xc0; break; // Black on red
- default: ASSERT(!"Unhandled color scheme");
- }
- SetConsoleTextAttribute(g_Console, Attrib);
- #elif defined(__linux) && !defined(ANDROID_NDK)
- switch (a_Scheme)
- {
- case csRegular: printf("\x1b[0m"); break; // Whatever the console default is
- case csInfo: printf("\x1b[33;1m"); break; // Yellow on black
- case csWarning: printf("\x1b[31;1m"); break; // Red on black
- case csError: printf("\x1b[1;33;41;1m"); break; // Yellow on red
- default: ASSERT(!"Unhandled color scheme");
- }
- #endif
-}
-
-
-
-
-
-void cMCLogger::ResetColor(void)
-{
- if (!m_ShouldColorOutput)
- {
- return;
- }
- #ifdef _WIN32
- SetConsoleTextAttribute(g_Console, g_DefaultConsoleAttrib);
- #elif defined(__linux) && !defined(ANDROID_NDK)
- printf("\x1b[0m");
- #endif
-}
-
-
-
-
-
-//////////////////////////////////////////////////////////////////////////
-// Global functions
-
-void LOG(const char* a_Format, ...)
-{
- va_list argList;
- va_start(argList, a_Format);
- cMCLogger::GetInstance()->Log( a_Format, argList );
- va_end(argList);
-}
-
-void LOGINFO(const char* a_Format, ...)
-{
- va_list argList;
- va_start(argList, a_Format);
- cMCLogger::GetInstance()->Info( a_Format, argList );
- va_end(argList);
-}
-
-void LOGWARN(const char* a_Format, ...)
-{
- va_list argList;
- va_start(argList, a_Format);
- cMCLogger::GetInstance()->Warn( a_Format, argList );
- va_end(argList);
-}
-
-void LOGERROR(const char* a_Format, ...)
-{
- va_list argList;
- va_start(argList, a_Format);
- cMCLogger::GetInstance()->Error( a_Format, argList );
- va_end(argList);
-}
-
-
-
-
diff --git a/src/MCLogger.h b/src/MCLogger.h
deleted file mode 100644
index 114210f63..000000000
--- a/src/MCLogger.h
+++ /dev/null
@@ -1,96 +0,0 @@
-
-#pragma once
-
-
-
-
-class cLog;
-
-
-
-
-
-// tolua_begin
-class cMCLogger
-{
-public:
- enum eLogLevel
- {
- llRegular,
- llInfo,
- llWarning,
- llError,
- };
- // tolua_end
-
- /** Creates a logger with the default filename, "logs/LOG_<timestamp>.log" */
- cMCLogger(void);
-
- /** Creates a logger with the specified filename inside "logs" folder */
- cMCLogger(const AString & a_FileName); // tolua_export
-
- ~cMCLogger(); // tolua_export
-
- void Log (const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0);
- void Info (const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0);
- void Warn (const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0);
- void Error(const char * a_Format, va_list a_ArgList) FORMATSTRING(2, 0);
-
- /** Logs the simple text message at the specified log level. */
- void LogSimple(const char * a_Text, eLogLevel a_LogLevel = llRegular); // tolua_export
-
- static cMCLogger * GetInstance();
-private:
- enum eColorScheme
- {
- csRegular,
- csInfo,
- csWarning,
- csError,
- } ;
-
- cCriticalSection m_CriticalSection;
- cLog * m_Log;
- static cMCLogger * s_MCLogger;
- bool m_ShouldColorOutput;
-
-
- /// Sets the specified color scheme in the terminal (TODO: if coloring available)
- void SetColor(eColorScheme a_Scheme);
-
- /// Resets the color back to whatever is the default in the terminal
- void ResetColor(void);
-
- /// Common initialization for all constructors, creates a logfile with the specified name and assigns s_MCLogger to this
- void InitLog(const AString & a_FileName);
-}; // tolua_export
-
-
-
-
-
-extern void LOG(const char* a_Format, ...) FORMATSTRING(1, 2);
-extern void LOGINFO(const char* a_Format, ...) FORMATSTRING(1, 2);
-extern void LOGWARN(const char* a_Format, ...) FORMATSTRING(1, 2);
-extern void LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2);
-
-
-
-
-
-// In debug builds, translate LOGD to LOG, otherwise leave it out altogether:
-#ifdef _DEBUG
- #define LOGD LOG
-#else
- #define LOGD(...)
-#endif // _DEBUG
-
-
-
-
-
-#define LOGWARNING LOGWARN
-
-
-
-
diff --git a/src/Map.cpp b/src/Map.cpp
index 7721baa70..8f205a606 100644
--- a/src/Map.cpp
+++ b/src/Map.cpp
@@ -200,8 +200,8 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z)
int BlockX = m_CenterX + ((a_X - (m_Width / 2)) * PixelWidth);
int BlockZ = m_CenterZ + ((a_Z - (m_Height / 2)) * PixelWidth);
- int ChunkX, ChunkY, ChunkZ;
- m_World->BlockToChunk(BlockX, 0, BlockZ, ChunkX, ChunkY, ChunkZ);
+ int ChunkX, ChunkZ;
+ cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
int RelX = BlockX - (ChunkX * cChunkDef::Width);
int RelZ = BlockZ - (ChunkZ * cChunkDef::Width);
diff --git a/src/Map.h b/src/Map.h
index e23ca2c92..fe324a5e7 100644
--- a/src/Map.h
+++ b/src/Map.h
@@ -29,13 +29,12 @@ class cMap;
/** Encapsulates a map decorator.
- *
- * A map decorator represents an object drawn on the map that can move freely.
- * (e.g. player trackers and item frame pointers)
- *
- * Excluding manually placed decorators,
- * decorators are automatically managed (allocated and freed) by their parent cMap instance.
- */
+A map decorator represents an object drawn on the map that can move freely.
+(e.g. player trackers and item frame pointers)
+
+Excluding manually placed decorators,
+decorators are automatically managed (allocated and freed) by their parent cMap instance.
+*/
class cMapDecorator
{
public:
@@ -194,10 +193,9 @@ public:
protected:
/** Encapsulates the state of a map client.
- *
- * In order to enhance performace, maps are streamed column-by-column to each client.
- * This structure stores the state of the stream.
- */
+ In order to enhance performace, maps are streamed column-by-column to each client.
+ This structure stores the state of the stream.
+ */
struct cMapClient
{
cClientHandle * m_Handle;
@@ -258,7 +256,7 @@ private:
friend class cMapSerializer;
-}; // tolua_export
+}; // tolua_export
diff --git a/src/MapManager.h b/src/MapManager.h
index ceab8f126..a40ec2630 100644
--- a/src/MapManager.h
+++ b/src/MapManager.h
@@ -32,28 +32,25 @@ public:
cMapManager(cWorld * a_World);
/** Returns the map with the specified ID, NULL if out of range.
- *
- * WARNING: The returned map object is not thread safe.
- */
+ WARNING: The returned map object is not thread safe.
+ */
cMap * GetMapData(unsigned int a_ID);
/** Creates a new map. Returns NULL on error */
cMap * CreateMap(int a_CenterX, int a_CenterY, int a_Scale = 3);
/** Calls the callback for the map with the specified ID.
- *
- * Returns true if the map was found and the callback called, false if map not found.
- * Callback return ignored.
- */
- bool DoWithMap(int a_ID, cMapCallback & a_Callback); // Exported in ManualBindings.cpp
-
- /** Calls the callback for each map.
- *
- * Returns true if all maps processed, false if the callback aborted by returning true.
- */
+ Returns true if the map was found and the callback called, false if map not found.
+ Callback return value is ignored.
+ */
+ bool DoWithMap(int a_ID, cMapCallback & a_Callback); // Exported in ManualBindings.cpp
+
+ /** Calls the callback for each map.
+ Returns true if all maps processed, false if the callback aborted by returning true.
+ */
bool ForEachMap(cMapCallback & a_Callback);
- size_t GetNumMaps(void) const; // tolua_export
+ size_t GetNumMaps(void) const; // tolua_export
/** Loads the map data from the disk */
void LoadMapData(void);
@@ -72,7 +69,7 @@ private:
cWorld * m_World;
-}; // tolua_export
+}; // tolua_export
diff --git a/src/Matrix4.h b/src/Matrix4.h
index 456677f0f..61ea60bfd 100644
--- a/src/Matrix4.h
+++ b/src/Matrix4.h
@@ -3,7 +3,7 @@
-#define _USE_MATH_DEFINES // Enable non-standard math defines (MSVC)
+#define _USE_MATH_DEFINES // Enable non-standard math defines (MSVC)
#include <math.h>
@@ -34,6 +34,8 @@ public:
{
*this = a_Rhs;
}
+
+ // tolua_end
inline Matrix4 & operator = (const Matrix4 & a_Rhs)
{
@@ -43,6 +45,8 @@ public:
}
return *this;
}
+
+ // tolua_begin
inline T & operator [] (int a_N)
{
@@ -104,7 +108,7 @@ public:
}
inline void Translate(const Vector3<T> & a_Pos)
- {
+ {
cell[3] += a_Pos.x;
cell[7] += a_Pos.y;
cell[11] += a_Pos.z;
diff --git a/src/MobCensus.cpp b/src/MobCensus.cpp
index 23f74b59e..4109aff07 100644
--- a/src/MobCensus.cpp
+++ b/src/MobCensus.cpp
@@ -19,9 +19,9 @@ void cMobCensus::CollectMob(cMonster & a_Monster, cChunk & a_Chunk, double a_Dis
bool cMobCensus::IsCapped(cMonster::eFamily a_MobFamily)
{
- const int ratio = 319; // this should be 256 as we are only supposed to take account from chunks that are in 17x17 from a player
+ const int ratio = 319; // This should be 256 as we are only supposed to take account from chunks that are in 17x17 from a player
// but for now, we use all chunks loaded by players. that means 19 x 19 chunks. That's why we use 256 * (19*19) / (17*17) = 319
- // MG TODO : code the correct count
+ // MG TODO : code the correct count
if ((GetCapMultiplier(a_MobFamily) * GetNumChunks()) / ratio >= m_MobFamilyCollecter.GetNumberOfCollectedMobs(a_MobFamily))
{
return false;
diff --git a/src/MobFamilyCollecter.h b/src/MobFamilyCollecter.h
index 6cef133b5..c4324bd68 100644
--- a/src/MobFamilyCollecter.h
+++ b/src/MobFamilyCollecter.h
@@ -4,7 +4,7 @@
#include <map>
#include <set>
#include "BlockID.h"
-#include "Mobs/Monster.h" //this is a side-effect of keeping Mobfamily inside Monster class. I'd prefer to keep both (Mobfamily and Monster) inside a "Monster" namespace MG TODO : do it
+#include "Mobs/Monster.h" // This is a side-effect of keeping Mobfamily inside Monster class. I'd prefer to keep both (Mobfamily and Monster) inside a "Monster" namespace MG TODO : do it
@@ -29,7 +29,7 @@ public :
// return the number of mobs for this family
int GetNumberOfCollectedMobs(cMonster::eFamily a_Family);
-protected :
+protected :
std::map<cMonster::eFamily, std::set<cMonster *> > m_Mobs;
} ;
diff --git a/src/MobProximityCounter.cpp b/src/MobProximityCounter.cpp
index ce20bf56b..82ba771ff 100644
--- a/src/MobProximityCounter.cpp
+++ b/src/MobProximityCounter.cpp
@@ -8,12 +8,12 @@
void cMobProximityCounter::CollectMob(cEntity& a_Monster, cChunk& a_Chunk, double a_Distance)
{
-// LOGD("Collecting monster %s, with distance %f",a_Monster->GetClass(),a_Distance);
+ // LOGD("Collecting monster %s, with distance %f", a_Monster->GetClass(), a_Distance);
tMonsterToDistance::iterator it = m_MonsterToDistance.find(&a_Monster);
if (it == m_MonsterToDistance.end())
{
- sDistanceAndChunk newDistanceAndChunk(a_Distance,a_Chunk);
- std::pair<tMonsterToDistance::iterator,bool> result = m_MonsterToDistance.insert(tMonsterToDistance::value_type(&a_Monster,newDistanceAndChunk));
+ sDistanceAndChunk newDistanceAndChunk(a_Distance, a_Chunk);
+ std::pair<tMonsterToDistance::iterator, bool> result = m_MonsterToDistance.insert(tMonsterToDistance::value_type(&a_Monster, newDistanceAndChunk));
if (!result.second)
{
ASSERT(!"A collected Monster was not found inside distance map using find(), but insert() said there already is a key for it");
@@ -34,9 +34,9 @@ void cMobProximityCounter::CollectMob(cEntity& a_Monster, cChunk& a_Chunk, doubl
void cMobProximityCounter::convertMaps()
{
- for(tMonsterToDistance::const_iterator itr = m_MonsterToDistance.begin(); itr != m_MonsterToDistance.end(); ++itr)
+ for (tMonsterToDistance::const_iterator itr = m_MonsterToDistance.begin(); itr != m_MonsterToDistance.end(); ++itr)
{
- m_DistanceToMonster.insert(tDistanceToMonster::value_type(itr->second.m_Distance,sMonsterAndChunk(*itr->first,*itr->second.m_Chunk)));
+ m_DistanceToMonster.insert(tDistanceToMonster::value_type(itr->second.m_Distance, sMonsterAndChunk(*itr->first, *itr->second.m_Chunk)));
}
}
@@ -55,13 +55,13 @@ cMobProximityCounter::sIterablePair cMobProximityCounter::getMobWithinThosesDist
convertMaps();
}
- for(tDistanceToMonster::const_iterator itr = m_DistanceToMonster.begin(); itr != m_DistanceToMonster.end(); ++itr)
+ for (tDistanceToMonster::const_iterator itr = m_DistanceToMonster.begin(); itr != m_DistanceToMonster.end(); ++itr)
{
if (toReturn.m_Begin == m_DistanceToMonster.end())
{
if ((a_DistanceMin == 1) || (itr->first > a_DistanceMin))
{
- toReturn.m_Begin = itr; // this is the first one with distance > a_DistanceMin;
+ toReturn.m_Begin = itr; // This is the first one with distance > a_DistanceMin;
}
}
@@ -69,7 +69,7 @@ cMobProximityCounter::sIterablePair cMobProximityCounter::getMobWithinThosesDist
{
if ((a_DistanceMax != 1) && (itr->first > a_DistanceMax))
{
- toReturn.m_End = itr; // this is just after the last one with distance < a_DistanceMax
+ toReturn.m_End = itr; // This is just after the last one with distance < a_DistanceMax
// Note : if we are not going through this, it's ok, toReturn.m_End will be end();
break;
}
diff --git a/src/MobProximityCounter.h b/src/MobProximityCounter.h
index 79429eb60..2dabeaa21 100644
--- a/src/MobProximityCounter.h
+++ b/src/MobProximityCounter.h
@@ -27,11 +27,11 @@ protected :
cChunk& m_Chunk;
};
-public :
- typedef std::map<cEntity*,sDistanceAndChunk> tMonsterToDistance;
- typedef std::multimap<double,sMonsterAndChunk> tDistanceToMonster;
+public :
+ typedef std::map<cEntity*, sDistanceAndChunk> tMonsterToDistance;
+ typedef std::multimap<double, sMonsterAndChunk> tDistanceToMonster;
-protected :
+protected :
// this map is filled during collection phase, it will be later transformed into DistanceToMonster
tMonsterToDistance m_MonsterToDistance;
@@ -41,7 +41,7 @@ protected :
// this are the collected chunks. Used to determinate the number of elligible chunk for spawning.
std::set<cChunk*> m_EligibleForSpawnChunks;
-protected :
+protected :
// transform monsterToDistance map (that was usefull for collecting) into distanceToMonster
// that will be usefull for picking up.
void convertMaps();
@@ -55,7 +55,8 @@ public :
// return the mobs that are within the range of distance of the closest player they are
// that means that if a mob is 30 m from a player and 150 m from another one. It will be
// in the range [0..50] but not in [100..200]
- struct sIterablePair{
+ struct sIterablePair
+ {
tDistanceToMonster::const_iterator m_Begin;
tDistanceToMonster::const_iterator m_End;
int m_Count;
diff --git a/src/MobSpawner.cpp b/src/MobSpawner.cpp
index de8e01b8a..db05b70af 100644
--- a/src/MobSpawner.cpp
+++ b/src/MobSpawner.cpp
@@ -8,7 +8,7 @@
-cMobSpawner::cMobSpawner(cMonster::eFamily a_MonsterFamily,const std::set<cMonster::eType>& a_AllowedTypes) :
+cMobSpawner::cMobSpawner(cMonster::eFamily a_MonsterFamily, const std::set<cMonster::eType>& a_AllowedTypes) :
m_MonsterFamily(a_MonsterFamily),
m_NewPack(true),
m_MobType(cMonster::mtInvalidType)
@@ -91,7 +91,7 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome)
addIfAllowed(cMonster::mtCow, allowedMobs);
addIfAllowed(cMonster::mtChicken, allowedMobs);
addIfAllowed(cMonster::mtEnderman, allowedMobs);
- addIfAllowed(cMonster::mtSlime, allowedMobs); // MG TODO : much more complicated rule
+ addIfAllowed(cMonster::mtSlime, allowedMobs); // MG TODO : much more complicated rule
if (a_Biome == biForest || a_Biome == biForestHills || a_Biome == biTaiga || a_Biome == biTaigaHills)
{
@@ -141,7 +141,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
SkyLight = a_Chunk->GetTimeAlteredLight(SkyLight);
- switch(a_MobType)
+ switch (a_MobType)
{
case cMonster::mtSquid:
{
@@ -208,7 +208,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
bool HasFloor = false;
for (int x = 0; x < 2; ++x)
{
- for(int z = 0; z < 2; ++z)
+ for (int z = 0; z < 2; ++z)
{
CanSpawn = a_Chunk->UnboundedRelGetBlockType(a_RelX + x, a_RelY, a_RelZ + z, TargetBlock);
CanSpawn = CanSpawn && (TargetBlock == E_BLOCK_AIR);
@@ -241,7 +241,8 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
(m_Random.NextInt(2, a_Biome) == 0)
);
}
-
+
+ case cMonster::mtMagmaCube:
case cMonster::mtSlime:
{
return (
diff --git a/src/MobSpawner.h b/src/MobSpawner.h
index ea6636310..f3c56fe2d 100644
--- a/src/MobSpawner.h
+++ b/src/MobSpawner.h
@@ -6,7 +6,7 @@
#include "ChunkDef.h"
#include "Chunk.h"
#include "FastRandom.h"
-#include "Mobs/Monster.h" //this is a side-effect of keeping Mobfamily inside Monster class. I'd prefer to keep both (Mobfamily and Monster) inside a "Monster" namespace MG TODO : do it
+#include "Mobs/Monster.h" // This is a side-effect of keeping Mobfamily inside Monster class. I'd prefer to keep both (Mobfamily and Monster) inside a "Monster" namespace MG TODO : do it
@@ -51,7 +51,7 @@ public :
typedef const std::set<cMonster *> tSpawnedContainer;
tSpawnedContainer & getSpawned(void);
-protected :
+protected :
// return true if specified type of mob can spawn on specified block
bool CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome);
@@ -62,7 +62,7 @@ protected :
// add toAdd inside toAddIn, if toAdd is in m_AllowedTypes
void addIfAllowed(cMonster::eType toAdd, std::set<cMonster::eType> & toAddIn);
-protected :
+protected :
cMonster::eFamily m_MonsterFamily;
std::set<cMonster::eType> m_AllowedTypes;
bool m_NewPack;
diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp
index 85b122034..5f5b1853d 100644
--- a/src/Mobs/AggressiveMonster.cpp
+++ b/src/Mobs/AggressiveMonster.cpp
@@ -42,7 +42,7 @@ void cAggressiveMonster::InStateChasing(float a_Dt)
MoveToPosition(m_Target->GetPosition());
}
}
-}
+}
@@ -95,12 +95,14 @@ void cAggressiveMonster::Attack(float a_Dt)
{
m_AttackInterval += a_Dt * m_AttackRate;
- if ((m_Target != NULL) && (m_AttackInterval > 3.0))
+ if ((m_Target == NULL) || (m_AttackInterval < 3.0))
{
- // Setting this higher gives us more wiggle room for attackrate
- m_AttackInterval = 0.0;
- m_Target->TakeDamage(dtMobAttack, this, m_AttackDamage, 0);
+ return;
}
+
+ // Setting this higher gives us more wiggle room for attackrate
+ m_AttackInterval = 0.0;
+ m_Target->TakeDamage(dtMobAttack, this, m_AttackDamage, 0);
}
diff --git a/src/Mobs/Bat.h b/src/Mobs/Bat.h
index e878d0ee8..6b06aeb4f 100644
--- a/src/Mobs/Bat.h
+++ b/src/Mobs/Bat.h
@@ -15,7 +15,7 @@ class cBat :
public:
cBat(void);
- CLASS_PROTODEF(cBat);
+ CLASS_PROTODEF(cBat)
bool IsHanging(void) const {return false; }
} ;
diff --git a/src/Mobs/Blaze.h b/src/Mobs/Blaze.h
index 5970451c7..f283b1070 100644
--- a/src/Mobs/Blaze.h
+++ b/src/Mobs/Blaze.h
@@ -15,7 +15,7 @@ class cBlaze :
public:
cBlaze(void);
- CLASS_PROTODEF(cBlaze);
+ CLASS_PROTODEF(cBlaze)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void Attack(float a_Dt) override;
diff --git a/src/Mobs/CMakeLists.txt b/src/Mobs/CMakeLists.txt
index 90294631e..23bcadaa6 100644
--- a/src/Mobs/CMakeLists.txt
+++ b/src/Mobs/CMakeLists.txt
@@ -4,10 +4,76 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ AggressiveMonster.cpp
+ Bat.cpp
+ Blaze.cpp
+ CaveSpider.cpp
+ Chicken.cpp
+ Cow.cpp
+ Creeper.cpp
+ EnderDragon.cpp
+ Enderman.cpp
+ Ghast.cpp
+ Giant.cpp
+ Horse.cpp
+ IronGolem.cpp
+ MagmaCube.cpp
+ Monster.cpp
+ Mooshroom.cpp
+ PassiveAggressiveMonster.cpp
+ PassiveMonster.cpp
+ Pig.cpp
+ Sheep.cpp
+ Skeleton.cpp
+ Slime.cpp
+ SnowGolem.cpp
+ Spider.cpp
+ Squid.cpp
+ Villager.cpp
+ Witch.cpp
+ Wither.cpp
+ Wolf.cpp
+ Zombie.cpp
+ ZombiePigman.cpp)
+
+SET (HDRS
+ AggressiveMonster.h
+ Bat.h
+ Blaze.h
+ CaveSpider.h
+ Chicken.h
+ Cow.h
+ Creeper.h
+ EnderDragon.h
+ Enderman.h
+ Ghast.h
+ Giant.h
+ Horse.h
+ IncludeAllMonsters.h
+ IronGolem.h
+ MagmaCube.h
+ Monster.h
+ Mooshroom.h
+ Ocelot.h
+ PassiveAggressiveMonster.h
+ PassiveMonster.h
+ Pig.h
+ Sheep.h
+ Silverfish.h
+ Skeleton.h
+ Slime.h
+ SnowGolem.h
+ Spider.h
+ Squid.h
+ Villager.h
+ Witch.h
+ Wither.h
+ Wolf.h
+ Zombie.h
+ ZombiePigman.h)
-add_library(Mobs ${SOURCE})
+if(NOT MSVC)
+ add_library(Mobs ${SRCS} ${HDRS})
+endif()
add_subdirectory(Components)
diff --git a/src/Mobs/CaveSpider.cpp b/src/Mobs/CaveSpider.cpp
index 1157b81f9..118a6e93b 100644
--- a/src/Mobs/CaveSpider.cpp
+++ b/src/Mobs/CaveSpider.cpp
@@ -27,6 +27,21 @@ void cCaveSpider::Tick(float a_Dt, cChunk & a_Chunk)
+void cCaveSpider::Attack(float a_Dt)
+{
+ super::Attack(a_Dt);
+
+ if (m_Target->IsPawn())
+ {
+ // TODO: Easy = no poison, Medium = 7 seconds, Hard = 15 seconds
+ ((cPawn *) m_Target)->AddEntityEffect(cEntityEffect::effPoison, 7 * 20, 0);
+ }
+}
+
+
+
+
+
void cCaveSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{
int LootingLevel = 0;
diff --git a/src/Mobs/CaveSpider.h b/src/Mobs/CaveSpider.h
index be9f174f9..f9ed10e1b 100644
--- a/src/Mobs/CaveSpider.h
+++ b/src/Mobs/CaveSpider.h
@@ -14,9 +14,10 @@ class cCaveSpider :
public:
cCaveSpider(void);
- CLASS_PROTODEF(cCaveSpider);
+ CLASS_PROTODEF(cCaveSpider)
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void Attack(float a_Dt) override;
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
} ;
diff --git a/src/Mobs/Chicken.h b/src/Mobs/Chicken.h
index a4c1d6b9e..b1a50b61c 100644
--- a/src/Mobs/Chicken.h
+++ b/src/Mobs/Chicken.h
@@ -14,7 +14,7 @@ class cChicken :
public:
cChicken(void);
- CLASS_PROTODEF(cChicken);
+ CLASS_PROTODEF(cChicken)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
diff --git a/src/Mobs/Cow.h b/src/Mobs/Cow.h
index 973171ab5..8814b7e09 100644
--- a/src/Mobs/Cow.h
+++ b/src/Mobs/Cow.h
@@ -15,7 +15,7 @@ class cCow :
public:
cCow();
- CLASS_PROTODEF(cCow);
+ CLASS_PROTODEF(cCow)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
diff --git a/src/Mobs/Creeper.cpp b/src/Mobs/Creeper.cpp
index b9041bd5a..02718edf8 100644
--- a/src/Mobs/Creeper.cpp
+++ b/src/Mobs/Creeper.cpp
@@ -37,13 +37,13 @@ void cCreeper::Tick(float a_Dt, cChunk & a_Chunk)
{
if (m_bIsBlowing)
{
- m_ExplodingTimer += 1;
+ m_ExplodingTimer += 1;
}
if (m_ExplodingTimer == 30)
{
m_World->DoExplosionAt((m_bIsCharged ? 5 : 3), GetPosX(), GetPosY(), GetPosZ(), false, esMonster, this);
- Destroy(); // Just in case we aren't killed by the explosion
+ Destroy(); // Just in case we aren't killed by the explosion
}
}
}
@@ -125,7 +125,7 @@ void cCreeper::Attack(float a_Dt)
if (!m_bIsBlowing)
{
- m_World->BroadcastSoundEffect("game.tnt.primed", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
+ m_World->BroadcastSoundEffect("game.tnt.primed", GetPosX(), GetPosY(), GetPosZ(), 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
m_bIsBlowing = true;
m_World->BroadcastEntityMetadata(*this);
}
@@ -143,7 +143,7 @@ void cCreeper::OnRightClicked(cPlayer & a_Player)
{
a_Player.UseEquippedItem();
}
- m_World->BroadcastSoundEffect("game.tnt.primed", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
+ m_World->BroadcastSoundEffect("game.tnt.primed", GetPosX(), GetPosY(), GetPosZ(), 1.f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
m_bIsBlowing = true;
m_World->BroadcastEntityMetadata(*this);
m_BurnedWithFlintAndSteel = true;
diff --git a/src/Mobs/Creeper.h b/src/Mobs/Creeper.h
index fc7db6716..747daca09 100644
--- a/src/Mobs/Creeper.h
+++ b/src/Mobs/Creeper.h
@@ -15,7 +15,7 @@ class cCreeper :
public:
cCreeper(void);
- CLASS_PROTODEF(cCreeper);
+ CLASS_PROTODEF(cCreeper)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
diff --git a/src/Mobs/EnderDragon.h b/src/Mobs/EnderDragon.h
index 77177edfe..1d4cd657c 100644
--- a/src/Mobs/EnderDragon.h
+++ b/src/Mobs/EnderDragon.h
@@ -15,7 +15,7 @@ class cEnderDragon :
public:
cEnderDragon(void);
- CLASS_PROTODEF(cEnderDragon);
+ CLASS_PROTODEF(cEnderDragon)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
} ;
diff --git a/src/Mobs/Enderman.cpp b/src/Mobs/Enderman.cpp
index becc99a86..51255beb3 100644
--- a/src/Mobs/Enderman.cpp
+++ b/src/Mobs/Enderman.cpp
@@ -2,6 +2,76 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Enderman.h"
+#include "../Entities/Player.h"
+#include "../Tracer.h"
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cPlayerLookCheck
+class cPlayerLookCheck :
+ public cPlayerListCallback
+{
+public:
+ cPlayerLookCheck(Vector3d a_EndermanPos, int a_SightDistance) :
+ m_Player(NULL),
+ m_EndermanPos(a_EndermanPos),
+ m_SightDistance(a_SightDistance)
+ {
+ }
+
+ virtual bool Item(cPlayer * a_Player) override
+ {
+ // Don't check players who are in creative gamemode
+ if (a_Player->IsGameModeCreative())
+ {
+ return false;
+ }
+
+ Vector3d Direction = m_EndermanPos - a_Player->GetPosition();
+
+ // Don't check players who are more then SightDistance (64) blocks away
+ if (Direction.Length() > m_SightDistance)
+ {
+ return false;
+ }
+
+ // Don't check if the player has a pumpkin on his head
+ if (a_Player->GetEquippedHelmet().m_ItemType == E_BLOCK_PUMPKIN)
+ {
+ return false;
+ }
+
+
+ Vector3d LookVector = a_Player->GetLookVector();
+ double dot = Direction.Dot(LookVector);
+
+ // 0.09 rad ~ 5 degrees
+ // If the player's crosshair is within 5 degrees of the enderman, it counts as looking
+ if (dot <= cos(0.09))
+ {
+ return false;
+ }
+
+ cTracer LineOfSight(a_Player->GetWorld());
+ if (LineOfSight.Trace(m_EndermanPos, Direction, (int)Direction.Length()))
+ {
+ // No direct line of sight
+ return false;
+ }
+
+ m_Player = a_Player;
+ return true;
+ }
+
+ cPlayer * GetPlayer(void) const { return m_Player; }
+
+protected:
+ cPlayer * m_Player;
+ Vector3d m_EndermanPos;
+ int m_SightDistance;
+} ;
@@ -32,3 +102,82 @@ void cEnderman::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+void cEnderman::CheckEventSeePlayer()
+{
+ if (m_Target != NULL)
+ {
+ return;
+ }
+
+ cPlayerLookCheck Callback(GetPosition(), m_SightDistance);
+ if (m_World->ForEachPlayer(Callback))
+ {
+ return;
+ }
+
+ ASSERT(Callback.GetPlayer() != NULL);
+
+ if (!CheckLight())
+ {
+ // Insufficient light for enderman to become aggravated
+ // TODO: Teleport to a suitable location
+ return;
+ }
+
+ if (!Callback.GetPlayer()->IsGameModeCreative())
+ {
+ super::EventSeePlayer(Callback.GetPlayer());
+ m_EMState = CHASING;
+ m_bIsScreaming = true;
+ GetWorld()->BroadcastEntityMetadata(*this);
+ }
+}
+
+
+
+
+
+void cEnderman::CheckEventLostPlayer(void)
+{
+ super::CheckEventLostPlayer();
+ if (!CheckLight())
+ {
+ EventLosePlayer();
+ }
+}
+
+
+
+
+
+void cEnderman::EventLosePlayer()
+{
+ super::EventLosePlayer();
+ m_bIsScreaming = false;
+ GetWorld()->BroadcastEntityMetadata(*this);
+}
+
+
+
+
+
+bool cEnderman::CheckLight()
+{
+ int ChunkX, ChunkZ;
+ cChunkDef::BlockToChunk(POSX_TOINT, POSZ_TOINT, ChunkX, ChunkZ);
+
+ // Check if the chunk the enderman is in is lit
+ if (!m_World->IsChunkLighted(ChunkX, ChunkZ))
+ {
+ m_World->QueueLightChunk(ChunkX, ChunkZ);
+ return true;
+ }
+
+ // Enderman only attack if the skylight is lower or equal to 8
+ if (m_World->GetBlockSkyLight(POSX_TOINT, POSY_TOINT, POSZ_TOINT) - GetWorld()->GetSkyDarkness() > 8)
+ {
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/Mobs/Enderman.h b/src/Mobs/Enderman.h
index 32e40e70b..4583746e7 100644
--- a/src/Mobs/Enderman.h
+++ b/src/Mobs/Enderman.h
@@ -15,14 +15,20 @@ class cEnderman :
public:
cEnderman(void);
- CLASS_PROTODEF(cEnderman);
+ CLASS_PROTODEF(cEnderman)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
+ virtual void CheckEventSeePlayer(void) override;
+ virtual void CheckEventLostPlayer(void) override;
+ virtual void EventLosePlayer(void) override;
bool IsScreaming(void) const {return m_bIsScreaming; }
BLOCKTYPE GetCarriedBlock(void) const {return CarriedBlock; }
NIBBLETYPE GetCarriedMeta(void) const {return CarriedMeta; }
+ /** Returns if the current sky light level is sufficient for the enderman to become aggravated */
+ bool CheckLight(void);
+
private:
bool m_bIsScreaming;
diff --git a/src/Mobs/Ghast.h b/src/Mobs/Ghast.h
index 43e8bedb6..1d4e6b94a 100644
--- a/src/Mobs/Ghast.h
+++ b/src/Mobs/Ghast.h
@@ -15,7 +15,7 @@ class cGhast :
public:
cGhast(void);
- CLASS_PROTODEF(cGhast);
+ CLASS_PROTODEF(cGhast)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void Attack(float a_Dt) override;
diff --git a/src/Mobs/Giant.h b/src/Mobs/Giant.h
index 356dd4352..7c04c9b4f 100644
--- a/src/Mobs/Giant.h
+++ b/src/Mobs/Giant.h
@@ -15,7 +15,7 @@ class cGiant :
public:
cGiant(void);
- CLASS_PROTODEF(cGiant);
+ CLASS_PROTODEF(cGiant)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
} ;
diff --git a/src/Mobs/Horse.cpp b/src/Mobs/Horse.cpp
index 9d130301f..67a09d4ab 100644
--- a/src/Mobs/Horse.cpp
+++ b/src/Mobs/Horse.cpp
@@ -63,7 +63,7 @@ void cHorse::Tick(float a_Dt, cChunk & a_Chunk)
m_Attachee->Detach();
m_bIsRearing = true;
}
- }
+ }
else
{
m_bIsTame = true;
diff --git a/src/Mobs/Horse.h b/src/Mobs/Horse.h
index be0c23f9b..47189b3b0 100644
--- a/src/Mobs/Horse.h
+++ b/src/Mobs/Horse.h
@@ -15,7 +15,7 @@ class cHorse :
public:
cHorse(int Type, int Color, int Style, int TameTimes);
- CLASS_PROTODEF(cHorse);
+ CLASS_PROTODEF(cHorse)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
diff --git a/src/Mobs/IronGolem.h b/src/Mobs/IronGolem.h
index 41c60438c..c5341ed76 100644
--- a/src/Mobs/IronGolem.h
+++ b/src/Mobs/IronGolem.h
@@ -15,11 +15,11 @@ class cIronGolem :
public:
cIronGolem(void);
- CLASS_PROTODEF(cIronGolem);
+ CLASS_PROTODEF(cIronGolem)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
- // Iron golems do not drown
+ // Iron golems do not drown nor float
virtual void HandleAir(void) override {}
virtual void SetSwimState(cChunk & a_Chunk) override {}
} ;
diff --git a/src/Mobs/MagmaCube.h b/src/Mobs/MagmaCube.h
index 43065cae5..bfe63fa2e 100644
--- a/src/Mobs/MagmaCube.h
+++ b/src/Mobs/MagmaCube.h
@@ -15,7 +15,7 @@ public:
/// Creates a MagmaCube of the specified size; size is 1 .. 3, with 1 being the smallest
cMagmaCube(int a_Size);
- CLASS_PROTODEF(cMagmaCube);
+ CLASS_PROTODEF(cMagmaCube)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
int GetSize(void) const { return m_Size; }
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index aaef7580d..fe8a7346f 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -62,7 +62,7 @@ static const struct
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cMonster:
cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height)
@@ -115,12 +115,10 @@ void cMonster::TickPathFinding()
const int PosY = POSY_TOINT;
const int PosZ = POSZ_TOINT;
- m_FinalDestination.y = (double)FindFirstNonAirBlockPosition(m_FinalDestination.x, m_FinalDestination.z);
-
std::vector<Vector3d> m_PotentialCoordinates;
m_TraversedCoordinates.push_back(Vector3i(PosX, PosY, PosZ));
- static const struct // Define which directions to try to move to
+ static const struct // Define which directions to try to move to
{
int x, z;
} gCrossCoords[] =
@@ -128,7 +126,7 @@ void cMonster::TickPathFinding()
{ 1, 0},
{-1, 0},
{ 0, 1},
- { 0,-1},
+ { 0, -1},
} ;
if ((PosY - 1 < 0) || (PosY + 2 > cChunkDef::Height) /* PosY + 1 will never be true if PosY + 2 is not */)
@@ -201,19 +199,6 @@ void cMonster::TickPathFinding()
-void cMonster::MoveToPosition(const Vector3f & a_Position)
-{
- FinishPathFinding();
-
- m_FinalDestination = a_Position;
- m_bMovingToDestination = true;
- TickPathFinding();
-}
-
-
-
-
-
void cMonster::MoveToPosition(const Vector3d & a_Position)
{
FinishPathFinding();
@@ -227,15 +212,7 @@ void cMonster::MoveToPosition(const Vector3d & a_Position)
bool cMonster::IsCoordinateInTraversedList(Vector3i a_Coords)
{
- for (std::vector<Vector3i>::const_iterator itr = m_TraversedCoordinates.begin(); itr != m_TraversedCoordinates.end(); ++itr)
- {
- if (itr->Equals(a_Coords))
- {
- return true;
- }
- }
-
- return false;
+ return (std::find(m_TraversedCoordinates.begin(), m_TraversedCoordinates.end(), a_Coords) != m_TraversedCoordinates.end());
}
@@ -296,49 +273,57 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
{
if (m_bOnGround)
{
- m_Destination.y = FindFirstNonAirBlockPosition(m_Destination.x, m_Destination.z);
-
if (DoesPosYRequireJump((int)floor(m_Destination.y)))
{
m_bOnGround = false;
- AddSpeedY(5.2); // Jump!!
+
+ // TODO: Change to AddSpeedY once collision detection is fixed - currently, mobs will go into blocks attempting to jump without a teleport
+ AddPosY(1.2); // Jump!!
}
}
Vector3f Distance = m_Destination - GetPosition();
- if(!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move
+ if (!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move
{
Distance.y = 0;
Distance.Normalize();
if (m_bOnGround)
{
- Distance *= 2.5;
+ Distance *= 2.5f;
+ }
+ else if (IsSwimming())
+ {
+ Distance *= 1.3f;
}
else
{
// Don't let the mob move too much if he's falling.
- Distance *= 0.25;
+ Distance *= 0.25f;
}
AddSpeedX(Distance.x);
AddSpeedZ(Distance.z);
+ // It's too buggy!
+ /*
if (m_EMState == ESCAPING)
- { //Runs Faster when escaping :D otherwise they just walk away
+ {
+ // Runs Faster when escaping :D otherwise they just walk away
SetSpeedX (GetSpeedX() * 2.f);
SetSpeedZ (GetSpeedZ() * 2.f);
}
+ */
}
else
{
- if (ReachedFinalDestination()) // If we have reached the ultimate, final destination, stop pathfinding and attack if appropriate
+ if (ReachedFinalDestination()) // If we have reached the ultimate, final destination, stop pathfinding and attack if appropriate
{
FinishPathFinding();
}
else
{
- TickPathFinding(); // We have reached the next point in our path, calculate another point
+ TickPathFinding(); // We have reached the next point in our path, calculate another point
}
}
}
@@ -353,13 +338,13 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk)
// If enemy passive we ignore checks for player visibility
InStateIdle(a_Dt);
break;
- }
+ }
case CHASING:
{
// If we do not see a player anymore skip chasing action
InStateChasing(a_Dt);
break;
- }
+ }
case ESCAPING:
{
InStateEscaping(a_Dt);
@@ -435,14 +420,11 @@ void cMonster::HandleFalling()
+
int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ)
{
int PosY = POSY_TOINT;
-
- if (PosY < 0)
- PosY = 0;
- else if (PosY > cChunkDef::Height)
- PosY = cChunkDef::Height;
+ PosY = Clamp(PosY, 0, cChunkDef::Height);
if (!cBlockInfo::IsSolid(m_World->GetBlock((int)floor(a_PosX), PosY, (int)floor(a_PosZ))))
{
@@ -478,7 +460,7 @@ bool cMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
if (!m_SoundHurt.empty() && (m_Health > 0))
{
- m_World->BroadcastSoundEffect(m_SoundHurt, (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 1.0f, 0.8f);
+ m_World->BroadcastSoundEffect(m_SoundHurt, GetPosX(), GetPosY(), GetPosZ(), 1.0f, 0.8f);
}
if (a_TDI.Attacker != NULL)
@@ -492,12 +474,12 @@ bool cMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
-void cMonster::KilledBy(cEntity * a_Killer)
+void cMonster::KilledBy(TakeDamageInfo & a_TDI)
{
- super::KilledBy(a_Killer);
+ super::KilledBy(a_TDI);
if (m_SoundHurt != "")
{
- m_World->BroadcastSoundEffect(m_SoundDeath, (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 1.0f, 0.8f);
+ m_World->BroadcastSoundEffect(m_SoundDeath, GetPosX(), GetPosY(), GetPosZ(), 1.0f, 0.8f);
}
int Reward;
switch (m_MobType)
@@ -558,7 +540,7 @@ void cMonster::KilledBy(cEntity * a_Killer)
break;
}
}
- if ((a_Killer != NULL) && (!IsBaby()))
+ if ((a_TDI.Attacker != NULL) && (!IsBaby()))
{
m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), Reward);
}
@@ -569,8 +551,8 @@ void cMonster::KilledBy(cEntity * a_Killer)
-//Checks to see if EventSeePlayer should be fired
-//monster sez: Do I see the player
+// Checks to see if EventSeePlayer should be fired
+// monster sez: Do I see the player
void cMonster::CheckEventSeePlayer(void)
{
// TODO: Rewrite this to use cWorld's DoWithPlayers()
@@ -587,7 +569,7 @@ void cMonster::CheckEventSeePlayer(void)
void cMonster::CheckEventLostPlayer(void)
-{
+{
if (m_Target != NULL)
{
if ((m_Target->GetPosition() - GetPosition()).Length() > m_SightDistance)
@@ -630,7 +612,7 @@ void cMonster::InStateIdle(float a_Dt)
{
if (m_bMovingToDestination)
{
- return; // Still getting there
+ return; // Still getting there
}
m_IdleInterval += a_Dt;
@@ -639,7 +621,7 @@ void cMonster::InStateIdle(float a_Dt)
{
// At this interval the results are predictable
int rem = m_World->GetTickRandomNumber(6) + 1;
- m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds
+ m_IdleInterval -= 1; // So nothing gets dropped when the server hangs for a few seconds
Vector3d Dist;
Dist.x = (double)m_World->GetTickRandomNumber(10) - 5;
@@ -706,6 +688,15 @@ void cMonster::GetMonsterConfig(const AString & a_Name)
+bool cMonster::IsUndead(void)
+{
+ return false;
+}
+
+
+
+
+
AString cMonster::MobTypeToString(cMonster::eType a_MobType)
{
// Mob types aren't sorted, so we need to search linearly:
@@ -727,8 +718,7 @@ AString cMonster::MobTypeToString(cMonster::eType a_MobType)
cMonster::eType cMonster::StringToMobType(const AString & a_Name)
{
- AString lcName(a_Name);
- StrToLower(lcName);
+ AString lcName = StrToLower(a_Name);
// Binary-search for the lowercase name:
int lo = 0, hi = ARRAYCOUNT(g_MobTypeNames) - 1;
@@ -847,13 +837,13 @@ cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType)
}
case mtSlime:
{
- toReturn = new cSlime(Random.NextInt(2) + 1);
+ toReturn = new cSlime(1 << Random.NextInt(3)); // Size 1, 2 or 4
break;
}
case mtSkeleton:
{
// TODO: Actual detection of spawning in Nether
- toReturn = new cSkeleton(Random.NextInt(1) == 0 ? false : true);
+ toReturn = new cSkeleton((Random.NextInt(1) == 0) ? false : true);
break;
}
case mtVillager:
@@ -900,7 +890,7 @@ cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType)
case mtMooshroom: toReturn = new cMooshroom(); break;
case mtOcelot: toReturn = new cOcelot(); break;
case mtPig: toReturn = new cPig(); break;
- case mtSheep: toReturn = new cSheep (Random.NextInt(15)); break; // Colour parameter
+ case mtSheep: toReturn = new cSheep(); break;
case mtSilverfish: toReturn = new cSilverfish(); break;
case mtSnowGolem: toReturn = new cSnowGolem(); break;
case mtSpider: toReturn = new cSpider(); break;
@@ -908,7 +898,7 @@ cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType)
case mtWitch: toReturn = new cWitch(); break;
case mtWither: toReturn = new cWither(); break;
case mtWolf: toReturn = new cWolf(); break;
- case mtZombie: toReturn = new cZombie(false); break; // TODO: Infected zombie parameter
+ case mtZombie: toReturn = new cZombie(false); break; // TODO: Infected zombie parameter
case mtZombiePigman: toReturn = new cZombiePigman(); break;
default:
{
@@ -1034,7 +1024,7 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk)
(a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand
(GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime
!IsOnFire() && // Not already burning
- (GetWorld()->GetWeather() != eWeather_Rain) // Not raining
+ GetWorld()->IsWeatherWetAt(POSX_TOINT, POSZ_TOINT) // Not raining
)
{
// Burn for 100 ticks, then decide again
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index 7d7e90eb2..cdbd26c09 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -61,28 +61,28 @@ public:
enum eFamily
{
- mfHostile = 0, // Spider, Zombies ...
- mfPassive = 1, // Cows, Pigs
- mfAmbient = 2, // Bats
- mfWater = 3, // Squid
+ mfHostile = 0, // Spider, Zombies ...
+ mfPassive = 1, // Cows, Pigs
+ mfAmbient = 2, // Bats
+ mfWater = 3, // Squid
mfNoSpawn,
- mfUnhandled, // Nothing. Be sure this is the last and the others are in order
+ mfUnhandled, // Nothing. Be sure this is the last and the others are in order
} ;
// tolua_end
enum MState{ATTACKING, IDLE, CHASING, ESCAPING} m_EMState;
- enum MPersonality{PASSIVE,AGGRESSIVE,COWARDLY} m_EMPersonality;
+ enum MPersonality{PASSIVE, AGGRESSIVE, COWARDLY} m_EMPersonality;
/** Creates the mob object.
- * If a_ConfigName is not empty, the configuration is loaded using GetMonsterConfig()
- * a_MobType is the type of the mob (also used in the protocol ( http://wiki.vg/Entities#Mobs , 2012_12_22))
- * a_SoundHurt and a_SoundDeath are assigned into m_SoundHurt and m_SoundDeath, respectively
+ If a_ConfigName is not empty, the configuration is loaded using GetMonsterConfig()
+ a_MobType is the type of the mob (also used in the protocol ( http://wiki.vg/Entities#Mobs 2012_12_22))
+ a_SoundHurt and a_SoundDeath are assigned into m_SoundHurt and m_SoundDeath, respectively
*/
cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height);
- CLASS_PROTODEF(cMonster);
+ CLASS_PROTODEF(cMonster)
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
@@ -90,10 +90,9 @@ public:
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
- virtual void KilledBy(cEntity * a_Killer) override;
+ virtual void KilledBy(TakeDamageInfo & a_TDI) override;
- virtual void MoveToPosition(const Vector3f & a_Position);
- virtual void MoveToPosition(const Vector3d & a_Position); // tolua_export
+ virtual void MoveToPosition(const Vector3d & a_Position); // tolua_export
virtual bool ReachedDestination(void);
// tolua_begin
@@ -107,6 +106,9 @@ public:
/// Reads the monster configuration for the specified monster name and assigns it to this object.
void GetMonsterConfig(const AString & a_Name);
+ /** Returns whether this mob is undead (skeleton, zombie, etc.) */
+ virtual bool IsUndead(void);
+
virtual void EventLosePlayer(void);
virtual void CheckEventLostPlayer(void);
@@ -178,6 +180,7 @@ protected:
/** Stores if mobile is currently moving towards the ultimate, final destination */
bool m_bMovingToDestination;
+
/** Finds the first non-air block position (not the highest, as cWorld::GetHeight does)
If current Y is nonsolid, goes down to try to find a solid block, then returns that + 1
If current Y is solid, goes up to find first nonsolid block, and returns that */
@@ -229,7 +232,7 @@ protected:
AString m_SoundHurt;
AString m_SoundDeath;
- float m_AttackRate;
+ float m_AttackRate;
int m_AttackDamage;
int m_AttackRange;
float m_AttackInterval;
@@ -246,13 +249,13 @@ protected:
bool m_BurnsInDaylight;
/** Adds a random number of a_Item between a_Min and a_Max to itemdrops a_Drops*/
- void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0);
+ void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0);
/** Adds a item a_Item with the chance of a_Chance (in percent) to itemdrops a_Drops*/
- void AddRandomUncommonDropItem(cItems & a_Drops, float a_Chance, short a_Item, short a_ItemHealth = 0);
+ void AddRandomUncommonDropItem(cItems & a_Drops, float a_Chance, short a_Item, short a_ItemHealth = 0);
/** Adds one rare item out of the list of rare items a_Items modified by the looting level a_LootingLevel(I-III or custom) to the itemdrop a_Drops*/
- void AddRandomRareDropItem(cItems & a_Drops, cItems & a_Items, short a_LootingLevel);
+ void AddRandomRareDropItem(cItems & a_Drops, cItems & a_Items, short a_LootingLevel);
/** Adds armor that is equipped with the chance saved in m_DropChance[...] (this will be greter than 1 if piccked up or 0.085 + (0.01 per LootingLevel) if born with) to the drop*/
void AddRandomArmorDropItem(cItems & a_Drops, short a_LootingLevel);
@@ -261,7 +264,7 @@ protected:
void AddRandomWeaponDropItem(cItems & a_Drops, short a_LootingLevel);
-} ; // tolua_export
+} ; // tolua_export
diff --git a/src/Mobs/Mooshroom.h b/src/Mobs/Mooshroom.h
index 16f6c8248..fb002c2bf 100644
--- a/src/Mobs/Mooshroom.h
+++ b/src/Mobs/Mooshroom.h
@@ -15,7 +15,7 @@ class cMooshroom :
public:
cMooshroom(void);
- CLASS_PROTODEF(cMooshroom);
+ CLASS_PROTODEF(cMooshroom)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
diff --git a/src/Mobs/Ocelot.h b/src/Mobs/Ocelot.h
index adb7a1f75..f2727d354 100644
--- a/src/Mobs/Ocelot.h
+++ b/src/Mobs/Ocelot.h
@@ -18,7 +18,7 @@ public:
{
}
- CLASS_PROTODEF(cOcelot);
+ CLASS_PROTODEF(cOcelot)
} ;
diff --git a/src/Mobs/Pig.h b/src/Mobs/Pig.h
index 313af2f44..534a0ca6f 100644
--- a/src/Mobs/Pig.h
+++ b/src/Mobs/Pig.h
@@ -15,7 +15,7 @@ class cPig :
public:
cPig(void);
- CLASS_PROTODEF(cPig);
+ CLASS_PROTODEF(cPig)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp
index 5a6b760af..9fb47201d 100644
--- a/src/Mobs/Sheep.cpp
+++ b/src/Mobs/Sheep.cpp
@@ -5,6 +5,7 @@
#include "../BlockID.h"
#include "../Entities/Player.h"
#include "../World.h"
+#include "FastRandom.h"
@@ -16,6 +17,16 @@ cSheep::cSheep(int a_Color) :
m_WoolColor(a_Color),
m_TimeToStopEating(-1)
{
+ // Generate random wool color.
+ if (m_WoolColor == -1)
+ {
+ m_WoolColor = GenerateNaturalRandomColor();
+ }
+
+ if ((m_WoolColor < 0) || (m_WoolColor > 15))
+ {
+ m_WoolColor = 0;
+ }
}
@@ -37,20 +48,17 @@ void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer)
void cSheep::OnRightClicked(cPlayer & a_Player)
{
const cItem & EquippedItem = a_Player.GetEquippedItem();
- if ((EquippedItem.m_ItemType == E_ITEM_SHEARS) && (!m_IsSheared))
+ if ((EquippedItem.m_ItemType == E_ITEM_SHEARS) && !IsSheared() && !IsBaby())
{
m_IsSheared = true;
m_World->BroadcastEntityMetadata(*this);
-
- if (!a_Player.IsGameModeCreative())
- {
- a_Player.UseEquippedItem();
- }
+ a_Player.UseEquippedItem();
cItems Drops;
int NumDrops = m_World->GetTickRandomNumber(2) + 1;
Drops.push_back(cItem(E_BLOCK_WOOL, NumDrops, m_WoolColor));
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10);
+ m_World->BroadcastSoundEffect("mob.sheep.shear", GetPosX(), GetPosY(), GetPosZ(), 1.0f, 1.0f);
}
else if ((EquippedItem.m_ItemType == E_ITEM_DYE) && (m_WoolColor != 15 - EquippedItem.m_ItemDamage))
{
@@ -81,12 +89,12 @@ void cSheep::Tick(float a_Dt, cChunk & a_Chunk)
if (m_TimeToStopEating > 0)
{
- m_bMovingToDestination = false; // The sheep should not move when he's eating
+ m_bMovingToDestination = false; // The sheep should not move when he's eating
m_TimeToStopEating--;
if (m_TimeToStopEating == 0)
{
- if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS) // Make sure grass hasn't been destroyed in the meantime
+ if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS) // Make sure grass hasn't been destroyed in the meantime
{
// The sheep ate the grass so we change it to dirt
m_World->SetBlock(PosX, PosY, PosZ, E_BLOCK_DIRT, 0);
@@ -109,3 +117,38 @@ void cSheep::Tick(float a_Dt, cChunk & a_Chunk)
}
}
+
+
+
+
+NIBBLETYPE cSheep::GenerateNaturalRandomColor(void)
+{
+ cFastRandom Random;
+ int Chance = Random.NextInt(101);
+
+ if (Chance <= 81)
+ {
+ return E_META_WOOL_WHITE;
+ }
+ else if (Chance <= 86)
+ {
+ return E_META_WOOL_BLACK;
+ }
+ else if (Chance <= 91)
+ {
+ return E_META_WOOL_GRAY;
+ }
+ else if (Chance <= 96)
+ {
+ return E_META_WOOL_LIGHTGRAY;
+ }
+ else if (Chance <= 99)
+ {
+ return E_META_WOOL_BROWN;
+ }
+ else
+ {
+ return E_META_WOOL_PINK;
+ }
+}
+
diff --git a/src/Mobs/Sheep.h b/src/Mobs/Sheep.h
index 402e8e61c..28e1c7254 100644
--- a/src/Mobs/Sheep.h
+++ b/src/Mobs/Sheep.h
@@ -13,21 +13,32 @@ class cSheep :
typedef cPassiveMonster super;
public:
- cSheep(int a_Color);
-
- CLASS_PROTODEF(cSheep);
-
+
+ /** The number is the color of the sheep.
+ Use E_META_WOOL_* constants for the wool color.
+ If you type -1, the server will generate a random color
+ with the GenerateNaturalRandomColor() function. */
+ cSheep(int a_Color = -1);
+
+ CLASS_PROTODEF(cSheep)
+
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
virtual const cItem GetFollowedItem(void) const override { return cItem(E_ITEM_WHEAT); }
+ /** Generates a random color for the sheep like the vanilla server.
+ The percent's where used are from the wiki: http://minecraft.gamepedia.com/Sheep#Breeding */
+ static NIBBLETYPE GenerateNaturalRandomColor(void);
+
bool IsSheared(void) const { return m_IsSheared; }
+ void SetSheared(bool a_IsSheared) { m_IsSheared = a_IsSheared; }
+
int GetFurColor(void) const { return m_WoolColor; }
+ void SetFurColor(int a_WoolColor) { m_WoolColor = a_WoolColor; }
private:
-
bool m_IsSheared;
int m_WoolColor;
int m_TimeToStopEating;
diff --git a/src/Mobs/Silverfish.h b/src/Mobs/Silverfish.h
index a6e11c49d..2df333dbc 100644
--- a/src/Mobs/Silverfish.h
+++ b/src/Mobs/Silverfish.h
@@ -18,7 +18,7 @@ public:
{
}
- CLASS_PROTODEF(cSilverfish);
+ CLASS_PROTODEF(cSilverfish)
} ;
diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp
index 0641a3d57..cd707f4bb 100644
--- a/src/Mobs/Skeleton.cpp
+++ b/src/Mobs/Skeleton.cpp
@@ -4,6 +4,7 @@
#include "Skeleton.h"
#include "../World.h"
#include "../Entities/ArrowEntity.h"
+#include "ClientHandle.h"
@@ -47,7 +48,7 @@ void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer)
-void cSkeleton::MoveToPosition(const Vector3f & a_Position)
+void cSkeleton::MoveToPosition(const Vector3d & a_Position)
{
// If the destination is sufficiently skylight challenged AND the skeleton isn't on fire then block the movement
if (
@@ -90,3 +91,17 @@ void cSkeleton::Attack(float a_Dt)
m_AttackInterval = 0.0;
}
}
+
+
+
+
+
+void cSkeleton::SpawnOn(cClientHandle & a_ClientHandle)
+{
+ super::SpawnOn(a_ClientHandle);
+ a_ClientHandle.SendEntityEquipment(*this, 0, cItem(E_ITEM_BOW));
+}
+
+
+
+
diff --git a/src/Mobs/Skeleton.h b/src/Mobs/Skeleton.h
index 8f31b42e1..577588b32 100644
--- a/src/Mobs/Skeleton.h
+++ b/src/Mobs/Skeleton.h
@@ -15,12 +15,16 @@ class cSkeleton :
public:
cSkeleton(bool IsWither);
- CLASS_PROTODEF(cSkeleton);
+ CLASS_PROTODEF(cSkeleton)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
- virtual void MoveToPosition(const Vector3f & a_Position) override;
+ virtual void MoveToPosition(const Vector3d & a_Position) override;
virtual void Attack(float a_Dt) override;
- bool IsWither(void) const { return m_bIsWither; };
+ virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
+
+ virtual bool IsUndead(void) override { return true; }
+
+ bool IsWither(void) const { return m_bIsWither; }
private:
diff --git a/src/Mobs/Slime.cpp b/src/Mobs/Slime.cpp
index 52a52bb39..b709ec664 100644
--- a/src/Mobs/Slime.cpp
+++ b/src/Mobs/Slime.cpp
@@ -2,16 +2,25 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Slime.h"
+#include "FastRandom.h"
+#include "World.h"
-/// Creates a slime of the specified size; size is 1 .. 3, with 1 being the smallest
cSlime::cSlime(int a_Size) :
- super("Slime", mtSlime, "mob.slime.attack", "mob.slime.attack", 0.6 * a_Size, 0.6 * a_Size),
+ super("Slime",
+ mtSlime,
+ Printf("mob.slime.%s", GetSizeName(a_Size).c_str()),
+ Printf("mob.slime.%s", GetSizeName(a_Size).c_str()),
+ 0.6 * a_Size,
+ 0.6 * a_Size
+ ),
m_Size(a_Size)
{
+ SetMaxHealth(a_Size * a_Size);
+ SetAttackDamage(a_Size);
}
@@ -25,7 +34,9 @@ void cSlime::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{
LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
}
- if (GetSize() == 1)
+
+ // Only slimes with the size 1 can drop slimeballs.
+ if (m_Size == 1)
{
AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_SLIMEBALL);
}
@@ -34,3 +45,62 @@ void cSlime::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+
+void cSlime::Attack(float a_Dt)
+{
+ if (m_Size > 1)
+ {
+ // Only slimes larger than size 1 attack a player.
+ super::Attack(a_Dt);
+ }
+}
+
+
+
+
+
+void cSlime::KilledBy(TakeDamageInfo & a_TDI)
+{
+ if (GetHealth() > 0)
+ {
+ return;
+ }
+
+ if (m_Size != 1)
+ {
+ cFastRandom Random;
+ int SpawnAmount = 2 + Random.NextInt(3);
+
+ for (int i = 0; i < SpawnAmount; ++i)
+ {
+ double AddX = (i % 2 - 0.5) * m_Size / 4.0;
+ double AddZ = (i / 2 - 0.5) * m_Size / 4.0;
+
+ cSlime * NewSlime = new cSlime(m_Size / 2);
+ NewSlime->SetPosition(GetPosX() + AddX, GetPosY() + 0.5, GetPosZ() + AddZ);
+ NewSlime->SetYaw(Random.NextFloat(1.0f) * 360.0f);
+ m_World->SpawnMobFinalize(NewSlime);
+ }
+ }
+ super::KilledBy(a_TDI);
+}
+
+
+
+
+
+const AString cSlime::GetSizeName(int a_Size) const
+{
+ if (a_Size > 1)
+ {
+ return "big";
+ }
+ else
+ {
+ return "small";
+ }
+}
+
+
+
+
diff --git a/src/Mobs/Slime.h b/src/Mobs/Slime.h
index 782c3113f..f0b800f94 100644
--- a/src/Mobs/Slime.h
+++ b/src/Mobs/Slime.h
@@ -13,17 +13,26 @@ class cSlime :
typedef cAggressiveMonster super;
public:
- /// Creates a slime of the specified size; size is 1 .. 3, with 1 being the smallest
+ /** Creates a slime of the specified size; size can be 1, 2 or 4, with 1 is the smallest and 4 is the tallest. */
cSlime(int a_Size);
- CLASS_PROTODEF(cSlime);
+ CLASS_PROTODEF(cSlime)
+ // cAggressiveMonster overrides:
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
+ virtual void Attack(float a_Dt) override;
+ virtual void KilledBy(TakeDamageInfo & a_TDI) override;
+
int GetSize(void) const { return m_Size; }
+ /** Returns the text describing the slime's size, as used by the client's resource subsystem for sounds.
+ Returns either "big" or "small". */
+ const AString GetSizeName(int a_Size) const;
+
protected:
- /// Size of the slime, 1 .. 3, with 1 being the smallest
+ /** Size of the slime, with 1 being the smallest.
+ Vanilla uses sizes 1, 2 and 4 only. */
int m_Size;
} ;
diff --git a/src/Mobs/SnowGolem.cpp b/src/Mobs/SnowGolem.cpp
index c1979a495..76334d970 100644
--- a/src/Mobs/SnowGolem.cpp
+++ b/src/Mobs/SnowGolem.cpp
@@ -30,7 +30,7 @@ void cSnowGolem::GetDrops(cItems & a_Drops, cEntity * a_Killer)
void cSnowGolem::Tick(float a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
- if (IsBiomeNoDownfall(m_World->GetBiomeAt((int) floor(GetPosX()), (int) floor(GetPosZ())) ))
+ if (IsBiomeNoDownfall(m_World->GetBiomeAt((int) floor(GetPosX()), (int) floor(GetPosZ()))))
{
TakeDamage(*this);
}
diff --git a/src/Mobs/SnowGolem.h b/src/Mobs/SnowGolem.h
index ff5e90da8..aba89e52d 100644
--- a/src/Mobs/SnowGolem.h
+++ b/src/Mobs/SnowGolem.h
@@ -15,7 +15,7 @@ class cSnowGolem :
public:
cSnowGolem(void);
- CLASS_PROTODEF(cSnowGolem);
+ CLASS_PROTODEF(cSnowGolem)
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
diff --git a/src/Mobs/Spider.h b/src/Mobs/Spider.h
index 51e65d028..813d2e266 100644
--- a/src/Mobs/Spider.h
+++ b/src/Mobs/Spider.h
@@ -15,7 +15,7 @@ class cSpider :
public:
cSpider(void);
- CLASS_PROTODEF(cSpider);
+ CLASS_PROTODEF(cSpider)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
} ;
diff --git a/src/Mobs/Squid.h b/src/Mobs/Squid.h
index a9dba8b70..b57340427 100644
--- a/src/Mobs/Squid.h
+++ b/src/Mobs/Squid.h
@@ -17,7 +17,7 @@ public:
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
- CLASS_PROTODEF(cSquid);
+ CLASS_PROTODEF(cSquid)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp
index 41283acf4..1cdac7c74 100644
--- a/src/Mobs/Villager.cpp
+++ b/src/Mobs/Villager.cpp
@@ -55,7 +55,7 @@ void cVillager::Tick(float a_Dt, cChunk & a_Chunk)
{
switch (m_Type)
{
- case vtFarmer:
+ case vtFarmer:
{
HandleFarmerPlaceCrops();
}
@@ -138,8 +138,8 @@ void cVillager::HandleFarmerPrepareFarmCrops()
m_CropsPos = Vector3i((int) GetPosX() + X - 5, (int) GetPosY() + Y - 3, (int) GetPosZ() + Z - 5);
MoveToPosition(Vector3f((float) (m_CropsPos.x + 0.5), (float) m_CropsPos.y, (float) (m_CropsPos.z + 0.5)));
return;
- } // for Y loop.
- } // Repeat the procces 5 times.
+ } // for Y loop.
+ } // Repeat the procces 5 times.
}
diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h
index abde48407..aa81f0790 100644
--- a/src/Mobs/Villager.h
+++ b/src/Mobs/Villager.h
@@ -27,7 +27,7 @@ public:
cVillager(eVillagerType VillagerType);
- CLASS_PROTODEF(cVillager);
+ CLASS_PROTODEF(cVillager)
// cEntity overrides
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
@@ -37,9 +37,8 @@ public:
/** return true if the given blocktype are: crops, potatoes or carrots.*/
bool IsBlockFarmable(BLOCKTYPE a_BlockType);
- //////////////////////////////////////////////////////////////////
// Farmer functions
- /** It searches in a 11x7x11 area for crops. If it found some it will navigate to them.*/
+ /** Searches in a 11x7x11 area for crops. If it found some it will navigate to them.*/
void HandleFarmerPrepareFarmCrops();
/** Looks if the farmer has reached it's destination, and if it's still crops and the destination is closer then 2 blocks it will harvest them.*/
@@ -49,7 +48,7 @@ public:
void HandleFarmerPlaceCrops();
// Get and set functions.
- int GetVilType(void) const { return m_Type; }
+ int GetVilType(void) const { return m_Type; }
Vector3i GetCropsPos(void) const { return m_CropsPos; }
bool DoesHaveActionActivated(void) const { return m_VillagerAction; }
diff --git a/src/Mobs/Witch.h b/src/Mobs/Witch.h
index 51c63322a..bd059f61d 100644
--- a/src/Mobs/Witch.h
+++ b/src/Mobs/Witch.h
@@ -16,7 +16,7 @@ class cWitch :
public:
cWitch();
- CLASS_PROTODEF(cWitch);
+ CLASS_PROTODEF(cWitch)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
diff --git a/src/Mobs/Wither.cpp b/src/Mobs/Wither.cpp
index da4cc7765..578b47995 100644
--- a/src/Mobs/Wither.cpp
+++ b/src/Mobs/Wither.cpp
@@ -103,9 +103,9 @@ void cWither::GetDrops(cItems & a_Drops, cEntity * a_Killer)
-void cWither::KilledBy(cEntity * a_Killer)
+void cWither::KilledBy(TakeDamageInfo & a_TDI)
{
- super::KilledBy(a_Killer);
+ super::KilledBy(a_TDI);
class cPlayerCallback : public cPlayerListCallback
{
diff --git a/src/Mobs/Wither.h b/src/Mobs/Wither.h
index 03a320788..2403823ed 100644
--- a/src/Mobs/Wither.h
+++ b/src/Mobs/Wither.h
@@ -15,7 +15,7 @@ class cWither :
public:
cWither(void);
- CLASS_PROTODEF(cWither);
+ CLASS_PROTODEF(cWither)
unsigned int GetWitherInvulnerableTicks(void) const { return m_WitherInvulnerableTicks; }
@@ -29,7 +29,9 @@ public:
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
- virtual void KilledBy(cEntity * a_Killer) override;
+ virtual void KilledBy(TakeDamageInfo & a_TDI) override;
+
+ virtual bool IsUndead(void) override { return true; }
private:
diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp
index e6268abc7..4fe1ff1d6 100644
--- a/src/Mobs/Wolf.cpp
+++ b/src/Mobs/Wolf.cpp
@@ -36,7 +36,7 @@ bool cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
{
m_IsAngry = true;
}
- m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face
+ m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face
return true;
}
@@ -68,6 +68,7 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
{
if (!IsTame() && !IsAngry())
{
+ // If the player is holding a bone, try to tame the wolf:
if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_BONE)
{
if (!a_Player.IsGameModeCreative())
@@ -77,14 +78,16 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
if (m_World->GetTickRandomNumber(7) == 0)
{
+ // Taming succeeded
SetMaxHealth(20);
SetIsTame(true);
- SetOwner(a_Player.GetName());
+ SetOwner(a_Player.GetName(), a_Player.GetUUID());
m_World->BroadcastEntityStatus(*this, esWolfTamed);
m_World->BroadcastParticleEffect("heart", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5);
}
else
{
+ // Taming failed
m_World->BroadcastEntityStatus(*this, esWolfTaming);
m_World->BroadcastParticleEffect("smoke", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5);
}
@@ -92,6 +95,7 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
}
else if (IsTame())
{
+ // Feed the wolf, restoring its health, or dye its collar:
switch (a_Player.GetEquippedItem().m_ItemType)
{
case E_ITEM_RAW_BEEF:
@@ -114,7 +118,7 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
}
case E_ITEM_DYE:
{
- if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog?
+ if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog?
{
SetCollarColor(15 - a_Player.GetEquippedItem().m_ItemDamage);
if (!a_Player.IsGameModeCreative())
@@ -126,7 +130,7 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
}
default:
{
- if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog?
+ if (a_Player.GetName() == m_OwnerName) // Is the player the owner of the dog?
{
SetIsSitting(!IsSitting());
}
@@ -172,7 +176,7 @@ void cWolf::Tick(float a_Dt, cChunk & a_Chunk)
m_World->BroadcastEntityMetadata(*this);
}
- m_FinalDestination = a_Closest_Player->GetPosition(); // So that we will look at a player holding food
+ m_FinalDestination = a_Closest_Player->GetPosition(); // So that we will look at a player holding food
// Don't move to the player if the wolf is sitting.
if (!IsSitting())
diff --git a/src/Mobs/Wolf.h b/src/Mobs/Wolf.h
index fb8a7c995..7500854f8 100644
--- a/src/Mobs/Wolf.h
+++ b/src/Mobs/Wolf.h
@@ -16,7 +16,7 @@ class cWolf :
public:
cWolf(void);
- CLASS_PROTODEF(cWolf);
+ CLASS_PROTODEF(cWolf)
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
@@ -29,7 +29,8 @@ public:
bool IsTame (void) const { return m_IsTame; }
bool IsBegging (void) const { return m_IsBegging; }
bool IsAngry (void) const { return m_IsAngry; }
- AString GetOwner (void) const { return m_OwnerName; }
+ AString GetOwnerName (void) const { return m_OwnerName; }
+ AString GetOwnerUUID (void) const { return m_OwnerUUID; }
int GetCollarColor(void) const { return m_CollarColor; }
// Set functions
@@ -37,8 +38,12 @@ public:
void SetIsTame (bool a_IsTame) { m_IsTame = a_IsTame; }
void SetIsBegging (bool a_IsBegging) { m_IsBegging = a_IsBegging; }
void SetIsAngry (bool a_IsAngry) { m_IsAngry = a_IsAngry; }
- void SetOwner (const AString & a_NewOwner) { m_OwnerName = a_NewOwner; }
void SetCollarColor(int a_CollarColor) { m_CollarColor = a_CollarColor; }
+ void SetOwner (const AString & a_NewOwnerName, const AString & a_NewOwnerUUID)
+ {
+ m_OwnerName = a_NewOwnerName;
+ m_OwnerUUID = a_NewOwnerUUID;
+ }
protected:
@@ -47,6 +52,7 @@ protected:
bool m_IsBegging;
bool m_IsAngry;
AString m_OwnerName;
+ AString m_OwnerUUID;
int m_CollarColor;
} ;
diff --git a/src/Mobs/Zombie.cpp b/src/Mobs/Zombie.cpp
index 725790ed9..30225c32d 100644
--- a/src/Mobs/Zombie.cpp
+++ b/src/Mobs/Zombie.cpp
@@ -42,7 +42,7 @@ void cZombie::GetDrops(cItems & a_Drops, cEntity * a_Killer)
-void cZombie::MoveToPosition(const Vector3f & a_Position)
+void cZombie::MoveToPosition(const Vector3d & a_Position)
{
// If the destination is sufficiently skylight challenged AND the skeleton isn't on fire then block the movement
if (
diff --git a/src/Mobs/Zombie.h b/src/Mobs/Zombie.h
index 1ba368f9c..118b6e6e7 100644
--- a/src/Mobs/Zombie.h
+++ b/src/Mobs/Zombie.h
@@ -14,13 +14,15 @@ class cZombie :
public:
cZombie(bool a_IsVillagerZombie);
- CLASS_PROTODEF(cZombie);
+ CLASS_PROTODEF(cZombie)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
- virtual void MoveToPosition(const Vector3f & a_Position) override;
+ virtual void MoveToPosition(const Vector3d & a_Position) override;
- bool IsVillagerZombie(void) const {return m_IsVillagerZombie; }
- bool IsConverting (void) const {return m_IsConverting; }
+ virtual bool IsUndead(void) override { return true; }
+
+ bool IsVillagerZombie(void) const { return m_IsVillagerZombie; }
+ bool IsConverting (void) const { return m_IsConverting; }
private:
diff --git a/src/Mobs/ZombiePigman.cpp b/src/Mobs/ZombiePigman.cpp
index c9d94face..05350f877 100644
--- a/src/Mobs/ZombiePigman.cpp
+++ b/src/Mobs/ZombiePigman.cpp
@@ -37,11 +37,11 @@ void cZombiePigman::GetDrops(cItems & a_Drops, cEntity * a_Killer)
-void cZombiePigman::KilledBy(cEntity * a_Killer)
+void cZombiePigman::KilledBy(TakeDamageInfo & a_TDI)
{
- super::KilledBy(a_Killer);
+ super::KilledBy(a_TDI);
- if ((a_Killer != NULL) && (a_Killer->IsPlayer()))
+ if ((a_TDI.Attacker != NULL) && (a_TDI.Attacker->IsPlayer()))
{
// TODO: Anger all nearby zombie pigmen
// TODO: In vanilla, if one player angers ZPs, do they attack any nearby player, or only that one attacker?
diff --git a/src/Mobs/ZombiePigman.h b/src/Mobs/ZombiePigman.h
index ab3cebf6d..bae0115eb 100644
--- a/src/Mobs/ZombiePigman.h
+++ b/src/Mobs/ZombiePigman.h
@@ -14,10 +14,12 @@ class cZombiePigman :
public:
cZombiePigman(void);
- CLASS_PROTODEF(cZombiePigman);
+ CLASS_PROTODEF(cZombiePigman)
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
- virtual void KilledBy(cEntity * a_Killer) override;
+ virtual void KilledBy(TakeDamageInfo & a_TDI) override;
+
+ virtual bool IsUndead(void) override { return true; }
} ;
diff --git a/src/MonsterConfig.cpp b/src/MonsterConfig.cpp
index f5e746ce8..f5e078213 100644
--- a/src/MonsterConfig.cpp
+++ b/src/MonsterConfig.cpp
@@ -35,7 +35,7 @@ struct cMonsterConfig::sMonsterConfigState
cMonsterConfig::cMonsterConfig(void)
- : m_pState( new sMonsterConfigState )
+ : m_pState( new sMonsterConfigState)
{
Initialize();
}
diff --git a/src/Noise.cpp b/src/Noise.cpp
index fbd2a1800..507d05ea5 100644
--- a/src/Noise.cpp
+++ b/src/Noise.cpp
@@ -9,7 +9,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Globals:
void Debug3DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int a_SizeZ, const AString & a_FileNameBase)
@@ -90,7 +90,7 @@ void Debug2DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, cons
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCubicCell2D:
class cCubicCell2D
@@ -239,7 +239,7 @@ void cCubicCell2D::Move(int a_NewFloorX, int a_NewFloorY)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCubicCell3D:
class cCubicCell3D
@@ -422,7 +422,7 @@ void cCubicCell3D::Move(int a_NewFloorX, int a_NewFloorY, int a_NewFloorZ)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cNoise:
cNoise::cNoise(int a_Seed) :
@@ -487,8 +487,8 @@ NOISE_DATATYPE cNoise::SmoothNoise1D(int a_X) const
NOISE_DATATYPE cNoise::CubicNoise2D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y) const
{
- const int BaseX = FAST_FLOOR(a_X);
- const int BaseY = FAST_FLOOR(a_Y);
+ const int BaseX = FAST_FLOOR(a_X);
+ const int BaseY = FAST_FLOOR(a_Y);
const NOISE_DATATYPE points[4][4] =
{
@@ -515,74 +515,78 @@ NOISE_DATATYPE cNoise::CubicNoise2D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y) cons
NOISE_DATATYPE cNoise::CubicNoise3D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const
{
- const int BaseX = FAST_FLOOR(a_X);
- const int BaseY = FAST_FLOOR(a_Y);
- const int BaseZ = FAST_FLOOR(a_Z);
+ const int BaseX = FAST_FLOOR(a_X);
+ const int BaseY = FAST_FLOOR(a_Y);
+ const int BaseZ = FAST_FLOOR(a_Z);
- const NOISE_DATATYPE points1[4][4] = {
+ const NOISE_DATATYPE points1[4][4] =
+ {
{ IntNoise3D(BaseX - 1, BaseY - 1, BaseZ - 1), IntNoise3D(BaseX, BaseY - 1, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY - 1, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY - 1, BaseZ - 1), },
{ IntNoise3D(BaseX - 1, BaseY, BaseZ - 1), IntNoise3D(BaseX, BaseY, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY, BaseZ - 1), },
{ IntNoise3D(BaseX - 1, BaseY + 1, BaseZ - 1), IntNoise3D(BaseX, BaseY + 1, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY + 1, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY + 1, BaseZ - 1), },
{ IntNoise3D(BaseX - 1, BaseY + 2, BaseZ - 1), IntNoise3D(BaseX, BaseY + 2, BaseZ - 1), IntNoise3D(BaseX + 1, BaseY + 2, BaseZ - 1), IntNoise3D(BaseX + 2, BaseY + 2, BaseZ - 1), },
};
- const NOISE_DATATYPE FracX = (a_X) - BaseX;
- const NOISE_DATATYPE x1interp1 = CubicInterpolate( points1[0][0], points1[0][1], points1[0][2], points1[0][3], FracX );
- const NOISE_DATATYPE x1interp2 = CubicInterpolate( points1[1][0], points1[1][1], points1[1][2], points1[1][3], FracX );
- const NOISE_DATATYPE x1interp3 = CubicInterpolate( points1[2][0], points1[2][1], points1[2][2], points1[2][3], FracX );
- const NOISE_DATATYPE x1interp4 = CubicInterpolate( points1[3][0], points1[3][1], points1[3][2], points1[3][3], FracX );
-
- const NOISE_DATATYPE points2[4][4] = {
- { IntNoise3D( BaseX-1, BaseY-1, BaseZ ), IntNoise3D( BaseX, BaseY-1, BaseZ ), IntNoise3D( BaseX+1, BaseY-1, BaseZ ), IntNoise3D( BaseX+2, BaseY-1, BaseZ ), },
- { IntNoise3D( BaseX-1, BaseY, BaseZ ), IntNoise3D( BaseX, BaseY, BaseZ ), IntNoise3D( BaseX+1, BaseY, BaseZ ), IntNoise3D( BaseX+2, BaseY, BaseZ ), },
- { IntNoise3D( BaseX-1, BaseY+1, BaseZ ), IntNoise3D( BaseX, BaseY+1, BaseZ ), IntNoise3D( BaseX+1, BaseY+1, BaseZ ), IntNoise3D( BaseX+2, BaseY+1, BaseZ ), },
- { IntNoise3D( BaseX-1, BaseY+2, BaseZ ), IntNoise3D( BaseX, BaseY+2, BaseZ ), IntNoise3D( BaseX+1, BaseY+2, BaseZ ), IntNoise3D( BaseX+2, BaseY+2, BaseZ ), },
+ const NOISE_DATATYPE FracX = (a_X) - BaseX;
+ const NOISE_DATATYPE x1interp1 = CubicInterpolate( points1[0][0], points1[0][1], points1[0][2], points1[0][3], FracX);
+ const NOISE_DATATYPE x1interp2 = CubicInterpolate( points1[1][0], points1[1][1], points1[1][2], points1[1][3], FracX);
+ const NOISE_DATATYPE x1interp3 = CubicInterpolate( points1[2][0], points1[2][1], points1[2][2], points1[2][3], FracX);
+ const NOISE_DATATYPE x1interp4 = CubicInterpolate( points1[3][0], points1[3][1], points1[3][2], points1[3][3], FracX);
+
+ const NOISE_DATATYPE points2[4][4] =
+ {
+ { IntNoise3D(BaseX - 1, BaseY - 1, BaseZ), IntNoise3D(BaseX, BaseY - 1, BaseZ), IntNoise3D(BaseX + 1, BaseY - 1, BaseZ), IntNoise3D(BaseX + 2, BaseY - 1, BaseZ), },
+ { IntNoise3D(BaseX - 1, BaseY, BaseZ), IntNoise3D(BaseX, BaseY, BaseZ), IntNoise3D(BaseX + 1, BaseY, BaseZ), IntNoise3D(BaseX + 2, BaseY, BaseZ), },
+ { IntNoise3D(BaseX - 1, BaseY + 1, BaseZ), IntNoise3D(BaseX, BaseY + 1, BaseZ), IntNoise3D(BaseX + 1, BaseY + 1, BaseZ), IntNoise3D(BaseX + 2, BaseY + 1, BaseZ), },
+ { IntNoise3D(BaseX - 1, BaseY + 2, BaseZ), IntNoise3D(BaseX, BaseY + 2, BaseZ), IntNoise3D(BaseX + 1, BaseY + 2, BaseZ), IntNoise3D(BaseX + 2, BaseY + 2, BaseZ), },
};
- const NOISE_DATATYPE x2interp1 = CubicInterpolate( points2[0][0], points2[0][1], points2[0][2], points2[0][3], FracX );
- const NOISE_DATATYPE x2interp2 = CubicInterpolate( points2[1][0], points2[1][1], points2[1][2], points2[1][3], FracX );
- const NOISE_DATATYPE x2interp3 = CubicInterpolate( points2[2][0], points2[2][1], points2[2][2], points2[2][3], FracX );
- const NOISE_DATATYPE x2interp4 = CubicInterpolate( points2[3][0], points2[3][1], points2[3][2], points2[3][3], FracX );
+ const NOISE_DATATYPE x2interp1 = CubicInterpolate( points2[0][0], points2[0][1], points2[0][2], points2[0][3], FracX);
+ const NOISE_DATATYPE x2interp2 = CubicInterpolate( points2[1][0], points2[1][1], points2[1][2], points2[1][3], FracX);
+ const NOISE_DATATYPE x2interp3 = CubicInterpolate( points2[2][0], points2[2][1], points2[2][2], points2[2][3], FracX);
+ const NOISE_DATATYPE x2interp4 = CubicInterpolate( points2[3][0], points2[3][1], points2[3][2], points2[3][3], FracX);
- const NOISE_DATATYPE points3[4][4] = {
- { IntNoise3D( BaseX-1, BaseY-1, BaseZ+1 ), IntNoise3D( BaseX, BaseY-1, BaseZ+1 ), IntNoise3D( BaseX+1, BaseY-1, BaseZ+1 ), IntNoise3D( BaseX+2, BaseY-1, BaseZ + 1), },
- { IntNoise3D( BaseX-1, BaseY, BaseZ+1 ), IntNoise3D( BaseX, BaseY, BaseZ+1 ), IntNoise3D( BaseX+1, BaseY, BaseZ+1 ), IntNoise3D( BaseX+2, BaseY, BaseZ + 1), },
- { IntNoise3D( BaseX-1, BaseY+1, BaseZ+1 ), IntNoise3D( BaseX, BaseY+1, BaseZ+1 ), IntNoise3D( BaseX+1, BaseY+1, BaseZ+1 ), IntNoise3D( BaseX+2, BaseY+1, BaseZ + 1), },
- { IntNoise3D( BaseX-1, BaseY+2, BaseZ+1 ), IntNoise3D( BaseX, BaseY+2, BaseZ+1 ), IntNoise3D( BaseX+1, BaseY+2, BaseZ+1 ), IntNoise3D( BaseX+2, BaseY+2, BaseZ + 1), },
+ const NOISE_DATATYPE points3[4][4] =
+ {
+ { IntNoise3D( BaseX-1, BaseY-1, BaseZ+1), IntNoise3D( BaseX, BaseY-1, BaseZ+1), IntNoise3D( BaseX+1, BaseY-1, BaseZ+1), IntNoise3D( BaseX+2, BaseY-1, BaseZ + 1), },
+ { IntNoise3D( BaseX-1, BaseY, BaseZ+1), IntNoise3D( BaseX, BaseY, BaseZ+1), IntNoise3D( BaseX+1, BaseY, BaseZ+1), IntNoise3D( BaseX+2, BaseY, BaseZ + 1), },
+ { IntNoise3D( BaseX-1, BaseY+1, BaseZ+1), IntNoise3D( BaseX, BaseY+1, BaseZ+1), IntNoise3D( BaseX+1, BaseY+1, BaseZ+1), IntNoise3D( BaseX+2, BaseY+1, BaseZ + 1), },
+ { IntNoise3D( BaseX-1, BaseY+2, BaseZ+1), IntNoise3D( BaseX, BaseY+2, BaseZ+1), IntNoise3D( BaseX+1, BaseY+2, BaseZ+1), IntNoise3D( BaseX+2, BaseY+2, BaseZ + 1), },
};
- const NOISE_DATATYPE x3interp1 = CubicInterpolate( points3[0][0], points3[0][1], points3[0][2], points3[0][3], FracX );
- const NOISE_DATATYPE x3interp2 = CubicInterpolate( points3[1][0], points3[1][1], points3[1][2], points3[1][3], FracX );
- const NOISE_DATATYPE x3interp3 = CubicInterpolate( points3[2][0], points3[2][1], points3[2][2], points3[2][3], FracX );
- const NOISE_DATATYPE x3interp4 = CubicInterpolate( points3[3][0], points3[3][1], points3[3][2], points3[3][3], FracX );
+ const NOISE_DATATYPE x3interp1 = CubicInterpolate( points3[0][0], points3[0][1], points3[0][2], points3[0][3], FracX);
+ const NOISE_DATATYPE x3interp2 = CubicInterpolate( points3[1][0], points3[1][1], points3[1][2], points3[1][3], FracX);
+ const NOISE_DATATYPE x3interp3 = CubicInterpolate( points3[2][0], points3[2][1], points3[2][2], points3[2][3], FracX);
+ const NOISE_DATATYPE x3interp4 = CubicInterpolate( points3[3][0], points3[3][1], points3[3][2], points3[3][3], FracX);
- const NOISE_DATATYPE points4[4][4] = {
- { IntNoise3D( BaseX-1, BaseY-1, BaseZ+2 ), IntNoise3D( BaseX, BaseY-1, BaseZ+2 ), IntNoise3D( BaseX+1, BaseY-1, BaseZ+2 ), IntNoise3D( BaseX+2, BaseY-1, BaseZ+2 ), },
- { IntNoise3D( BaseX-1, BaseY, BaseZ+2 ), IntNoise3D( BaseX, BaseY, BaseZ+2 ), IntNoise3D( BaseX+1, BaseY, BaseZ+2 ), IntNoise3D( BaseX+2, BaseY, BaseZ+2 ), },
- { IntNoise3D( BaseX-1, BaseY+1, BaseZ+2 ), IntNoise3D( BaseX, BaseY+1, BaseZ+2 ), IntNoise3D( BaseX+1, BaseY+1, BaseZ+2 ), IntNoise3D( BaseX+2, BaseY+1, BaseZ+2 ), },
- { IntNoise3D( BaseX-1, BaseY+2, BaseZ+2 ), IntNoise3D( BaseX, BaseY+2, BaseZ+2 ), IntNoise3D( BaseX+1, BaseY+2, BaseZ+2 ), IntNoise3D( BaseX+2, BaseY+2, BaseZ+2 ), },
+ const NOISE_DATATYPE points4[4][4] =
+ {
+ { IntNoise3D( BaseX-1, BaseY-1, BaseZ+2), IntNoise3D( BaseX, BaseY-1, BaseZ+2), IntNoise3D( BaseX+1, BaseY-1, BaseZ+2), IntNoise3D( BaseX+2, BaseY-1, BaseZ+2), },
+ { IntNoise3D( BaseX-1, BaseY, BaseZ+2), IntNoise3D( BaseX, BaseY, BaseZ+2), IntNoise3D( BaseX+1, BaseY, BaseZ+2), IntNoise3D( BaseX+2, BaseY, BaseZ+2), },
+ { IntNoise3D( BaseX-1, BaseY+1, BaseZ+2), IntNoise3D( BaseX, BaseY+1, BaseZ+2), IntNoise3D( BaseX+1, BaseY+1, BaseZ+2), IntNoise3D( BaseX+2, BaseY+1, BaseZ+2), },
+ { IntNoise3D( BaseX-1, BaseY+2, BaseZ+2), IntNoise3D( BaseX, BaseY+2, BaseZ+2), IntNoise3D( BaseX+1, BaseY+2, BaseZ+2), IntNoise3D( BaseX+2, BaseY+2, BaseZ+2), },
};
- const NOISE_DATATYPE x4interp1 = CubicInterpolate( points4[0][0], points4[0][1], points4[0][2], points4[0][3], FracX );
- const NOISE_DATATYPE x4interp2 = CubicInterpolate( points4[1][0], points4[1][1], points4[1][2], points4[1][3], FracX );
- const NOISE_DATATYPE x4interp3 = CubicInterpolate( points4[2][0], points4[2][1], points4[2][2], points4[2][3], FracX );
- const NOISE_DATATYPE x4interp4 = CubicInterpolate( points4[3][0], points4[3][1], points4[3][2], points4[3][3], FracX );
+ const NOISE_DATATYPE x4interp1 = CubicInterpolate( points4[0][0], points4[0][1], points4[0][2], points4[0][3], FracX);
+ const NOISE_DATATYPE x4interp2 = CubicInterpolate( points4[1][0], points4[1][1], points4[1][2], points4[1][3], FracX);
+ const NOISE_DATATYPE x4interp3 = CubicInterpolate( points4[2][0], points4[2][1], points4[2][2], points4[2][3], FracX);
+ const NOISE_DATATYPE x4interp4 = CubicInterpolate( points4[3][0], points4[3][1], points4[3][2], points4[3][3], FracX);
- const NOISE_DATATYPE FracY = (a_Y) - BaseY;
- const NOISE_DATATYPE yinterp1 = CubicInterpolate( x1interp1, x1interp2, x1interp3, x1interp4, FracY );
- const NOISE_DATATYPE yinterp2 = CubicInterpolate( x2interp1, x2interp2, x2interp3, x2interp4, FracY );
- const NOISE_DATATYPE yinterp3 = CubicInterpolate( x3interp1, x3interp2, x3interp3, x3interp4, FracY );
- const NOISE_DATATYPE yinterp4 = CubicInterpolate( x4interp1, x4interp2, x4interp3, x4interp4, FracY );
+ const NOISE_DATATYPE FracY = (a_Y) - BaseY;
+ const NOISE_DATATYPE yinterp1 = CubicInterpolate( x1interp1, x1interp2, x1interp3, x1interp4, FracY);
+ const NOISE_DATATYPE yinterp2 = CubicInterpolate( x2interp1, x2interp2, x2interp3, x2interp4, FracY);
+ const NOISE_DATATYPE yinterp3 = CubicInterpolate( x3interp1, x3interp2, x3interp3, x3interp4, FracY);
+ const NOISE_DATATYPE yinterp4 = CubicInterpolate( x4interp1, x4interp2, x4interp3, x4interp4, FracY);
- const NOISE_DATATYPE FracZ = (a_Z) - BaseZ;
- return CubicInterpolate( yinterp1, yinterp2, yinterp3, yinterp4, FracZ );
+ const NOISE_DATATYPE FracZ = (a_Z) - BaseZ;
+ return CubicInterpolate( yinterp1, yinterp2, yinterp3, yinterp4, FracZ);
}
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCubicNoise:
#ifdef _DEBUG
@@ -631,7 +635,7 @@ void cCubicNoise::Generate2D(
Cell.InitWorkRnds(FloorX[0], FloorY[0]);
#ifdef _DEBUG
- // Statistics on the noise-space coords:
+ // Statistics on the noise-space coords:
if (NumSameX == 1)
{
m_NumSingleX++;
@@ -782,7 +786,7 @@ void cCubicNoise::CalcFloorFrac(
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cPerlinNoise:
cPerlinNoise::cPerlinNoise(void) :
@@ -952,7 +956,7 @@ void cPerlinNoise::Generate3D(
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cRidgedMultiNoise:
cRidgedMultiNoise::cRidgedMultiNoise(void) :
diff --git a/src/Noise.h b/src/Noise.h
index 83af0cf08..4cf8d4ad8 100644
--- a/src/Noise.h
+++ b/src/Noise.h
@@ -5,6 +5,12 @@
#pragma once
+#include <cmath>
+
+
+
+
+
// Some settings
#define NOISE_DATATYPE float
@@ -33,6 +39,12 @@ public:
INLINE NOISE_DATATYPE IntNoise2D(int a_X, int a_Y) const;
INLINE NOISE_DATATYPE IntNoise3D(int a_X, int a_Y, int a_Z) const;
+ // Return a float number in the specified range:
+ INLINE NOISE_DATATYPE IntNoise2DInRange(int a_X, int a_Y, float a_Min, float a_Max) const
+ {
+ return a_Min + std::abs(IntNoise2D(a_X, a_Y)) * (a_Max - a_Min);
+ }
+
// Note: These functions have a mod8-irregular chance - each of the mod8 remainders has different chance of occurrence. Divide by 8 to rectify.
INLINE int IntNoise1DInt(int a_X) const;
INLINE int IntNoise2DInt(int a_X, int a_Y) const;
@@ -100,7 +112,7 @@ protected:
cNoise m_Noise; // Used for integral rnd values
#ifdef _DEBUG
- // Statistics on the noise-space coords:
+ // Statistics on the noise-space coords:
static int m_NumSingleX;
static int m_NumSingleXY;
static int m_NumSingleY;
@@ -256,7 +268,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Inline function definitions:
// These need to be in the header, otherwise linker error occur in MSVC
@@ -361,7 +373,7 @@ NOISE_DATATYPE cNoise::LinearInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B,
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Global functions:
extern void Debug2DNoise(const NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, const AString & a_FileNameBase);
diff --git a/src/OSSupport/CMakeLists.txt b/src/OSSupport/CMakeLists.txt
index dee60b450..a42fcbed4 100644
--- a/src/OSSupport/CMakeLists.txt
+++ b/src/OSSupport/CMakeLists.txt
@@ -3,13 +3,42 @@ cmake_minimum_required (VERSION 2.6)
project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
-add_library(OSSupport ${SOURCE})
+SET (SRCS
+ CriticalSection.cpp
+ Errors.cpp
+ Event.cpp
+ File.cpp
+ GZipFile.cpp
+ IsThread.cpp
+ ListenThread.cpp
+ Semaphore.cpp
+ Sleep.cpp
+ Socket.cpp
+ SocketThreads.cpp
+ Thread.cpp
+ Timer.cpp)
-if(UNIX)
- target_link_libraries(OSSupport pthread)
+SET (HDRS
+ CriticalSection.h
+ Errors.h
+ Event.h
+ File.h
+ GZipFile.h
+ IsThread.h
+ ListenThread.h
+ Queue.h
+ Semaphore.h
+ Sleep.h
+ Socket.h
+ SocketThreads.h
+ Thread.h
+ Timer.h)
+
+if(NOT MSVC)
+ add_library(OSSupport ${SRCS} ${HDRS})
+
+ if(UNIX)
+ target_link_libraries(OSSupport pthread)
+ endif()
endif()
diff --git a/src/OSSupport/CriticalSection.cpp b/src/OSSupport/CriticalSection.cpp
index bda97e3a1..5dfc8b5f9 100644
--- a/src/OSSupport/CriticalSection.cpp
+++ b/src/OSSupport/CriticalSection.cpp
@@ -6,7 +6,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCriticalSection:
cCriticalSection::cCriticalSection()
@@ -105,10 +105,10 @@ bool cCriticalSection::IsLockedByCurrentThread(void)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCSLock
-cCSLock::cCSLock(cCriticalSection * a_CS)
+cCSLock::cCSLock(cCriticalSection * a_CS)
: m_CS(a_CS)
, m_IsLocked(false)
{
@@ -119,7 +119,7 @@ cCSLock::cCSLock(cCriticalSection * a_CS)
-cCSLock::cCSLock(cCriticalSection & a_CS)
+cCSLock::cCSLock(cCriticalSection & a_CS)
: m_CS(&a_CS)
, m_IsLocked(false)
{
@@ -165,7 +165,7 @@ void cCSLock::Unlock(void)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCSUnlock:
cCSUnlock::cCSUnlock(cCSLock & a_Lock) :
diff --git a/src/OSSupport/CriticalSection.h b/src/OSSupport/CriticalSection.h
index 73a71f5e1..c3c6e57f0 100644
--- a/src/OSSupport/CriticalSection.h
+++ b/src/OSSupport/CriticalSection.h
@@ -47,7 +47,7 @@ class cCSLock
cCriticalSection * m_CS;
// Unlike a cCriticalSection, this object should be used from a single thread, therefore access to m_IsLocked is not threadsafe
- // In Windows, it is an error to call cCriticalSection::Unlock() multiple times if the lock is not held,
+ // In Windows, it is an error to call cCriticalSection::Unlock() multiple times if the lock is not held,
// therefore we need to check this value whether we are locked or not.
bool m_IsLocked;
diff --git a/src/OSSupport/Errors.cpp b/src/OSSupport/Errors.cpp
index 6072b6ac6..9401ec257 100644
--- a/src/OSSupport/Errors.cpp
+++ b/src/OSSupport/Errors.cpp
@@ -3,7 +3,7 @@
#include "Errors.h"
-AString GetOSErrorString( int a_ErrNo )
+AString GetOSErrorString( int a_ErrNo)
{
char buffer[ 1024 ];
AString Out;
@@ -22,10 +22,10 @@ AString GetOSErrorString( int a_ErrNo )
// According to http://linux.die.net/man/3/strerror_r there are two versions of strerror_r():
- #if !defined(__APPLE__) && ( _GNU_SOURCE ) && !defined(ANDROID_NDK) // GNU version of strerror_r()
+ #if !defined(__APPLE__) && ( _GNU_SOURCE) && !defined(ANDROID_NDK) // GNU version of strerror_r()
- char * res = strerror_r( errno, buffer, ARRAYCOUNT(buffer) );
- if( res != NULL )
+ char * res = strerror_r( errno, buffer, ARRAYCOUNT(buffer));
+ if (res != NULL)
{
Printf(Out, "%d: %s", a_ErrNo, res);
return Out;
@@ -33,8 +33,8 @@ AString GetOSErrorString( int a_ErrNo )
#else // XSI version of strerror_r():
- int res = strerror_r( errno, buffer, ARRAYCOUNT(buffer) );
- if( res == 0 )
+ int res = strerror_r( errno, buffer, ARRAYCOUNT(buffer));
+ if (res == 0)
{
Printf(Out, "%d: %s", a_ErrNo, buffer);
return Out;
diff --git a/src/OSSupport/Event.cpp b/src/OSSupport/Event.cpp
index 72bce4c3c..74f823216 100644
--- a/src/OSSupport/Event.cpp
+++ b/src/OSSupport/Event.cpp
@@ -32,7 +32,7 @@ cEvent::cEvent(void)
AString EventName;
Printf(EventName, "cEvent%p", this);
- m_Event = sem_open(EventName.c_str(), O_CREAT, 777, 0 );
+ m_Event = sem_open(EventName.c_str(), O_CREAT, 777, 0);
if (m_Event == SEM_FAILED)
{
AString error = GetOSErrorString(errno);
@@ -90,7 +90,7 @@ void cEvent::Wait(void)
}
#else
int res = sem_wait(m_Event);
- if (res != 0 )
+ if (res != 0)
{
AString error = GetOSErrorString(errno);
LOGWARN("cEvent: waiting for the event failed: %i, err = %s. Continuing, but server may be unstable.", res, error.c_str());
diff --git a/src/OSSupport/File.cpp b/src/OSSupport/File.cpp
index addf8f928..2194c46ee 100644
--- a/src/OSSupport/File.cpp
+++ b/src/OSSupport/File.cpp
@@ -70,6 +70,7 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
case fmRead: Mode = "rb"; break;
case fmWrite: Mode = "wb"; break;
case fmReadWrite: Mode = "rb+"; break;
+ case fmAppend: Mode = "a+"; break;
}
if (Mode == NULL)
{
@@ -81,7 +82,7 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
m_File = _fsopen((FILE_IO_PREFIX + iFileName).c_str(), Mode, _SH_DENYWR);
#else
m_File = fopen((FILE_IO_PREFIX + iFileName).c_str(), Mode);
-#endif // _WIN32
+#endif // _WIN32
if ((m_File == NULL) && (iMode == fmReadWrite))
{
@@ -94,7 +95,7 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
m_File = _fsopen((FILE_IO_PREFIX + iFileName).c_str(), "wb+", _SH_DENYWR);
#else
m_File = fopen((FILE_IO_PREFIX + iFileName).c_str(), "wb+");
-#endif // _WIN32
+#endif // _WIN32
}
return (m_File != NULL);
@@ -255,10 +256,10 @@ int cFile::ReadRestOfFile(AString & a_Contents)
return -1;
}
- int DataSize = GetSize() - Tell();
+ size_t DataSize = GetSize() - Tell();
// HACK: This depends on the internal knowledge that AString's data() function returns the internal buffer directly
- a_Contents.assign((size_t)DataSize, '\0');
+ a_Contents.assign(DataSize, '\0');
return Read((void *)a_Contents.data(), DataSize);
}
@@ -459,7 +460,7 @@ int cFile::Printf(const char * a_Fmt, ...)
va_start(args, a_Fmt);
AppendVPrintf(buf, a_Fmt, args);
va_end(args);
- return Write(buf.c_str(), (int)buf.length());
+ return Write(buf.c_str(), buf.length());
}
diff --git a/src/OSSupport/File.h b/src/OSSupport/File.h
index 2a7ecf0ed..dfb38e839 100644
--- a/src/OSSupport/File.h
+++ b/src/OSSupport/File.h
@@ -60,9 +60,10 @@ public:
/** The mode in which to open the file */
enum eMode
{
- fmRead, // Read-only. If the file doesn't exist, object will not be valid
- fmWrite, // Write-only. If the file already exists, it will be overwritten
- fmReadWrite // Read/write. If the file already exists, it will be left intact; writing will overwrite the data from the beginning
+ fmRead, // Read-only. If the file doesn't exist, object will not be valid
+ fmWrite, // Write-only. If the file already exists, it will be overwritten
+ fmReadWrite, // Read/write. If the file already exists, it will be left intact; writing will overwrite the data from the beginning
+ fmAppend // Write-only. If the file already exists cursor will be moved to the end of the file
} ;
/** Simple constructor - creates an unopened file object, use Open() to open / create a real file */
diff --git a/src/OSSupport/Queue.h b/src/OSSupport/Queue.h
index beb6a63f1..bf4d7f004 100644
--- a/src/OSSupport/Queue.h
+++ b/src/OSSupport/Queue.h
@@ -21,19 +21,19 @@ cQueueFuncs and is used as the default behavior.
/// This empty struct allows for the callback functions to be inlined
template<class T>
-struct cQueueFuncs
+struct cQueueFuncs
{
public:
/// Called when an Item is deleted from the queue without being returned
- static void Delete(T) {};
+ static void Delete(T) {}
/// Called when an Item is inserted with EnqueueItemIfNotPresent and there is another equal value already inserted
static void Combine(T & a_existing, const T & a_new)
{
UNUSED(a_existing);
UNUSED(a_new);
- };
+ }
};
@@ -88,7 +88,7 @@ public:
cCSLock Lock(m_CS);
if (m_Contents.size() == 0)
{
- return false;
+ return false;
}
item = m_Contents.front();
m_Contents.pop_front();
diff --git a/src/OSSupport/Semaphore.cpp b/src/OSSupport/Semaphore.cpp
index 468de6858..c1fc7d9c7 100644
--- a/src/OSSupport/Semaphore.cpp
+++ b/src/OSSupport/Semaphore.cpp
@@ -5,9 +5,9 @@
-cSemaphore::cSemaphore( unsigned int a_MaxCount, unsigned int a_InitialCount /* = 0 */ )
+cSemaphore::cSemaphore( unsigned int a_MaxCount, unsigned int a_InitialCount /* = 0 */)
#ifndef _WIN32
- : m_bNamed( false )
+ : m_bNamed( false)
#endif
{
#ifndef _WIN32
@@ -20,15 +20,15 @@ cSemaphore::cSemaphore( unsigned int a_MaxCount, unsigned int a_InitialCount /*
m_bNamed = true;
AString Name;
- Printf(Name, "cSemaphore%p", this );
+ Printf(Name, "cSemaphore%p", this);
m_Handle = sem_open(Name.c_str(), O_CREAT, 777, a_InitialCount);
- if( m_Handle == SEM_FAILED )
+ if (m_Handle == SEM_FAILED)
{
- LOG("ERROR: Could not create Semaphore. (%i)", errno );
+ LOG("ERROR: Could not create Semaphore. (%i)", errno);
}
else
{
- if( sem_unlink(Name.c_str()) != 0 )
+ if (sem_unlink(Name.c_str()) != 0)
{
LOG("ERROR: Could not unlink cSemaphore. (%i)", errno);
}
@@ -36,56 +36,72 @@ cSemaphore::cSemaphore( unsigned int a_MaxCount, unsigned int a_InitialCount /*
}
#else
m_Handle = CreateSemaphore(
- NULL, // security attribute
- a_InitialCount, // initial count
- a_MaxCount, // maximum count
- 0 // name (optional)
+ NULL, // security attribute
+ a_InitialCount, // initial count
+ a_MaxCount, // maximum count
+ 0 // name (optional)
);
#endif
}
+
+
+
+
cSemaphore::~cSemaphore()
{
#ifdef _WIN32
- CloseHandle( m_Handle );
+ CloseHandle( m_Handle);
#else
- if( m_bNamed )
- {
- if( sem_close( (sem_t*)m_Handle ) != 0 )
- {
- LOG("ERROR: Could not close cSemaphore. (%i)", errno);
- }
- }
- else
- {
- sem_destroy( (sem_t*)m_Handle );
- delete (sem_t*)m_Handle;
- }
+ if (m_bNamed)
+ {
+ if (sem_close( (sem_t*)m_Handle) != 0)
+ {
+ LOG("ERROR: Could not close cSemaphore. (%i)", errno);
+ }
+ }
+ else
+ {
+ sem_destroy( (sem_t*)m_Handle);
+ delete (sem_t*)m_Handle;
+ }
m_Handle = 0;
#endif
}
+
+
+
+
void cSemaphore::Wait()
{
#ifndef _WIN32
- if( sem_wait( (sem_t*)m_Handle ) != 0)
- {
- LOG("ERROR: Could not wait for cSemaphore. (%i)", errno);
- }
+ if (sem_wait( (sem_t*)m_Handle) != 0)
+ {
+ LOG("ERROR: Could not wait for cSemaphore. (%i)", errno);
+ }
#else
WaitForSingleObject( m_Handle, INFINITE);
#endif
}
+
+
+
+
void cSemaphore::Signal()
{
#ifndef _WIN32
- if( sem_post( (sem_t*)m_Handle ) != 0 )
+ if (sem_post( (sem_t*)m_Handle) != 0)
{
- LOG("ERROR: Could not signal cSemaphore. (%i)", errno);
+ LOG("ERROR: Could not signal cSemaphore. (%i)", errno);
}
#else
- ReleaseSemaphore( m_Handle, 1, NULL );
+ ReleaseSemaphore( m_Handle, 1, NULL);
#endif
}
+
+
+
+
diff --git a/src/OSSupport/Semaphore.h b/src/OSSupport/Semaphore.h
index fbe8907f1..adc531ed8 100644
--- a/src/OSSupport/Semaphore.h
+++ b/src/OSSupport/Semaphore.h
@@ -3,13 +3,13 @@
class cSemaphore
{
public:
- cSemaphore( unsigned int a_MaxCount, unsigned int a_InitialCount = 0 );
+ cSemaphore( unsigned int a_MaxCount, unsigned int a_InitialCount = 0);
~cSemaphore();
void Wait();
void Signal();
private:
- void* m_Handle; // HANDLE pointer
+ void* m_Handle; // HANDLE pointer
#ifndef _WIN32
bool m_bNamed;
diff --git a/src/OSSupport/Sleep.cpp b/src/OSSupport/Sleep.cpp
index 70fb06b40..297d668d7 100644
--- a/src/OSSupport/Sleep.cpp
+++ b/src/OSSupport/Sleep.cpp
@@ -9,11 +9,11 @@
-void cSleep::MilliSleep( unsigned int a_MilliSeconds )
+void cSleep::MilliSleep( unsigned int a_MilliSeconds)
{
#ifdef _WIN32
- Sleep(a_MilliSeconds); // Don't tick too much
+ Sleep(a_MilliSeconds); // Don't tick too much
#else
- usleep(a_MilliSeconds*1000);
+ usleep(a_MilliSeconds*1000);
#endif
}
diff --git a/src/OSSupport/Sleep.h b/src/OSSupport/Sleep.h
index 0ec0adf9d..57d29682c 100644
--- a/src/OSSupport/Sleep.h
+++ b/src/OSSupport/Sleep.h
@@ -3,5 +3,5 @@
class cSleep
{
public:
- static void MilliSleep( unsigned int a_MilliSeconds );
+ static void MilliSleep( unsigned int a_MilliSeconds);
};
diff --git a/src/OSSupport/Socket.cpp b/src/OSSupport/Socket.cpp
index 56835b518..c07d31c8b 100644
--- a/src/OSSupport/Socket.cpp
+++ b/src/OSSupport/Socket.cpp
@@ -25,15 +25,6 @@ cSocket::cSocket(xSocket a_Socket)
-cSocket::~cSocket()
-{
- // Do NOT close the socket; this class is an API wrapper, not a RAII!
-}
-
-
-
-
-
cSocket::operator cSocket::xSocket() const
{
return m_Socket;
@@ -138,7 +129,7 @@ int cSocket::WSAStartup(void)
#ifdef _WIN32
WSADATA wsaData;
memset(&wsaData, 0, sizeof(wsaData));
- return ::WSAStartup(MAKEWORD(2, 2),&wsaData);
+ return ::WSAStartup(MAKEWORD(2, 2), &wsaData);
#else
return 0;
#endif
@@ -244,7 +235,7 @@ cSocket cSocket::AcceptIPv6(void)
// Windows XP doesn't have inet_ntop, so we need to improvise. And MSVC has different headers than GCC
#ifdef _MSC_VER
// MSVC version
- Printf(SClient.m_IPString, "%x:%x:%x:%x:%x:%x:%x:%x",
+ Printf(SClient.m_IPString, "%x:%x:%x:%x:%x:%x:%x:%x",
from.sin6_addr.u.Word[0],
from.sin6_addr.u.Word[1],
from.sin6_addr.u.Word[2],
@@ -256,7 +247,7 @@ cSocket cSocket::AcceptIPv6(void)
);
#else // _MSC_VER
// MinGW
- Printf(SClient.m_IPString, "%x:%x:%x:%x:%x:%x:%x:%x",
+ Printf(SClient.m_IPString, "%x:%x:%x:%x:%x:%x:%x:%x",
from.sin6_addr.s6_addr16[0],
from.sin6_addr.s6_addr16[1],
from.sin6_addr.s6_addr16[2],
diff --git a/src/OSSupport/Socket.h b/src/OSSupport/Socket.h
index 35ecadfa0..e4ec895cb 100644
--- a/src/OSSupport/Socket.h
+++ b/src/OSSupport/Socket.h
@@ -41,7 +41,6 @@ public:
cSocket(void) : m_Socket(INVALID_SOCKET) {}
cSocket(xSocket a_Socket);
- ~cSocket();
bool IsValid(void) const { return IsValidSocket(m_Socket); }
void CloseSocket(void);
diff --git a/src/OSSupport/SocketThreads.cpp b/src/OSSupport/SocketThreads.cpp
index ca8b8438d..f436318a5 100644
--- a/src/OSSupport/SocketThreads.cpp
+++ b/src/OSSupport/SocketThreads.cpp
@@ -13,7 +13,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSocketThreads:
cSocketThreads::cSocketThreads(void)
diff --git a/src/OSSupport/Thread.cpp b/src/OSSupport/Thread.cpp
index 535784613..faaccce96 100644
--- a/src/OSSupport/Thread.cpp
+++ b/src/OSSupport/Thread.cpp
@@ -47,13 +47,13 @@ static void SetThreadName(DWORD dwThreadID, const char * threadName)
-cThread::cThread( ThreadFunc a_ThreadFunction, void* a_Param, const char* a_ThreadName /* = 0 */ )
- : m_ThreadFunction( a_ThreadFunction )
- , m_Param( a_Param )
- , m_Event( new cEvent() )
- , m_StopEvent( 0 )
+cThread::cThread( ThreadFunc a_ThreadFunction, void* a_Param, const char* a_ThreadName /* = 0 */)
+ : m_ThreadFunction( a_ThreadFunction)
+ , m_Param( a_Param)
+ , m_Event( new cEvent())
+ , m_StopEvent( 0)
{
- if( a_ThreadName )
+ if (a_ThreadName)
{
m_ThreadName.assign(a_ThreadName);
}
@@ -68,7 +68,7 @@ cThread::~cThread()
delete m_Event;
m_Event = NULL;
- if( m_StopEvent )
+ if (m_StopEvent)
{
m_StopEvent->Wait();
delete m_StopEvent;
@@ -80,24 +80,24 @@ cThread::~cThread()
-void cThread::Start( bool a_bWaitOnDelete /* = true */ )
+void cThread::Start( bool a_bWaitOnDelete /* = true */)
{
- if( a_bWaitOnDelete )
+ if (a_bWaitOnDelete)
m_StopEvent = new cEvent();
#ifndef _WIN32
pthread_t SndThread;
- if( pthread_create( &SndThread, NULL, MyThread, this) )
+ if (pthread_create( &SndThread, NULL, MyThread, this))
LOGERROR("ERROR: Could not create thread!");
#else
DWORD ThreadID = 0;
- HANDLE hThread = CreateThread( 0 // security
- ,0 // stack size
- , (LPTHREAD_START_ROUTINE) MyThread // function name
- ,this // parameters
- ,0 // flags
- ,&ThreadID ); // thread id
- CloseHandle( hThread );
+ HANDLE hThread = CreateThread(NULL // security
+ , 0 // stack size
+ , (LPTHREAD_START_ROUTINE) MyThread // function name
+ , this // parameters
+ , 0 // flags
+ , &ThreadID); // thread id
+ CloseHandle( hThread);
#ifdef _MSC_VER
if (!m_ThreadName.empty())
@@ -116,9 +116,9 @@ void cThread::Start( bool a_bWaitOnDelete /* = true */ )
#ifdef _WIN32
-unsigned long cThread::MyThread(void* a_Param )
+unsigned long cThread::MyThread(void* a_Param)
#else
-void *cThread::MyThread( void *a_Param )
+void *cThread::MyThread( void *a_Param)
#endif
{
cThread* self = (cThread*)a_Param;
@@ -130,8 +130,8 @@ void *cThread::MyThread( void *a_Param )
// Set event to let other thread know this thread has been created and it's safe to delete the cThread object
self->m_Event->Set();
- ThreadFunction( ThreadParam );
+ ThreadFunction( ThreadParam);
- if( StopEvent ) StopEvent->Set();
+ if (StopEvent) StopEvent->Set();
return 0;
}
diff --git a/src/OSSupport/Thread.h b/src/OSSupport/Thread.h
index 4153b2427..7ee352c82 100644
--- a/src/OSSupport/Thread.h
+++ b/src/OSSupport/Thread.h
@@ -4,18 +4,18 @@ class cThread
{
public:
typedef void (ThreadFunc)(void*);
- cThread( ThreadFunc a_ThreadFunction, void* a_Param, const char* a_ThreadName = 0 );
+ cThread( ThreadFunc a_ThreadFunction, void* a_Param, const char* a_ThreadName = 0);
~cThread();
- void Start( bool a_bWaitOnDelete = true );
+ void Start( bool a_bWaitOnDelete = true);
void WaitForThread();
private:
ThreadFunc* m_ThreadFunction;
#ifdef _WIN32
- static unsigned long MyThread(void* a_Param );
+ static unsigned long MyThread(void* a_Param);
#else
- static void *MyThread( void *lpParam );
+ static void *MyThread( void *lpParam);
#endif
void* m_Param;
diff --git a/src/PolarSSL++/CMakeLists.txt b/src/PolarSSL++/CMakeLists.txt
index 9a59cdb2c..39d41292d 100644
--- a/src/PolarSSL++/CMakeLists.txt
+++ b/src/PolarSSL++/CMakeLists.txt
@@ -3,7 +3,7 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-set(SOURCES
+set(SRCS
AesCfb128Decryptor.cpp
AesCfb128Encryptor.cpp
BlockingSslClientSocket.cpp
@@ -18,7 +18,7 @@ set(SOURCES
X509Cert.cpp
)
-set(HEADERS
+set(HDRS
AesCfb128Decryptor.h
AesCfb128Encryptor.h
BlockingSslClientSocket.h
@@ -33,8 +33,10 @@ set(HEADERS
X509Cert.h
)
-add_library(PolarSSL++ ${SOURCES} ${HEADERS})
+if(NOT MSVC)
+ add_library(PolarSSL++ ${SRCS} ${HDRS})
-if (UNIX)
- target_link_libraries(PolarSSL++ polarssl)
+ if (UNIX)
+ target_link_libraries(PolarSSL++ polarssl)
+ endif()
endif()
diff --git a/src/PolarSSL++/Sha1Checksum.cpp b/src/PolarSSL++/Sha1Checksum.cpp
index a1ee9d7b9..e69ef236f 100644
--- a/src/PolarSSL++/Sha1Checksum.cpp
+++ b/src/PolarSSL++/Sha1Checksum.cpp
@@ -50,7 +50,7 @@ public:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSha1Checksum:
cSha1Checksum::cSha1Checksum(void) :
diff --git a/src/Protocol/Authenticator.cpp b/src/Protocol/Authenticator.cpp
index 2050393c2..984000795 100644
--- a/src/Protocol/Authenticator.cpp
+++ b/src/Protocol/Authenticator.cpp
@@ -2,6 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Authenticator.h"
+#include "MojangAPI.h"
#include "../Root.h"
#include "../Server.h"
#include "../ClientHandle.h"
@@ -11,9 +12,6 @@
#include "PolarSSL++/BlockingSslClientSocket.h"
-#include <sstream>
-#include <iomanip>
-
@@ -21,10 +19,6 @@
#define DEFAULT_AUTH_SERVER "sessionserver.mojang.com"
#define DEFAULT_AUTH_ADDRESS "/session/minecraft/hasJoined?username=%USERNAME%&serverId=%SERVERID%"
-
-
-
-
cAuthenticator::cAuthenticator(void) :
super("cAuthenticator"),
m_Server(DEFAULT_AUTH_SERVER),
@@ -48,8 +42,8 @@ cAuthenticator::~cAuthenticator()
void cAuthenticator::ReadINI(cIniFile & IniFile)
{
- m_Server = IniFile.GetValueSet("Authentication", "Server", DEFAULT_AUTH_SERVER);
- m_Address = IniFile.GetValueSet("Authentication", "Address", DEFAULT_AUTH_ADDRESS);
+ m_Server = IniFile.GetValueSet ("Authentication", "Server", DEFAULT_AUTH_SERVER);
+ m_Address = IniFile.GetValueSet ("Authentication", "Address", DEFAULT_AUTH_ADDRESS);
m_ShouldAuthenticate = IniFile.GetValueSetB("Authentication", "Authenticate", true);
}
@@ -61,7 +55,8 @@ void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, co
{
if (!m_ShouldAuthenticate)
{
- cRoot::Get()->AuthenticateUser(a_ClientID, a_UserName, cClientHandle::GenerateOfflineUUID(a_UserName));
+ Json::Value Value;
+ cRoot::Get()->AuthenticateUser(a_ClientID, a_UserName, cClientHandle::GenerateOfflineUUID(a_UserName), Value);
return;
}
@@ -121,10 +116,11 @@ void cAuthenticator::Execute(void)
AString NewUserName = UserName;
AString UUID;
- if (AuthWithYggdrasil(NewUserName, ServerID, UUID))
+ Json::Value Properties;
+ if (AuthWithYggdrasil(NewUserName, ServerID, UUID, Properties))
{
- LOGINFO("User %s authenticated with UUID '%s'", NewUserName.c_str(), UUID.c_str());
- cRoot::Get()->AuthenticateUser(ClientID, NewUserName, UUID);
+ LOGINFO("User %s authenticated with UUID %s", NewUserName.c_str(), UUID.c_str());
+ cRoot::Get()->AuthenticateUser(ClientID, NewUserName, UUID, Properties);
}
else
{
@@ -137,76 +133,9 @@ void cAuthenticator::Execute(void)
-bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID)
+bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID, Json::Value & a_Properties)
{
- LOGD("Trying to auth user %s", a_UserName.c_str());
-
- int ret;
- unsigned char buf[1024];
-
- /* Initialize certificates */
- // This is the data of the root certs for Starfield Technologies, the CA that signed sessionserver.mojang.com's cert:
- // Downloaded from http://certs.starfieldtech.com/repository/
- static const AString StarfieldCACert(
- // G2 cert
- "-----BEGIN CERTIFICATE-----\n"
- "MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx\n"
- "EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\n"
- "HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs\n"
- "ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw\n"
- "MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6\n"
- "b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj\n"
- "aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp\n"
- "Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n"
- "ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg\n"
- "nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1\n"
- "HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N\n"
- "Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN\n"
- "dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0\n"
- "HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO\n"
- "BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G\n"
- "CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU\n"
- "sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3\n"
- "4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg\n"
- "8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K\n"
- "pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1\n"
- "mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0\n"
- "-----END CERTIFICATE-----\n\n"
- // Original (G1) cert:
- "-----BEGIN CERTIFICATE-----\n"
- "MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl\n"
- "MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp\n"
- "U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw\n"
- "NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE\n"
- "ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp\n"
- "ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3\n"
- "DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf\n"
- "8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN\n"
- "+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0\n"
- "X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa\n"
- "K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA\n"
- "1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G\n"
- "A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR\n"
- "zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0\n"
- "YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD\n"
- "bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w\n"
- "DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3\n"
- "L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D\n"
- "eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl\n"
- "xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp\n"
- "VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY\n"
- "WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=\n"
- "-----END CERTIFICATE-----\n"
- );
-
- // Connect the socket:
- cBlockingSslClientSocket Socket;
- Socket.SetTrustedRootCertsFromString(StarfieldCACert, m_Server);
- if (!Socket.Connect(m_Server, 443))
- {
- LOGWARNING("cAuthenticator: Can't connect to %s: %s", m_Server.c_str(), Socket.GetLastErrorText().c_str());
- return false;
- }
+ LOGD("Trying to authenticate user %s", a_UserName.c_str());
// Create the GET request:
AString ActualAddress = m_Address;
@@ -220,50 +149,19 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
Request += "Connection: close\r\n";
Request += "\r\n";
- if (!Socket.Send(Request.c_str(), Request.size()))
+ AString Response;
+ if (!cMojangAPI::SecureRequest(m_Server, Request, Response))
{
- LOGWARNING("cAuthenticator: Writing SSL data failed: %s", Socket.GetLastErrorText().c_str());
return false;
}
- // Read the HTTP response:
- std::string Response;
- for (;;)
- {
- ret = Socket.Receive(buf, sizeof(buf));
-
- if ((ret == POLARSSL_ERR_NET_WANT_READ) || (ret == POLARSSL_ERR_NET_WANT_WRITE))
- {
- // This value should never be returned, it is handled internally by cBlockingSslClientSocket
- LOGWARNING("cAuthenticator: SSL reading failed internally.");
- return false;
- }
- if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
- {
- break;
- }
- if (ret < 0)
- {
- LOGWARNING("cAuthenticator: SSL reading failed: -0x%x", -ret);
- return false;
- }
- if (ret == 0)
- {
- break;
- }
-
- Response.append((const char *)buf, (size_t)ret);
- }
-
- Socket.Disconnect();
-
// Check the HTTP status line:
- AString prefix("HTTP/1.1 200 OK");
+ const AString Prefix("HTTP/1.1 200 OK");
AString HexDump;
- if (Response.compare(0, prefix.size(), prefix))
+ if (Response.compare(0, Prefix.size(), Prefix))
{
- LOGINFO("User \"%s\" failed to auth, bad http status line received", a_UserName.c_str());
- LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ LOGINFO("User %s failed to auth, bad HTTP status line received", a_UserName.c_str());
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
return false;
}
@@ -271,8 +169,8 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
size_t idxHeadersEnd = Response.find("\r\n\r\n");
if (idxHeadersEnd == AString::npos)
{
- LOGINFO("User \"%s\" failed to authenticate, bad http response header received", a_UserName.c_str());
- LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ LOGINFO("User %s failed to authenticate, bad HTTP response header received", a_UserName.c_str());
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
return false;
}
Response.erase(0, idxHeadersEnd + 4);
@@ -286,20 +184,16 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
Json::Reader reader;
if (!reader.parse(Response, root, false))
{
- LOGWARNING("cAuthenticator: Cannot parse Received Data to json!");
+ LOGWARNING("cAuthenticator: Cannot parse received data (authentication) to JSON!");
return false;
}
a_UserName = root.get("name", "Unknown").asString();
- a_UUID = root.get("id", "").asString();
+ a_UUID = cMojangAPI::MakeUUIDShort(root.get("id", "").asString());
+ a_Properties = root["properties"];
- // If the UUID doesn't contain the hashes, insert them at the proper places:
- if (a_UUID.size() == 32)
- {
- a_UUID.insert(8, "-");
- a_UUID.insert(13, "-");
- a_UUID.insert(18, "-");
- a_UUID.insert(23, "-");
- }
+ // Store the player's profile in the MojangAPI caches:
+ cRoot::Get()->GetMojangAPI().AddPlayerProfile(a_UserName, a_UUID, a_Properties);
+
return true;
}
@@ -307,3 +201,69 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
+/* In case we want to export this function to the plugin API later - don't forget to add the relevant INI configuration lines for DEFAULT_PROPERTIES_ADDRESS
+
+#define DEFAULT_PROPERTIES_ADDRESS "/session/minecraft/profile/%UUID%"
+
+// Gets the properties, such as skin, of a player based on their UUID via Mojang's API
+bool GetPlayerProperties(const AString & a_UUID, Json::Value & a_Properties);
+
+bool cAuthenticator::GetPlayerProperties(const AString & a_UUID, Json::Value & a_Properties)
+{
+ LOGD("Trying to get properties for user %s", a_UUID.c_str());
+
+ // Create the GET request:
+ AString ActualAddress = m_PropertiesAddress;
+ ReplaceString(ActualAddress, "%UUID%", a_UUID);
+
+ AString Request;
+ Request += "GET " + ActualAddress + " HTTP/1.0\r\n";
+ Request += "Host: " + m_Server + "\r\n";
+ Request += "User-Agent: MCServer\r\n";
+ Request += "Connection: close\r\n";
+ Request += "\r\n";
+
+ AString Response;
+ if (!ConnectSecurelyToAddress(StarfieldCACert(), m_Server, Request, Response))
+ {
+ return false;
+ }
+
+ // Check the HTTP status line:
+ const AString Prefix("HTTP/1.1 200 OK");
+ AString HexDump;
+ if (Response.compare(0, Prefix.size(), Prefix))
+ {
+ LOGINFO("Failed to get properties for user %s, bad HTTP status line received", a_UUID.c_str());
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ return false;
+ }
+
+ // Erase the HTTP headers from the response:
+ size_t idxHeadersEnd = Response.find("\r\n\r\n");
+ if (idxHeadersEnd == AString::npos)
+ {
+ LOGINFO("Failed to get properties for user %s, bad HTTP response header received", a_UUID.c_str());
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ return false;
+ }
+ Response.erase(0, idxHeadersEnd + 4);
+
+ // Parse the Json response:
+ if (Response.empty())
+ {
+ return false;
+ }
+
+ Json::Value root;
+ Json::Reader reader;
+ if (!reader.parse(Response, root, false))
+ {
+ LOGWARNING("cAuthenticator: Cannot parse received properties data to JSON!");
+ return false;
+ }
+
+ a_Properties = root["properties"];
+ return true;
+}
+*/
diff --git a/src/Protocol/Authenticator.h b/src/Protocol/Authenticator.h
index 211f51394..853eff535 100644
--- a/src/Protocol/Authenticator.h
+++ b/src/Protocol/Authenticator.h
@@ -11,8 +11,6 @@
#pragma once
-#ifndef CAUTHENTICATOR_H_INCLUDED
-#define CAUTHENTICATOR_H_INCLUDED
#include "../OSSupport/IsThread.h"
@@ -23,6 +21,11 @@
// fwd: "cRoot.h"
class cRoot;
+namespace Json
+{
+ class Value;
+}
+
@@ -47,7 +50,7 @@ public:
/** Stops the authenticator thread. The thread may be started and stopped repeatedly */
void Stop(void);
-
+
private:
class cUser
@@ -71,23 +74,26 @@ private:
cUserList m_Queue;
cEvent m_QueueNonempty;
+ /** The server that is to be contacted for auth / UUID conversions */
AString m_Server;
+
+ /** The URL to use for auth, without server part.
+ %USERNAME% will be replaced with actual user name.
+ %SERVERID% will be replaced with server's ID.
+ For example "/session/minecraft/hasJoined?username=%USERNAME%&serverId=%SERVERID%". */
AString m_Address;
+
+ AString m_PropertiesAddress;
bool m_ShouldAuthenticate;
/** cIsThread override: */
virtual void Execute(void) override;
- /** Returns true if the user authenticated okay, false on error; iLevel is the recursion deptht (bails out if too deep) */
- bool AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID);
+ /** Returns true if the user authenticated okay, false on error
+ Returns the case-corrected username, UUID, and properties (eg. skin). */
+ bool AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID, Json::Value & a_Properties);
};
-
-#endif // CAUTHENTICATOR_H_INCLUDED
-
-
-
-
diff --git a/src/Protocol/CMakeLists.txt b/src/Protocol/CMakeLists.txt
index 849ec27ca..1ba66ff1f 100644
--- a/src/Protocol/CMakeLists.txt
+++ b/src/Protocol/CMakeLists.txt
@@ -4,9 +4,31 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ Authenticator.cpp
+ ChunkDataSerializer.cpp
+ MojangAPI.cpp
+ Protocol125.cpp
+ Protocol132.cpp
+ Protocol14x.cpp
+ Protocol15x.cpp
+ Protocol16x.cpp
+ Protocol17x.cpp
+ ProtocolRecognizer.cpp)
-add_library(Protocol ${SOURCE})
+SET (HDRS
+ Authenticator.h
+ ChunkDataSerializer.h
+ MojangAPI.h
+ Protocol.h
+ Protocol125.h
+ Protocol132.h
+ Protocol14x.h
+ Protocol15x.h
+ Protocol16x.h
+ Protocol17x.h
+ ProtocolRecognizer.h)
+
+if(NOT MSVC)
+ add_library(Protocol ${SRCS} ${HDRS})
+endif()
diff --git a/src/Protocol/MojangAPI.cpp b/src/Protocol/MojangAPI.cpp
new file mode 100644
index 000000000..823ff5469
--- /dev/null
+++ b/src/Protocol/MojangAPI.cpp
@@ -0,0 +1,799 @@
+
+// MojangAPI.cpp
+
+// Implements the cMojangAPI class representing the various API points provided by Mojang's webservices, and a cache for their results
+
+#include "Globals.h"
+#include "MojangAPI.h"
+#include "SQLiteCpp/Database.h"
+#include "SQLiteCpp/Statement.h"
+#include "inifile/iniFile.h"
+#include "json/json.h"
+#include "PolarSSL++/BlockingSslClientSocket.h"
+
+
+
+
+
+/** The maximum age for items to be kept in the cache. Any item older than this will be removed. */
+const Int64 MAX_AGE = 7 * 24 * 60 * 60; // 7 days ago
+
+/** The maximum number of names to send in a single query */
+const int MAX_PER_QUERY = 100;
+
+
+
+
+
+#define DEFAULT_NAME_TO_UUID_SERVER "api.mojang.com"
+#define DEFAULT_NAME_TO_UUID_ADDRESS "/profiles/minecraft"
+#define DEFAULT_UUID_TO_PROFILE_SERVER "sessionserver.mojang.com"
+#define DEFAULT_UUID_TO_PROFILE_ADDRESS "/session/minecraft/profile/%UUID%?unsigned=false"
+
+
+
+
+
+
+/** This is the data of the root certs for Starfield Technologies, the CA that signed sessionserver.mojang.com's cert:
+Downloaded from http://certs.starfieldtech.com/repository/ */
+static const AString & StarfieldCACert(void)
+{
+ static const AString Cert(
+ // G2 cert
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx\n"
+ "EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\n"
+ "HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs\n"
+ "ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw\n"
+ "MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6\n"
+ "b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj\n"
+ "aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp\n"
+ "Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n"
+ "ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg\n"
+ "nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1\n"
+ "HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N\n"
+ "Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN\n"
+ "dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0\n"
+ "HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO\n"
+ "BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G\n"
+ "CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU\n"
+ "sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3\n"
+ "4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg\n"
+ "8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K\n"
+ "pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1\n"
+ "mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0\n"
+ "-----END CERTIFICATE-----\n\n"
+ // Original (G1) cert:
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl\n"
+ "MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp\n"
+ "U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw\n"
+ "NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE\n"
+ "ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp\n"
+ "ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3\n"
+ "DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf\n"
+ "8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN\n"
+ "+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0\n"
+ "X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa\n"
+ "K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA\n"
+ "1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G\n"
+ "A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR\n"
+ "zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0\n"
+ "YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD\n"
+ "bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w\n"
+ "DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3\n"
+ "L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D\n"
+ "eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl\n"
+ "xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp\n"
+ "VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY\n"
+ "WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=\n"
+ "-----END CERTIFICATE-----\n"
+ );
+
+ return Cert;
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cMojangAPI::sProfile:
+
+cMojangAPI::sProfile::sProfile(
+ const AString & a_PlayerName,
+ const AString & a_UUID,
+ const Json::Value & a_Properties,
+ Int64 a_DateTime
+) :
+ m_PlayerName(a_PlayerName),
+ m_UUID(a_UUID),
+ m_Textures(),
+ m_TexturesSignature(),
+ m_DateTime(a_DateTime)
+{
+ /*
+ Example a_Profile contents:
+ "properties":
+ [
+ {
+ "name": "textures",
+ "value": "eyJ0aW1lc3RhbXAiOjE0MDcwNzAzMjEyNzEsInByb2ZpbGVJZCI6ImIxY2FmMjQyMDJhODQxYTc4MDU1YTA3OWM0NjBlZWU3IiwicHJvZmlsZU5hbWUiOiJ4b2Z0IiwiaXNQdWJsaWMiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9iNzc5YmFiZjVhNTg3Zjk0OGFkNjc0N2VhOTEyNzU0MjliNjg4Mjk1YWUzYzA3YmQwZTJmNWJmNGQwNTIifX19",
+ "signature": "XCty+jGEF39hEPrPhYNnCX087kPaoCjYruzYI/DS4nkL5hbjnkSM5Rh15hnUyv/FHhC8OF5rif3D1tQjtMI19KSVaXoUFXpbJM8/+PB8GDgEbX8Fc3u9nYkzOcM/xfxdYsFAdFhLQMkvase/BZLSuPhdy9DdI+TCrO7xuSTZfYmmwVuWo3w5gCY+mSIAnqltnOzaOOTcly75xvO0WYpVk7nJdnR2tvSi0wfrQPDrIg/uzhX7p0SnDqijmBU4QaNez/TNKiFxy69dAzt0RSotlQzqkDbyVKhhv9a4eY8h3pXi4UMftKEj4FAKczxLImkukJXuOn5NN15/Q+le0rJVBC60/xjKIVzltEsMN6qjWD0lQjey7WEL+4pGhCVuWY5KzuZjFvgqszuJTFz7lo+bcHiceldJtea8/fa02eTRObZvdLxbWC9ZfFY0IhpOVKfcLdno/ddDMNMQMi5kMrJ8MZZ/PcW1w5n7MMGWPGCla1kOaC55AL0QYSMGRVEZqgU9wXI5M7sHGZKGM4mWxkbEJYBkpI/p3GyxWgV6v33ZWlsz65TqlNrR1gCLaoFCm7Sif8NqPBZUAONHYon0roXhin/DyEanS93WV6i6FC1Wisscjq2AcvnOlgTo/5nN/1QsMbjNumuMGo37sqjRqlXoPb8zEUbAhhztYuJjEfQ2Rd8="
+ }
+ ]
+ */
+
+ // Parse the Textures and TexturesSignature from the Profile:
+ if (!a_Properties.isArray())
+ {
+ // Properties is not a valid array, bail out
+ return;
+ }
+ Json::UInt Size = a_Properties.size();
+ for (Json::UInt i = 0; i < Size; i++)
+ {
+ const Json::Value & Prop = a_Properties[i];
+ AString PropName = Prop.get("name", "").asString();
+ if (PropName != "textures")
+ {
+ continue;
+ }
+ m_Textures = Prop.get("value", "").asString();
+ m_TexturesSignature = Prop.get("signature", "").asString();
+ break;
+ } // for i - Properties[]
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cMojangAPI:
+
+cMojangAPI::cMojangAPI(void) :
+ m_NameToUUIDServer(DEFAULT_NAME_TO_UUID_SERVER),
+ m_NameToUUIDAddress(DEFAULT_NAME_TO_UUID_ADDRESS),
+ m_UUIDToProfileServer(DEFAULT_UUID_TO_PROFILE_SERVER),
+ m_UUIDToProfileAddress(DEFAULT_UUID_TO_PROFILE_ADDRESS)
+{
+}
+
+
+
+
+
+cMojangAPI::~cMojangAPI()
+{
+ SaveCachesToDisk();
+}
+
+
+
+
+
+void cMojangAPI::Start(cIniFile & a_SettingsIni)
+{
+ m_NameToUUIDServer = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDServer", DEFAULT_NAME_TO_UUID_SERVER);
+ m_NameToUUIDAddress = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDAddress", DEFAULT_NAME_TO_UUID_ADDRESS);
+ m_UUIDToProfileServer = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileServer", DEFAULT_UUID_TO_PROFILE_SERVER);
+ m_UUIDToProfileAddress = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileAddress", DEFAULT_UUID_TO_PROFILE_ADDRESS);
+ LoadCachesFromDisk();
+}
+
+
+
+
+
+AString cMojangAPI::GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_UseOnlyCached)
+{
+ // Convert the playername to lowercase:
+ AString lcPlayerName = StrToLower(a_PlayerName);
+
+ // Request the cache to query the name if not yet cached:
+ if (!a_UseOnlyCached)
+ {
+ AStringVector PlayerNames;
+ PlayerNames.push_back(lcPlayerName);
+ CacheNamesToUUIDs(PlayerNames);
+ }
+
+ // Retrieve from cache:
+ cCSLock Lock(m_CSNameToUUID);
+ cProfileMap::const_iterator itr = m_NameToUUID.find(lcPlayerName);
+ if (itr == m_NameToUUID.end())
+ {
+ // No UUID found
+ return "";
+ }
+ return itr->second.m_UUID;
+}
+
+
+
+
+
+AString cMojangAPI::GetPlayerNameFromUUID(const AString & a_UUID, bool a_UseOnlyCached)
+{
+ // Normalize the UUID to lowercase short format that is used as the map key:
+ AString UUID = MakeUUIDShort(a_UUID);
+
+ // Retrieve from caches:
+ {
+ cCSLock Lock(m_CSUUIDToProfile);
+ cProfileMap::const_iterator itr = m_UUIDToProfile.find(UUID);
+ if (itr != m_UUIDToProfile.end())
+ {
+ return itr->second.m_PlayerName;
+ }
+ }
+ {
+ cCSLock Lock(m_CSUUIDToName);
+ cProfileMap::const_iterator itr = m_UUIDToName.find(UUID);
+ if (itr != m_UUIDToName.end())
+ {
+ return itr->second.m_PlayerName;
+ }
+ }
+
+ // Name not yet cached, request cache and retry:
+ if (!a_UseOnlyCached)
+ {
+ CacheUUIDToProfile(UUID);
+ return GetPlayerNameFromUUID(a_UUID, true);
+ }
+
+ // No value found, none queried. Return an error:
+ return "";
+}
+
+
+
+
+
+AStringVector cMojangAPI::GetUUIDsFromPlayerNames(const AStringVector & a_PlayerNames, bool a_UseOnlyCached)
+{
+ // Convert all playernames to lowercase:
+ AStringVector PlayerNames;
+ for (AStringVector::const_iterator itr = a_PlayerNames.begin(), end = a_PlayerNames.end(); itr != end; ++itr)
+ {
+ PlayerNames.push_back(StrToLower(*itr));
+ } // for itr - a_PlayerNames[]
+
+ // Request the cache to populate any names not yet contained:
+ if (!a_UseOnlyCached)
+ {
+ CacheNamesToUUIDs(PlayerNames);
+ }
+
+ // Retrieve from cache:
+ size_t idx = 0;
+ AStringVector res;
+ res.resize(PlayerNames.size());
+ cCSLock Lock(m_CSNameToUUID);
+ for (AStringVector::const_iterator itr = PlayerNames.begin(), end = PlayerNames.end(); itr != end; ++itr, ++idx)
+ {
+ cProfileMap::const_iterator itrN = m_NameToUUID.find(*itr);
+ if (itrN != m_NameToUUID.end())
+ {
+ res[idx] = itrN->second.m_UUID;
+ }
+ } // for itr - PlayerNames[]
+ return res;
+}
+
+
+
+
+
+void cMojangAPI::AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const AString & a_UUID)
+{
+ AString UUID = MakeUUIDShort(a_UUID);
+ Int64 Now = time(NULL);
+ {
+ cCSLock Lock(m_CSNameToUUID);
+ m_NameToUUID[StrToLower(a_PlayerName)] = sProfile(a_PlayerName, UUID, "", "", Now);
+ }
+ {
+ cCSLock Lock(m_CSUUIDToName);
+ m_UUIDToName[UUID] = sProfile(a_PlayerName, UUID, "", "", Now);
+ }
+}
+
+
+
+
+
+void cMojangAPI::AddPlayerProfile(const AString & a_PlayerName, const AString & a_UUID, const Json::Value & a_Properties)
+{
+ AString UUID = MakeUUIDShort(a_UUID);
+ Int64 Now = time(NULL);
+ {
+ cCSLock Lock(m_CSNameToUUID);
+ m_NameToUUID[StrToLower(a_PlayerName)] = sProfile(a_PlayerName, UUID, "", "", Now);
+ }
+ {
+ cCSLock Lock(m_CSUUIDToName);
+ m_UUIDToName[UUID] = sProfile(a_PlayerName, UUID, "", "", Now);
+ }
+ {
+ cCSLock Lock(m_CSUUIDToProfile);
+ m_UUIDToProfile[UUID] = sProfile(a_PlayerName, UUID, a_Properties, Now);
+ }
+}
+
+
+
+
+
+bool cMojangAPI::SecureRequest(const AString & a_ServerName, const AString & a_Request, AString & a_Response)
+{
+ // Connect the socket:
+ cBlockingSslClientSocket Socket;
+ Socket.SetTrustedRootCertsFromString(StarfieldCACert(), a_ServerName);
+ if (!Socket.Connect(a_ServerName, 443))
+ {
+ LOGWARNING("%s: Can't connect to %s: %s", __FUNCTION__, a_ServerName.c_str(), Socket.GetLastErrorText().c_str());
+ return false;
+ }
+
+ if (!Socket.Send(a_Request.c_str(), a_Request.size()))
+ {
+ LOGWARNING("%s: Writing SSL data failed: %s", __FUNCTION__, Socket.GetLastErrorText().c_str());
+ return false;
+ }
+
+ // Read the HTTP response:
+ int ret;
+ unsigned char buf[1024];
+
+ for (;;)
+ {
+ ret = Socket.Receive(buf, sizeof(buf));
+
+ if ((ret == POLARSSL_ERR_NET_WANT_READ) || (ret == POLARSSL_ERR_NET_WANT_WRITE))
+ {
+ // This value should never be returned, it is handled internally by cBlockingSslClientSocket
+ LOGWARNING("%s: SSL reading failed internally", __FUNCTION__);
+ return false;
+ }
+ if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
+ {
+ break;
+ }
+ if (ret < 0)
+ {
+ LOGWARNING("%s: SSL reading failed: -0x%x", __FUNCTION__, -ret);
+ return false;
+ }
+ if (ret == 0)
+ {
+ break;
+ }
+
+ a_Response.append((const char *)buf, (size_t)ret);
+ }
+
+ Socket.Disconnect();
+ return true;
+}
+
+
+
+
+
+AString cMojangAPI::MakeUUIDShort(const AString & a_UUID)
+{
+ // Note: we only check the string's length, not the actual content
+ switch (a_UUID.size())
+ {
+ case 32:
+ {
+ // Already is a short UUID, only lowercase
+ return StrToLower(a_UUID);
+ }
+
+ case 36:
+ {
+ // Remove the dashes from the string by appending together the parts between them:
+ AString res;
+ res.reserve(32);
+ res.append(a_UUID, 0, 8);
+ res.append(a_UUID, 9, 4);
+ res.append(a_UUID, 14, 4);
+ res.append(a_UUID, 19, 4);
+ res.append(a_UUID, 24, 12);
+ return StrToLower(res);
+ }
+ }
+ LOGWARNING("%s: Not an UUID: \"%s\".", __FUNCTION__, a_UUID.c_str());
+ return "";
+}
+
+
+
+
+
+AString cMojangAPI::MakeUUIDDashed(const AString & a_UUID)
+{
+ // Note: we only check the string's length, not the actual content
+ switch (a_UUID.size())
+ {
+ case 36:
+ {
+ // Already is a dashed UUID, only lowercase
+ return StrToLower(a_UUID);
+ }
+
+ case 32:
+ {
+ // Insert dashes at the proper positions:
+ AString res;
+ res.reserve(36);
+ res.append(a_UUID, 0, 8);
+ res.push_back('-');
+ res.append(a_UUID, 8, 4);
+ res.push_back('-');
+ res.append(a_UUID, 12, 4);
+ res.push_back('-');
+ res.append(a_UUID, 16, 4);
+ res.push_back('-');
+ res.append(a_UUID, 20, 12);
+ return StrToLower(res);
+ }
+ }
+ LOGWARNING("%s: Not an UUID: \"%s\".", __FUNCTION__, a_UUID.c_str());
+ return "";
+}
+
+
+
+
+
+void cMojangAPI::LoadCachesFromDisk(void)
+{
+ try
+ {
+ // Open up the SQLite DB:
+ SQLite::Database db("MojangAPI.sqlite", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
+ db.exec("CREATE TABLE IF NOT EXISTS PlayerNameToUUID (PlayerName, UUID, DateTime)");
+ db.exec("CREATE TABLE IF NOT EXISTS UUIDToProfile (UUID, PlayerName, Textures, TexturesSignature, DateTime)");
+
+ // Clean up old entries:
+ {
+ SQLite::Statement stmt(db, "DELETE FROM PlayerNameToUUID WHERE DateTime < ?");
+ Int64 LimitDateTime = time(NULL) - MAX_AGE;
+ stmt.bind(1, LimitDateTime);
+ stmt.exec();
+ }
+ {
+ SQLite::Statement stmt(db, "DELETE FROM UUIDToProfile WHERE DateTime < ?");
+ Int64 LimitDateTime = time(NULL) - MAX_AGE;
+ stmt.bind(1, LimitDateTime);
+ stmt.exec();
+ }
+
+ // Retrieve all remaining entries:
+ {
+ SQLite::Statement stmt(db, "SELECT PlayerName, UUID, DateTime FROM PlayerNameToUUID");
+ while (stmt.executeStep())
+ {
+ AString PlayerName = stmt.getColumn(0);
+ AString UUID = stmt.getColumn(1);
+ Int64 DateTime = stmt.getColumn(2);
+ UUID = MakeUUIDShort(UUID);
+ m_NameToUUID[StrToLower(PlayerName)] = sProfile(PlayerName, UUID, "", "", DateTime);
+ m_UUIDToName[UUID] = sProfile(PlayerName, UUID, "", "", DateTime);
+ }
+ }
+ {
+ SQLite::Statement stmt(db, "SELECT PlayerName, UUID, Textures, TexturesSignature, DateTime FROM UUIDToProfile");
+ while (stmt.executeStep())
+ {
+ AString PlayerName = stmt.getColumn(0);
+ AString UUID = stmt.getColumn(1);
+ AString Textures = stmt.getColumn(2);
+ AString TexturesSignature = stmt.getColumn(2);
+ Int64 DateTime = stmt.getColumn(4);
+ UUID = MakeUUIDShort(UUID);
+ m_UUIDToProfile[UUID] = sProfile(PlayerName, UUID, Textures, TexturesSignature, DateTime);
+ }
+ }
+ }
+ catch (const SQLite::Exception & ex)
+ {
+ LOGINFO("Loading MojangAPI cache failed: %s", ex.what());
+ }
+}
+
+
+
+
+
+void cMojangAPI::SaveCachesToDisk(void)
+{
+ try
+ {
+ // Open up the SQLite DB:
+ SQLite::Database db("MojangAPI.sqlite", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
+ db.exec("CREATE TABLE IF NOT EXISTS PlayerNameToUUID (PlayerName, UUID, DateTime)");
+ db.exec("CREATE TABLE IF NOT EXISTS UUIDToProfile (UUID, PlayerName, Textures, TexturesSignature, DateTime)");
+
+ // Remove all entries:
+ db.exec("DELETE FROM PlayerNameToUUID");
+ db.exec("DELETE FROM UUIDToProfile");
+
+ // Save all cache entries - m_PlayerNameToUUID:
+ Int64 LimitDateTime = time(NULL) - MAX_AGE;
+ {
+ SQLite::Statement stmt(db, "INSERT INTO PlayerNameToUUID(PlayerName, UUID, DateTime) VALUES (?, ?, ?)");
+ cCSLock Lock(m_CSNameToUUID);
+ for (cProfileMap::const_iterator itr = m_NameToUUID.begin(), end = m_NameToUUID.end(); itr != end; ++itr)
+ {
+ if (itr->second.m_DateTime < LimitDateTime)
+ {
+ // This item is too old, do not save
+ continue;
+ }
+ stmt.bind(1, itr->second.m_PlayerName);
+ stmt.bind(2, itr->second.m_UUID);
+ stmt.bind(3, itr->second.m_DateTime);
+ stmt.exec();
+ stmt.reset();
+ }
+ }
+
+ // Save all cache entries - m_UUIDToProfile:
+ {
+ SQLite::Statement stmt(db, "INSERT INTO UUIDToProfile(UUID, PlayerName, Textures, TexturesSignature, DateTime) VALUES (?, ?, ?, ?, ?)");
+ cCSLock Lock(m_CSUUIDToProfile);
+ for (cProfileMap::const_iterator itr = m_UUIDToProfile.begin(), end = m_UUIDToProfile.end(); itr != end; ++itr)
+ {
+ if (itr->second.m_DateTime < LimitDateTime)
+ {
+ // This item is too old, do not save
+ continue;
+ }
+ stmt.bind(1, itr->second.m_UUID);
+ stmt.bind(2, itr->second.m_PlayerName);
+ stmt.bind(3, itr->second.m_Textures);
+ stmt.bind(4, itr->second.m_TexturesSignature);
+ stmt.bind(5, itr->second.m_DateTime);
+ stmt.exec();
+ stmt.reset();
+ }
+ }
+ }
+ catch (const SQLite::Exception & ex)
+ {
+ LOGINFO("Saving MojangAPI cache failed: %s", ex.what());
+ }
+}
+
+
+
+
+
+void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames)
+{
+ // Create a list of names to query, by removing those that are already cached:
+ AStringVector NamesToQuery;
+ NamesToQuery.reserve(a_PlayerNames.size());
+ {
+ cCSLock Lock(m_CSNameToUUID);
+ for (AStringVector::const_iterator itr = a_PlayerNames.begin(), end = a_PlayerNames.end(); itr != end; ++itr)
+ {
+ if (m_NameToUUID.find(*itr) == m_NameToUUID.end())
+ {
+ NamesToQuery.push_back(*itr);
+ }
+ } // for itr - a_PlayerNames[]
+ } // Lock(m_CSNameToUUID)
+
+ while (!NamesToQuery.empty())
+ {
+ // Create the request body - a JSON containing up to MAX_PER_QUERY playernames:
+ Json::Value root;
+ int Count = 0;
+ AStringVector::iterator itr = NamesToQuery.begin(), end = NamesToQuery.end();
+ for (; (itr != end) && (Count < MAX_PER_QUERY); ++itr, ++Count)
+ {
+ Json::Value req(*itr);
+ root.append(req);
+ } // for itr - a_PlayerNames[]
+ NamesToQuery.erase(NamesToQuery.begin(), itr);
+ Json::FastWriter Writer;
+ AString RequestBody = Writer.write(root);
+
+ // Create the HTTP request:
+ AString Request;
+ Request += "POST " + m_NameToUUIDAddress + " HTTP/1.0\r\n"; // We need to use HTTP 1.0 because we don't handle Chunked transfer encoding
+ Request += "Host: " + m_NameToUUIDServer + "\r\n";
+ Request += "User-Agent: MCServer\r\n";
+ Request += "Connection: close\r\n";
+ Request += "Content-Type: application/json\r\n";
+ Request += Printf("Content-Length: %u\r\n", (unsigned)RequestBody.length());
+ Request += "\r\n";
+ Request += RequestBody;
+
+ // Get the response from the server:
+ AString Response;
+ if (!SecureRequest(m_NameToUUIDServer, Request, Response))
+ {
+ continue;
+ }
+
+ // Check the HTTP status line:
+ const AString Prefix("HTTP/1.1 200 OK");
+ AString HexDump;
+ if (Response.compare(0, Prefix.size(), Prefix))
+ {
+ LOGINFO("%s failed: bad HTTP status line received", __FUNCTION__);
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ continue;
+ }
+
+ // Erase the HTTP headers from the response:
+ size_t idxHeadersEnd = Response.find("\r\n\r\n");
+ if (idxHeadersEnd == AString::npos)
+ {
+ LOGINFO("%s failed: bad HTTP response header received", __FUNCTION__);
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ continue;
+ }
+ Response.erase(0, idxHeadersEnd + 4);
+
+ // Parse the returned string into Json:
+ Json::Reader reader;
+ if (!reader.parse(Response, root, false) || !root.isArray())
+ {
+ LOGWARNING("%s failed: Cannot parse received data (NameToUUID) to JSON!", __FUNCTION__);
+ LOGD("Response body:\n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ continue;
+ }
+
+ // Store the returned results into cache:
+ size_t JsonCount = root.size();
+ Int64 Now = time(NULL);
+ {
+ cCSLock Lock(m_CSNameToUUID);
+ for (size_t idx = 0; idx < JsonCount; ++idx)
+ {
+ Json::Value & Val = root[idx];
+ AString JsonName = Val.get("name", "").asString();
+ AString JsonUUID = MakeUUIDShort(Val.get("id", "").asString());
+ if (JsonUUID.empty())
+ {
+ continue;
+ }
+ m_NameToUUID[StrToLower(JsonName)] = sProfile(JsonName, JsonUUID, "", "", Now);
+ } // for idx - root[]
+ } // cCSLock (m_CSNameToUUID)
+
+ // Also cache the UUIDToName:
+ {
+ cCSLock Lock(m_CSUUIDToName);
+ for (size_t idx = 0; idx < JsonCount; ++idx)
+ {
+ Json::Value & Val = root[idx];
+ AString JsonName = Val.get("name", "").asString();
+ AString JsonUUID = MakeUUIDShort(Val.get("id", "").asString());
+ if (JsonUUID.empty())
+ {
+ continue;
+ }
+ m_UUIDToName[JsonUUID] = sProfile(JsonName, JsonUUID, "", "", Now);
+ } // for idx - root[]
+ }
+ } // while (!NamesToQuery.empty())
+}
+
+
+
+
+
+void cMojangAPI::CacheUUIDToProfile(const AString & a_UUID)
+{
+ ASSERT(a_UUID.size() == 32);
+
+ // Check if already present:
+ {
+ if (m_UUIDToProfile.find(a_UUID) != m_UUIDToProfile.end())
+ {
+ return;
+ }
+ }
+
+ // Create the request address:
+ AString Address = m_UUIDToProfileAddress;
+ ReplaceString(Address, "%UUID%", a_UUID);
+
+ // Create the HTTP request:
+ AString Request;
+ Request += "GET " + Address + " HTTP/1.0\r\n"; // We need to use HTTP 1.0 because we don't handle Chunked transfer encoding
+ Request += "Host: " + m_UUIDToProfileServer + "\r\n";
+ Request += "User-Agent: MCServer\r\n";
+ Request += "Connection: close\r\n";
+ Request += "Content-Length: 0\r\n";
+ Request += "\r\n";
+
+ // Get the response from the server:
+ AString Response;
+ if (!SecureRequest(m_UUIDToProfileServer, Request, Response))
+ {
+ return;
+ }
+
+ // Check the HTTP status line:
+ const AString Prefix("HTTP/1.1 200 OK");
+ AString HexDump;
+ if (Response.compare(0, Prefix.size(), Prefix))
+ {
+ LOGINFO("%s failed: bad HTTP status line received", __FUNCTION__);
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ return;
+ }
+
+ // Erase the HTTP headers from the response:
+ size_t idxHeadersEnd = Response.find("\r\n\r\n");
+ if (idxHeadersEnd == AString::npos)
+ {
+ LOGINFO("%s failed: bad HTTP response header received", __FUNCTION__);
+ LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ return;
+ }
+ Response.erase(0, idxHeadersEnd + 4);
+
+ // Parse the returned string into Json:
+ Json::Reader reader;
+ Json::Value root;
+ if (!reader.parse(Response, root, false) || !root.isObject())
+ {
+ LOGWARNING("%s failed: Cannot parse received data (NameToUUID) to JSON!", __FUNCTION__);
+ LOGD("Response body:\n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
+ return;
+ }
+
+ /* Example response:
+ {
+ "id": "b1caf24202a841a78055a079c460eee7",
+ "name": "xoft",
+ "properties":
+ [
+ {
+ "name": "textures",
+ "value": "eyJ0aW1lc3RhbXAiOjE0MDcwNzAzMjEyNzEsInByb2ZpbGVJZCI6ImIxY2FmMjQyMDJhODQxYTc4MDU1YTA3OWM0NjBlZWU3IiwicHJvZmlsZU5hbWUiOiJ4b2Z0IiwiaXNQdWJsaWMiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9iNzc5YmFiZjVhNTg3Zjk0OGFkNjc0N2VhOTEyNzU0MjliNjg4Mjk1YWUzYzA3YmQwZTJmNWJmNGQwNTIifX19",
+ "signature": "XCty+jGEF39hEPrPhYNnCX087kPaoCjYruzYI/DS4nkL5hbjnkSM5Rh15hnUyv/FHhC8OF5rif3D1tQjtMI19KSVaXoUFXpbJM8/+PB8GDgEbX8Fc3u9nYkzOcM/xfxdYsFAdFhLQMkvase/BZLSuPhdy9DdI+TCrO7xuSTZfYmmwVuWo3w5gCY+mSIAnqltnOzaOOTcly75xvO0WYpVk7nJdnR2tvSi0wfrQPDrIg/uzhX7p0SnDqijmBU4QaNez/TNKiFxy69dAzt0RSotlQzqkDbyVKhhv9a4eY8h3pXi4UMftKEj4FAKczxLImkukJXuOn5NN15/Q+le0rJVBC60/xjKIVzltEsMN6qjWD0lQjey7WEL+4pGhCVuWY5KzuZjFvgqszuJTFz7lo+bcHiceldJtea8/fa02eTRObZvdLxbWC9ZfFY0IhpOVKfcLdno/ddDMNMQMi5kMrJ8MZZ/PcW1w5n7MMGWPGCla1kOaC55AL0QYSMGRVEZqgU9wXI5M7sHGZKGM4mWxkbEJYBkpI/p3GyxWgV6v33ZWlsz65TqlNrR1gCLaoFCm7Sif8NqPBZUAONHYon0roXhin/DyEanS93WV6i6FC1Wisscjq2AcvnOlgTo/5nN/1QsMbjNumuMGo37sqjRqlXoPb8zEUbAhhztYuJjEfQ2Rd8="
+ }
+ ]
+ }
+ */
+
+ // Store the returned result into caches:
+ AString PlayerName = root.get("name", "").asString();
+ if (PlayerName.empty())
+ {
+ // No valid playername, bail out
+ return;
+ }
+ Json::Value Properties = root.get("properties", "");
+ Int64 Now = time(NULL);
+ {
+ cCSLock Lock(m_CSUUIDToProfile);
+ m_UUIDToProfile[a_UUID] = sProfile(PlayerName, a_UUID, Properties, Now);
+ }
+ {
+ cCSLock Lock(m_CSUUIDToName);
+ m_UUIDToName[a_UUID] = sProfile(PlayerName, a_UUID, Properties, Now);
+ }
+ {
+ cCSLock Lock(m_CSNameToUUID);
+ m_NameToUUID[StrToLower(PlayerName)] = sProfile(PlayerName, a_UUID, Properties, Now);
+ }
+}
+
+
+
+
diff --git a/src/Protocol/MojangAPI.h b/src/Protocol/MojangAPI.h
new file mode 100644
index 000000000..6ed37625e
--- /dev/null
+++ b/src/Protocol/MojangAPI.h
@@ -0,0 +1,189 @@
+
+// MojangAPI.h
+
+// Declares the cMojangAPI class representing the various API points provided by Mojang's webservices, and a cache for their results
+
+
+
+
+
+#pragma once
+
+#include <time.h>
+
+namespace Json
+{
+ class Value;
+}
+
+
+
+
+
+// tolua_begin
+class cMojangAPI
+{
+public:
+ // tolua_end
+
+ cMojangAPI(void);
+ ~cMojangAPI();
+
+ /** Initializes the API; reads the settings from the specified ini file.
+ Loads cached results from disk. */
+ void Start(cIniFile & a_SettingsIni);
+
+ /** Connects to the specified server using SSL, sends the given request and receives the response.
+ Checks Mojang certificates using the hard-coded Starfield root CA certificate.
+ Returns true if all was successful, false on failure. */
+ static bool SecureRequest(const AString & a_ServerName, const AString & a_Request, AString & a_Response);
+
+ // tolua_begin
+
+ /** Normalizes the given UUID to its short form (32 bytes, no dashes, lowercase).
+ Logs a warning and returns empty string if not a UUID.
+ Note: only checks the string's length, not the actual content. */
+ static AString MakeUUIDShort(const AString & a_UUID);
+
+ /** Normalizes the given UUID to its dashed form (36 bytes, 4 dashes, lowercase).
+ Logs a warning and returns empty string if not a UUID.
+ Note: only checks the string's length, not the actual content. */
+ static AString MakeUUIDDashed(const AString & a_UUID);
+
+ // tolua_end
+
+ /** Converts a player name into a UUID.
+ The UUID will be empty on error.
+ If a_UseOnlyCached is true, the function only consults the cached values.
+ If a_UseOnlyCached is false and the name is not found in the cache, it is looked up online, which is a blocking
+ operation, do not use this in world-tick thread!
+ If you have multiple names to resolve, use the GetUUIDsFromPlayerNames() function, it uses a single request for multiple names. */
+ AString GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_UseOnlyCached = false);
+
+ /** Converts a UUID into a playername.
+ The returned playername will be empty on error.
+ Both short and dashed UUID formats are accepted.
+ Uses both m_UUIDToName and m_UUIDToProfile to search for the value. Uses m_UUIDToProfile for cache.
+ If a_UseOnlyCached is true, the function only consults the cached values.
+ If a_UseOnlyCached is false and the name is not found in the cache, it is looked up online, which is a blocking
+ operation, do not use this in world-tick thread! */
+ AString GetPlayerNameFromUUID(const AString & a_UUID, bool a_UseOnlyCached = false);
+
+ /** Converts the player names into UUIDs.
+ a_PlayerName[idx] will be converted to UUID and returned as idx-th value
+ The UUID will be empty on error.
+ If a_UseOnlyCached is true, only the cached values are returned.
+ If a_UseOnlyCached is false, the names not found in the cache are looked up online, which is a blocking
+ operation, do not use this in world-tick thread! */
+ AStringVector GetUUIDsFromPlayerNames(const AStringVector & a_PlayerName, bool a_UseOnlyCached = false);
+
+ /** Called by the Authenticator to add a PlayerName -> UUID mapping that it has received from
+ authenticating a user. This adds the cache item and "refreshes" it if existing, adjusting its datetime
+ stamp to now. */
+ void AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const AString & a_UUID);
+
+ /** Called by the Authenticator to add a profile that it has received from authenticating a user. Adds
+ the profile to the respective mapping caches and updtes their datetime stamp to now. */
+ void AddPlayerProfile(const AString & a_PlayerName, const AString & a_UUID, const Json::Value & a_Properties);
+
+protected:
+ /** Holds data for a single player profile. */
+ struct sProfile
+ {
+ AString m_PlayerName; // Case-correct playername
+ AString m_UUID; // Short lowercased UUID
+ AString m_Textures; // The Textures field of the profile properties
+ AString m_TexturesSignature; // The signature of the Textures field of the profile properties
+ Int64 m_DateTime; // UNIXtime of the profile lookup
+
+ /** Default constructor for the container's sake. */
+ sProfile(void) :
+ m_PlayerName(),
+ m_UUID(),
+ m_Textures(),
+ m_TexturesSignature(),
+ m_DateTime(time(NULL))
+ {
+ }
+
+ /** Constructor for the storage creation. */
+ sProfile(
+ const AString & a_PlayerName,
+ const AString & a_UUID,
+ const AString & a_Textures,
+ const AString & a_TexturesSignature,
+ Int64 a_DateTime
+ ) :
+ m_PlayerName(a_PlayerName),
+ m_UUID(a_UUID),
+ m_Textures(a_Textures),
+ m_TexturesSignature(a_TexturesSignature),
+ m_DateTime(a_DateTime)
+ {
+ }
+
+ /** Constructor that parses the values from the Json profile. */
+ sProfile(
+ const AString & a_PlayerName,
+ const AString & a_UUID,
+ const Json::Value & a_Properties,
+ Int64 a_DateTime
+ );
+ };
+ typedef std::map<AString, sProfile> cProfileMap;
+
+
+ /** The server to connect to when converting player names to UUIDs. For example "api.mojang.com". */
+ AString m_NameToUUIDServer;
+
+ /** The URL to use for converting player names to UUIDs, without server part.
+ For example "/profiles/page/1". */
+ AString m_NameToUUIDAddress;
+
+ /** The server to connect to when converting UUID to profile. For example "sessionserver.mojang.com". */
+ AString m_UUIDToProfileServer;
+
+ /** The URL to use for converting UUID to profile, without the server part.
+ Will replace %UUID% with the actual UUID. For example "session/minecraft/profile/%UUID%?unsigned=false". */
+ AString m_UUIDToProfileAddress;
+
+ /** Cache for the Name-to-UUID lookups. The map key is lowercased PlayerName. Protected by m_CSNameToUUID. */
+ cProfileMap m_NameToUUID;
+
+ /** Protects m_NameToUUID against simultaneous multi-threaded access. */
+ cCriticalSection m_CSNameToUUID;
+
+ /** Cache for the Name-to-UUID lookups. The map key is lowercased short UUID. Protected by m_CSUUIDToName. */
+ cProfileMap m_UUIDToName;
+
+ /** Protects m_UUIDToName against simultaneous multi-threaded access. */
+ cCriticalSection m_CSUUIDToName;
+
+ /** Cache for the UUID-to-profile lookups. The map key is lowercased short UUID.
+ Protected by m_CSUUIDToProfile. */
+ cProfileMap m_UUIDToProfile;
+
+ /** Protects m_UUIDToProfile against simultaneous multi-threaded access. */
+ cCriticalSection m_CSUUIDToProfile;
+
+
+ /** Loads the caches from a disk storage. */
+ void LoadCachesFromDisk(void);
+
+ /** Saves the caches to a disk storage. */
+ void SaveCachesToDisk(void);
+
+ /** Makes sure all specified names are in the m_PlayerNameToUUID cache. Downloads any missing ones from Mojang API servers.
+ Names that are not valid are not added into the cache.
+ ASSUMEs that a_PlayerNames contains lowercased player names. */
+ void CacheNamesToUUIDs(const AStringVector & a_PlayerNames);
+
+ /** Makes sure the specified UUID is in the m_UUIDToProfile cache. If missing, downloads it from Mojang API servers.
+ UUIDs that are not valid will not be added into the cache.
+ ASSUMEs that a_UUID is a lowercased short UUID. */
+ void CacheUUIDToProfile(const AString & a_UUID);
+} ; // tolua_export
+
+
+
+
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index ac872a2f2..8e1842ec1 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -100,13 +100,13 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) = 0;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0;
- virtual void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false) = 0;
+ virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) = 0;
virtual void SendExperience (void) = 0;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0;
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0;
virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) = 0;
virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) = 0;
- virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) = 0; // a_Src coords are Block * 8
+ virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) = 0;
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) = 0;
virtual void SendSpawnMob (const cMonster & a_Mob) = 0;
@@ -116,11 +116,11 @@ public:
virtual void SendTabCompletionResults(const AStringVector & a_Results) = 0;
virtual void SendTeleportEntity (const cEntity & a_Entity) = 0;
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
- virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) = 0;
+ virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) = 0;
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) = 0;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 0;
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) = 0;
- virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) = 0;
+ virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
virtual void SendWeather (eWeather a_Weather) = 0;
virtual void SendWholeInventory (const cWindow & a_Window) = 0;
virtual void SendWindowClose (const cWindow & a_Window) = 0;
@@ -132,13 +132,13 @@ public:
protected:
cClientHandle * m_Client;
- cCriticalSection m_CSPacket; //< Each SendXYZ() function must acquire this CS in order to send the whole packet at once
+ cCriticalSection m_CSPacket; // Each SendXYZ() function must acquire this CS in order to send the whole packet at once
/// A generic data-sending routine, all outgoing packet data needs to be routed through this so that descendants may override it
virtual void SendData(const char * a_Data, size_t a_Size) = 0;
/// Called after writing each packet, enables descendants to flush their buffers
- virtual void Flush(void) {};
+ virtual void Flush(void) {}
// Helpers for writing partial packet data, write using SendData()
void WriteByte(Byte a_Value)
diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp
index 6dc2e918d..a66c64309 100644
--- a/src/Protocol/Protocol125.cpp
+++ b/src/Protocol/Protocol125.cpp
@@ -398,7 +398,7 @@ void cProtocol125::SendEntityMetadata(const cEntity & a_Entity)
else
{
WriteEntityMetadata(a_Entity);
- }
+ }
WriteByte(0x7f);
Flush();
@@ -473,7 +473,7 @@ void cProtocol125::SendEntityVelocity(const cEntity & a_Entity)
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_ENTITY_VELOCITY);
WriteInt (a_Entity.GetUniqueID());
- WriteShort((short) (a_Entity.GetSpeedX() * 400)); //400 = 8000 / 20
+ WriteShort((short) (a_Entity.GetSpeedX() * 400)); // 400 = 8000 / 20
WriteShort((short) (a_Entity.GetSpeedY() * 400));
WriteShort((short) (a_Entity.GetSpeedZ() * 400));
Flush();
@@ -760,7 +760,7 @@ void cProtocol125::SendPlayerMoveLook(void)
);
*/
- WriteByte (PACKET_PLAYER_MOVE_LOOK);
+ WriteByte(PACKET_PLAYER_MOVE_LOOK);
cPlayer * Player = m_Client->GetPlayer();
WriteDouble(Player->GetPosX());
WriteDouble(Player->GetStance() + 0.03); // Add a small amount so that the player doesn't start inside a block
@@ -833,23 +833,23 @@ void cProtocol125::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
-void cProtocol125::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
+void cProtocol125::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks)
{
cCSLock Lock(m_CSPacket);
- if ((m_LastSentDimension == a_World.GetDimension()) && !a_ShouldIgnoreDimensionChecks)
+ if ((m_LastSentDimension == a_Dimension) && !a_ShouldIgnoreDimensionChecks)
{
// Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do (unless we are respawning from death)
return;
}
cPlayer * Player = m_Client->GetPlayer();
WriteByte (PACKET_RESPAWN);
- WriteInt (a_World.GetDimension());
+ WriteInt ((int)(a_Dimension));
WriteByte (2); // TODO: Difficulty; 2 = Normal
WriteChar ((char)Player->GetGameMode());
WriteShort (256); // Current world height
WriteString("default");
Flush();
- m_LastSentDimension = a_World.GetDimension();
+ m_LastSentDimension = a_Dimension;
}
@@ -899,7 +899,7 @@ void cProtocol125::SendScoreboardObjective(const AString & a_Name, const AString
-void cProtocol125::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
+void cProtocol125::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch)
{
// Not needed in this protocol version
}
@@ -1005,10 +1005,10 @@ void cProtocol125::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleTyp
void cProtocol125::SendStatistics(const cStatManager & a_Manager)
{
/* NOTE:
- * Versions prior to minecraft 1.7 use an incremental statistic sync
- * method. The current setup does not allow us to implement that, because
- * of performance considerations.
- */
+ Versions prior to minecraft 1.7 use an incremental statistic sync
+ method. The current setup does not allow us to implement that, because
+ of performance considerations.
+ */
#if 0
for (unsigned int i = 0; i < (unsigned int)statCount; ++i)
{
@@ -1072,8 +1072,11 @@ void cProtocol125::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ)
-void cProtocol125::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay)
+void cProtocol125::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle)
{
+ // This protocol doesn't support a_DoDaylightCycle on false.
+ UNUSED(a_DoDaylightCycle);
+
cCSLock Lock(m_CSPacket);
WriteByte (PACKET_UPDATE_TIME);
// Use a_WorldAge for daycount, and a_TimeOfDay for the proper time of day:
@@ -1116,12 +1119,12 @@ void cProtocol125::SendUpdateSign(
-void cProtocol125::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ )
+void cProtocol125::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_USE_BED);
WriteInt (a_Entity.GetUniqueID());
- WriteByte(0); // Unknown byte only 0 has been observed
+ WriteByte(0); // Unknown byte only 0 has been observed
WriteInt (a_BlockX);
WriteByte((Byte)a_BlockY);
WriteInt (a_BlockZ);
@@ -1135,7 +1138,7 @@ void cProtocol125::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_Bloc
void cProtocol125::SendWeather(eWeather a_Weather)
{
cCSLock Lock(m_CSPacket);
- switch( a_Weather )
+ switch (a_Weather)
{
case eWeather_Sunny:
{
@@ -1344,11 +1347,11 @@ int cProtocol125::ParseArmAnim(void)
int cProtocol125::ParseBlockDig(void)
{
- HANDLE_PACKET_READ(ReadChar, char, Status);
+ HANDLE_PACKET_READ(ReadChar, char, Status);
HANDLE_PACKET_READ(ReadBEInt, int, PosX);
- HANDLE_PACKET_READ(ReadByte, Byte, PosY);
+ HANDLE_PACKET_READ(ReadByte, Byte, PosY);
HANDLE_PACKET_READ(ReadBEInt, int, PosZ);
- HANDLE_PACKET_READ(ReadChar, char, BlockFace);
+ HANDLE_PACKET_READ(ReadChar, char, BlockFace);
m_Client->HandleLeftClick(PosX, PosY, PosZ, static_cast<eBlockFace>(BlockFace), Status);
return PARSE_OK;
}
@@ -1426,11 +1429,11 @@ int cProtocol125::ParseEntityAction(void)
switch (ActionID)
{
- case 1: m_Client->HandleEntityCrouch(EntityID, true); break; // Crouch
- case 2: m_Client->HandleEntityCrouch(EntityID, false); break; // Uncrouch
- case 3: m_Client->HandleEntityLeaveBed(EntityID); break; // Leave Bed
- case 4: m_Client->HandleEntitySprinting(EntityID, true); break; // Start sprinting
- case 5: m_Client->HandleEntitySprinting(EntityID, false); break; // Stop sprinting
+ case 1: m_Client->HandleEntityCrouch(EntityID, true); break; // Crouch
+ case 2: m_Client->HandleEntityCrouch(EntityID, false); break; // Uncrouch
+ case 3: m_Client->HandleEntityLeaveBed(EntityID); break; // Leave Bed
+ case 4: m_Client->HandleEntitySprinting(EntityID, true); break; // Start sprinting
+ case 5: m_Client->HandleEntitySprinting(EntityID, false); break; // Stop sprinting
}
return PARSE_OK;
@@ -1444,7 +1447,7 @@ int cProtocol125::ParseHandshake(void)
{
HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Username);
- AStringVector UserData = StringSplit(Username, ";"); // "FakeTruth;localhost:25565"
+ AStringVector UserData = StringSplit(Username, ";"); // "FakeTruth;localhost:25565"
if (UserData.empty())
{
m_Client->Kick("Did not receive username");
@@ -1454,9 +1457,9 @@ int cProtocol125::ParseHandshake(void)
LOGD("HANDSHAKE %s", Username.c_str());
- if (!m_Client->HandleHandshake( m_Username ))
+ if (!m_Client->HandleHandshake( m_Username))
{
- return PARSE_OK; // Player is not allowed into the server
+ return PARSE_OK; // Player is not allowed into the server
}
SendHandshake(cRoot::Get()->GetServer()->GetServerID());
@@ -1916,22 +1919,22 @@ void cProtocol125::WriteEntityMetadata(const cEntity & a_Entity)
{
WriteByte(0x51);
// No idea how Mojang makes their carts shakey shakey, so here is a complicated one-liner expression that does something similar
- WriteInt( (((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4 );
+ WriteInt( (((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4);
WriteByte(0x52);
- WriteInt(1); // Shaking direction, doesn't seem to affect anything
+ WriteInt(1); // Shaking direction, doesn't seem to affect anything
WriteByte(0x73);
- WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
+ WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace)
{
WriteByte(0x10);
- WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled?
+ WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled?
}
}
else if ((a_Entity.IsProjectile() && ((cProjectileEntity &)a_Entity).GetProjectileKind() == cProjectileEntity::pkArrow))
{
WriteByte(0x10);
- WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow?
+ WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow?
}
}
@@ -1946,43 +1949,43 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
case cMonster::mtCreeper:
{
WriteByte(0x10);
- WriteChar(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up?
+ WriteChar(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up?
WriteByte(0x11);
- WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged?
+ WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged?
break;
}
case cMonster::mtBat:
{
WriteByte(0x10);
- WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down?
+ WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down?
break;
}
case cMonster::mtPig:
{
WriteByte(0x10);
- WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled?
+ WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled?
break;
}
case cMonster::mtVillager:
{
WriteByte(0x50);
- WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE?
+ WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE?
break;
}
case cMonster::mtZombie:
{
WriteByte(0xC);
- WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Babby zombie?
+ WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Baby zombie?
WriteByte(0xD);
- WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); // Converted zombie?
+ WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); // Converted zombie?
WriteByte(0xE);
- WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager?
+ WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager?
break;
}
case cMonster::mtGhast:
{
WriteByte(0x10);
- WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to eject un flamé-bol? :P
+ WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to spit a flameball?
break;
}
case cMonster::mtWolf:
@@ -2004,9 +2007,9 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
WriteByte(WolfStatus);
WriteByte(0x72);
- WriteFloat((float)(a_Mob.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way)
+ WriteFloat((float)(a_Mob.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way)
WriteByte(0x13);
- WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode?
+ WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode?
break;
}
case cMonster::mtSheep:
@@ -2028,30 +2031,30 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
case cMonster::mtEnderman:
{
WriteByte(0x10);
- WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house
+ WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house
WriteByte(0x11);
- WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); // Meta of block that he stole from your house
+ WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); // Meta of block that he stole from your house
WriteByte(0x12);
- WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face?
+ WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face?
break;
}
case cMonster::mtSkeleton:
{
WriteByte(0xD);
- WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not
+ WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not
break;
}
case cMonster::mtWitch:
{
WriteByte(0x15);
- WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything
+ WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything
break;
}
case cMonster::mtWither:
{
- WriteByte(0x54); // Int at index 20
+ WriteByte(0x54); // Int at index 20
WriteInt((Int32)((const cWither &)a_Mob).GetWitherInvulnerableTicks());
- WriteByte(0x66); // Float at index 6
+ WriteByte(0x66); // Float at index 6
WriteFloat((float)(a_Mob.GetHealth()));
break;
}
@@ -2061,11 +2064,11 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
WriteByte(0x10);
if (a_Mob.GetMobType() == cMonster::mtSlime)
{
- WriteByte((Byte)((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
+ WriteByte((Byte)((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
}
else
{
- WriteByte((Byte)((const cMagmaCube &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
+ WriteByte((Byte)((const cMagmaCube &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
}
break;
}
@@ -2086,7 +2089,7 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
}
if (((const cHorse &)a_Mob).IsBaby())
{
- Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer
+ Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer
}
if (((const cHorse &)a_Mob).IsEating())
{
@@ -2104,16 +2107,16 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
WriteInt(Flags);
WriteByte(0x13);
- WriteByte((Byte)((const cHorse &)a_Mob).GetHorseType()); // Type of horse (donkey, chestnut, etc.)
+ WriteByte((Byte)((const cHorse &)a_Mob).GetHorseType()); // Type of horse (donkey, chestnut, etc.)
WriteByte(0x54);
int Appearance = 0;
- Appearance = ((const cHorse &)a_Mob).GetHorseColor(); // Mask FF
- Appearance |= ((const cHorse &)a_Mob).GetHorseStyle() * 256; // Mask FF00, so multiply by 256
- WriteInt(Appearance);
+ Appearance = ((const cHorse &)a_Mob).GetHorseColor(); // Mask FF
+ Appearance |= ((const cHorse &)a_Mob).GetHorseStyle() * 256; // Mask FF00, so multiply by 256
+ WriteInt(Appearance);
WriteByte(0x56);
- WriteInt(((const cHorse &)a_Mob).GetHorseArmour()); // Horshey armour
+ WriteInt(((const cHorse &)a_Mob).GetHorseArmour()); // Horshey armour
break;
}
default:
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index 9dbefd3a3..1063777a2 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -72,13 +72,13 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
- virtual void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false) override;
+ virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override;
virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
- virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override {} // This protocol doesn't support such message
- virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override {} // This protocol doesn't support such message
- virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
+ virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override {} // This protocol doesn't support such message
+ virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override {} // This protocol doesn't support such message
+ virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
@@ -88,11 +88,11 @@ public:
virtual void SendTabCompletionResults(const AStringVector & a_Results) override;
virtual void SendTeleportEntity (const cEntity & a_Entity) override;
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
- virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override;
+ virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override;
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
- virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override {};
+ virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override {}
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override;
- virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override;
+ virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendWeather (eWeather a_Weather) override;
virtual void SendWholeInventory (const cWindow & a_Window) override;
virtual void SendWindowClose (const cWindow & a_Window) override;
@@ -103,7 +103,8 @@ public:
protected:
/// Results of packet-parsing:
- enum {
+ enum eParseResult
+ {
PARSE_OK = 1,
PARSE_ERROR = -1,
PARSE_UNKNOWN = -2,
@@ -123,7 +124,7 @@ protected:
/// Sends the Handshake packet
void SendHandshake(const AString & a_ConnectionHash);
- /// Parse the packet of the specified type from m_ReceivedData (switch into ParseXYZ() )
+ /// Parse the packet of the specified type from m_ReceivedData (switch into ParseXYZ())
virtual int ParsePacket(unsigned char a_PacketType);
// Specific packet parsers:
diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp
index 31cf99f53..5c58ab0ba 100644
--- a/src/Protocol/Protocol132.cpp
+++ b/src/Protocol/Protocol132.cpp
@@ -71,7 +71,7 @@ enum
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol132:
cProtocol132::cProtocol132(cClientHandle * a_Client) :
@@ -195,13 +195,6 @@ void cProtocol132::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a
WriteInt (a_Entity.GetUniqueID());
WriteInt (a_Player.GetUniqueID());
Flush();
-
- // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
- SendSoundEffect(
- "random.pop",
- (int)(a_Entity.GetPosX() * 8), (int)(a_Entity.GetPosY() * 8), (int)(a_Entity.GetPosZ() * 8),
- 0.5, (float)(0.75 + ((float)((a_Entity.GetUniqueID() * 23) % 32)) / 64)
- );
}
@@ -285,14 +278,14 @@ void cProtocol132::SendPlayerSpawn(const cPlayer & a_Player)
-void cProtocol132::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
+void cProtocol132::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch)
{
cCSLock Lock(m_CSPacket);
WriteByte (PACKET_SOUND_EFFECT);
WriteString (a_SoundName);
- WriteInt (a_SrcX);
- WriteInt (a_SrcY);
- WriteInt (a_SrcZ);
+ WriteInt ((int)(a_X * 8.0));
+ WriteInt ((int)(a_Y * 8.0));
+ WriteInt ((int)(a_Z * 8.0));
WriteFloat (a_Volume);
WriteChar ((char)(a_Pitch * 63.0f));
Flush();
@@ -389,7 +382,7 @@ void cProtocol132::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
void cProtocol132::SendWholeInventory(const cWindow & a_Window)
{
- // 1.3.2 requires player inventory slots to be sent as SetSlot packets,
+ // 1.3.2 requires player inventory slots to be sent as SetSlot packets,
// otherwise it sometimes fails to update the window
// Send the entire window:
@@ -481,9 +474,9 @@ int cProtocol132::ParseHandshake(void)
HANDLE_PACKET_READ(ReadBEInt, int, ServerPort);
m_Username = Username;
- if (!m_Client->HandleHandshake( m_Username ))
+ if (!m_Client->HandleHandshake( m_Username))
{
- return PARSE_OK; // Player is not allowed into the server
+ return PARSE_OK; // Player is not allowed into the server
}
// Send a 0xfd Encryption Key Request http://wiki.vg/Protocol#0xFD
diff --git a/src/Protocol/Protocol132.h b/src/Protocol/Protocol132.h
index e5d3ee80c..1124a7253 100644
--- a/src/Protocol/Protocol132.h
+++ b/src/Protocol/Protocol132.h
@@ -53,7 +53,7 @@ public:
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
- virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
+ virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
virtual void SendTabCompletionResults(const AStringVector & a_Results) override;
diff --git a/src/Protocol/Protocol14x.cpp b/src/Protocol/Protocol14x.cpp
index f60e756fd..3b6b6a42a 100644
--- a/src/Protocol/Protocol14x.cpp
+++ b/src/Protocol/Protocol14x.cpp
@@ -66,7 +66,7 @@ enum
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol142:
cProtocol142::cProtocol142(cClientHandle * a_Client) :
@@ -130,8 +130,14 @@ void cProtocol142::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_Src
-void cProtocol142::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay)
+void cProtocol142::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle)
{
+ if (!a_DoDaylightCycle)
+ {
+ // When writing a "-" before the number the client ignores it but it will stop the client-side time expiration.
+ a_TimeOfDay = std::min(-a_TimeOfDay, -1LL);
+ }
+
cCSLock Lock(m_CSPacket);
WriteByte (PACKET_UPDATE_TIME);
WriteInt64(a_WorldAge);
@@ -144,7 +150,7 @@ void cProtocol142::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol146:
cProtocol146::cProtocol146(cClientHandle * a_Client) :
diff --git a/src/Protocol/Protocol14x.h b/src/Protocol/Protocol14x.h
index ca497bbc1..227cc8cc7 100644
--- a/src/Protocol/Protocol14x.h
+++ b/src/Protocol/Protocol14x.h
@@ -34,7 +34,7 @@ public:
// Sending commands (alphabetically sorted):
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
- virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override;
+ virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override;
// Specific packet parsers:
virtual int ParseLocaleViewDistance(void) override;
diff --git a/src/Protocol/Protocol15x.cpp b/src/Protocol/Protocol15x.cpp
index 264a596b9..2b1f01b08 100644
--- a/src/Protocol/Protocol15x.cpp
+++ b/src/Protocol/Protocol15x.cpp
@@ -47,7 +47,7 @@ enum
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol150:
cProtocol150::cProtocol150(cClientHandle * a_Client) :
diff --git a/src/Protocol/Protocol16x.cpp b/src/Protocol/Protocol16x.cpp
index eba795f61..0d354a030 100644
--- a/src/Protocol/Protocol16x.cpp
+++ b/src/Protocol/Protocol16x.cpp
@@ -55,7 +55,7 @@ enum
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol161:
cProtocol161::cProtocol161(cClientHandle * a_Client) :
@@ -158,10 +158,10 @@ void cProtocol161::SendPlayerMaxSpeed(void)
-void cProtocol161::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
+void cProtocol161::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks)
{
// Besides sending the respawn, we need to also send the player max speed, otherwise the client reverts to super-fast
- super::SendRespawn(a_World, a_ShouldIgnoreDimensionChecks);
+ super::SendRespawn(a_Dimension, a_ShouldIgnoreDimensionChecks);
SendPlayerMaxSpeed();
}
@@ -202,11 +202,11 @@ int cProtocol161::ParseEntityAction(void)
switch (ActionID)
{
- case 1: m_Client->HandleEntityCrouch(EntityID, true); break; // Crouch
- case 2: m_Client->HandleEntityCrouch(EntityID, false); break; // Uncrouch
- case 3: m_Client->HandleEntityLeaveBed(EntityID); break; // Leave Bed
- case 4: m_Client->HandleEntitySprinting(EntityID, true); break; // Start sprinting
- case 5: m_Client->HandleEntitySprinting(EntityID, false); break; // Stop sprinting
+ case 1: m_Client->HandleEntityCrouch(EntityID, true); break; // Crouch
+ case 2: m_Client->HandleEntityCrouch(EntityID, false); break; // Uncrouch
+ case 3: m_Client->HandleEntityLeaveBed(EntityID); break; // Leave Bed
+ case 4: m_Client->HandleEntitySprinting(EntityID, true); break; // Start sprinting
+ case 5: m_Client->HandleEntitySprinting(EntityID, false); break; // Stop sprinting
}
return PARSE_OK;
@@ -282,7 +282,7 @@ int cProtocol161::ParsePacket(unsigned char a_PacketType)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol162:
cProtocol162::cProtocol162(cClientHandle * a_Client) :
diff --git a/src/Protocol/Protocol16x.h b/src/Protocol/Protocol16x.h
index e6e79027e..add761d1e 100644
--- a/src/Protocol/Protocol16x.h
+++ b/src/Protocol/Protocol16x.h
@@ -42,7 +42,7 @@ protected:
virtual void SendGameMode (eGameMode a_GameMode) override;
virtual void SendHealth (void) override;
virtual void SendPlayerMaxSpeed(void) override;
- virtual void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false) override;
+ virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override;
virtual void SendWindowOpen (const cWindow & a_Window) override;
virtual int ParseEntityAction (void) override;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 855687269..56e73c1c1 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -37,6 +37,7 @@ Implements the 1.7.x protocol classes:
#include "../Mobs/IncludeAllMonsters.h"
#include "../UI/Window.h"
+#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/FlowerPotEntity.h"
@@ -47,7 +48,10 @@ Implements the 1.7.x protocol classes:
#define HANDLE_READ(ByteBuf, Proc, Type, Var) \
Type Var; \
- ByteBuf.Proc(Var);
+ if (!ByteBuf.Proc(Var))\
+ {\
+ return;\
+ }
@@ -81,7 +85,7 @@ extern bool g_ShouldLogCommIn, g_ShouldLogCommOut;
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol172:
cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) :
@@ -651,7 +655,7 @@ void cProtocol172::SendLogin(const cPlayer & a_Player, const cWorld & a_World)
cServer * Server = cRoot::Get()->GetServer();
cPacketizer Pkt(*this, 0x01); // Join Game packet
Pkt.WriteInt(a_Player.GetUniqueID());
- Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4
+ Pkt.WriteByte((Byte)a_Player.GetEffectiveGameMode() | (Server->IsHardcore() ? 0x08 : 0)); // Hardcore flag bit 4
Pkt.WriteChar((char)a_World.GetDimension());
Pkt.WriteByte(2); // TODO: Difficulty (set to Normal)
Pkt.WriteByte(std::min(Server->GetMaxPlayers(), 60));
@@ -680,7 +684,7 @@ void cProtocol172::SendLoginSuccess(void)
{
cPacketizer Pkt(*this, 0x02); // Login success packet
- Pkt.WriteString(m_Client->GetUUID());
+ Pkt.WriteString(cMojangAPI::MakeUUIDDashed(m_Client->GetUUID()));
Pkt.WriteString(m_Client->GetUsername());
}
@@ -807,7 +811,7 @@ void cProtocol172::SendPlayerAbilities(void)
if (Player->IsGameModeCreative())
{
Flags |= 0x01;
- Flags |= 0x08; // Godmode, used for creative
+ Flags |= 0x08; // Godmode, used for creative
}
if (Player->IsFlying())
{
@@ -819,7 +823,7 @@ void cProtocol172::SendPlayerAbilities(void)
}
Pkt.WriteByte(Flags);
Pkt.WriteFloat((float)(0.05 * Player->GetFlyingMaxSpeed()));
- Pkt.WriteFloat((float)(0.1 * Player->GetMaxSpeed()));
+ Pkt.WriteFloat((float)(0.1 * Player->GetNormalMaxSpeed()));
}
@@ -941,7 +945,7 @@ void cProtocol172::SendPlayerSpawn(const cPlayer & a_Player)
// Called to spawn another player for the client
cPacketizer Pkt(*this, 0x0c); // Spawn Player packet
Pkt.WriteVarInt(a_Player.GetUniqueID());
- Pkt.WriteString(a_Player.GetClientHandle()->GetUUID());
+ Pkt.WriteString(cMojangAPI::MakeUUIDDashed(a_Player.GetClientHandle()->GetUUID()));
Pkt.WriteString(a_Player.GetName());
Pkt.WriteFPInt(a_Player.GetPosX());
Pkt.WriteFPInt(a_Player.GetPosY());
@@ -986,9 +990,9 @@ void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
-void cProtocol172::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
+void cProtocol172::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks)
{
- if ((m_LastSentDimension == a_World.GetDimension()) && !a_ShouldIgnoreDimensionChecks)
+ if ((m_LastSentDimension == a_Dimension) && !a_ShouldIgnoreDimensionChecks)
{
// Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do (unless we are respawning from death)
return;
@@ -996,11 +1000,11 @@ void cProtocol172::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimens
cPacketizer Pkt(*this, 0x07); // Respawn packet
cPlayer * Player = m_Client->GetPlayer();
- Pkt.WriteInt(a_World.GetDimension());
+ Pkt.WriteInt((int)a_Dimension);
Pkt.WriteByte(2); // TODO: Difficulty (set to Normal)
Pkt.WriteByte((Byte)Player->GetEffectiveGameMode());
Pkt.WriteString("default");
- m_LastSentDimension = a_World.GetDimension();
+ m_LastSentDimension = a_Dimension;
}
@@ -1026,7 +1030,7 @@ void cProtocol172::SendExperienceOrb(const cExpOrb & a_ExpOrb)
{
ASSERT(m_State == 3); // In game mode?
- cPacketizer Pkt(*this, 0x11);
+ cPacketizer Pkt(*this, 0x11);
Pkt.WriteVarInt(a_ExpOrb.GetUniqueID());
Pkt.WriteInt((int) a_ExpOrb.GetPosX());
Pkt.WriteInt((int) a_ExpOrb.GetPosY());
@@ -1084,15 +1088,15 @@ void cProtocol172::SendDisplayObjective(const AString & a_Objective, cScoreboard
-void cProtocol172::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) // a_Src coords are Block * 8
+void cProtocol172::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch)
{
ASSERT(m_State == 3); // In game mode?
-
+
cPacketizer Pkt(*this, 0x29); // Sound Effect packet
Pkt.WriteString(a_SoundName);
- Pkt.WriteInt(a_SrcX);
- Pkt.WriteInt(a_SrcY);
- Pkt.WriteInt(a_SrcZ);
+ Pkt.WriteInt((int)(a_X * 8.0));
+ Pkt.WriteInt((int)(a_Y * 8.0));
+ Pkt.WriteInt((int)(a_Z * 8.0));
Pkt.WriteFloat(a_Volume);
Pkt.WriteByte((Byte)(a_Pitch * 63));
}
@@ -1130,7 +1134,7 @@ void cProtocol172::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock)
Pkt.WriteFPInt(a_FallingBlock.GetPosZ());
Pkt.WriteByteAngle(a_FallingBlock.GetYaw());
Pkt.WriteByteAngle(a_FallingBlock.GetPitch());
- Pkt.WriteInt(((int)a_FallingBlock.GetBlockType()) | (((int)a_FallingBlock.GetBlockMeta()) << 16)); // Or 0x10
+ Pkt.WriteInt(((int)a_FallingBlock.GetBlockType()) | (((int)a_FallingBlock.GetBlockMeta()) << 16)); // Or 0x10
Pkt.WriteShort((short)(a_FallingBlock.GetSpeedX() * 400));
Pkt.WriteShort((short)(a_FallingBlock.GetSpeedY() * 400));
Pkt.WriteShort((short)(a_FallingBlock.GetSpeedZ() * 400));
@@ -1219,7 +1223,7 @@ void cProtocol172::SendStatistics(const cStatManager & a_Manager)
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x37);
- Pkt.WriteVarInt(statCount); // TODO 2014-05-11 xdot: Optimization: Send "dirty" statistics only
+ Pkt.WriteVarInt(statCount); // TODO 2014-05-11 xdot: Optimization: Send "dirty" statistics only
for (size_t i = 0; i < (size_t)statCount; ++i)
{
@@ -1285,9 +1289,14 @@ void cProtocol172::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ)
-void cProtocol172::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay)
+void cProtocol172::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle)
{
ASSERT(m_State == 3); // In game mode?
+ if (!a_DoDaylightCycle)
+ {
+ // When writing a "-" before the number the client ignores it but it will stop the client-side time expiration.
+ a_TimeOfDay = std::min(-a_TimeOfDay, -1LL);
+ }
cPacketizer Pkt(*this, 0x03);
Pkt.WriteInt64(a_WorldAge);
@@ -1326,10 +1335,11 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
Byte Action = 0;
switch (a_BlockEntity.GetBlockType())
{
- case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing
- case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text
- case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
- case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
+ case E_BLOCK_MOB_SPAWNER: Action = 1; break; // Update mob spawner spinny mob thing
+ case E_BLOCK_COMMAND_BLOCK: Action = 2; break; // Update command block text
+ case E_BLOCK_BEACON: Action = 3; break; // Update beacon entity
+ case E_BLOCK_HEAD: Action = 4; break; // Update Mobhead entity
+ case E_BLOCK_FLOWER_POT: Action = 5; break; // Update flower pot
default: ASSERT(!"Unhandled or unimplemented BlockEntity update request!"); break;
}
Pkt.WriteByte(Action);
@@ -1587,7 +1597,7 @@ void cProtocol172::AddReceivedData(const char * a_Data, size_t a_Size)
ASSERT(!"Read wrong number of bytes!");
m_Client->PacketError(PacketType);
}
- } // for(ever)
+ } // for (ever)
// Log any leftover bytes into the logfile:
if (g_ShouldLogCommIn && (m_ReceivedData.GetReadableSpace() > 0))
@@ -1656,7 +1666,7 @@ bool cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
case 0x0c: HandlePacketSteerVehicle (a_ByteBuffer); return true;
case 0x0d: HandlePacketWindowClose (a_ByteBuffer); return true;
case 0x0e: HandlePacketWindowClick (a_ByteBuffer); return true;
- case 0x0f: // Confirm transaction - not used in MCS
+ case 0x0f: // Confirm transaction - not used in MCS
case 0x10: HandlePacketCreativeInventoryAction(a_ByteBuffer); return true;
case 0x11: HandlePacketEnchantItem (a_ByteBuffer); return true;
case 0x12: HandlePacketUpdateSign (a_ByteBuffer); return true;
@@ -1698,8 +1708,7 @@ bool cProtocol172::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType)
void cProtocol172::HandlePacketStatusPing(cByteBuffer & a_ByteBuffer)
{
- Int64 Timestamp;
- a_ByteBuffer.ReadBEInt64(Timestamp);
+ HANDLE_READ(a_ByteBuffer, ReadBEInt64, Int64, Timestamp);
cPacketizer Pkt(*this, 0x01); // Ping packet
Pkt.WriteInt64(Timestamp);
@@ -1712,16 +1721,16 @@ void cProtocol172::HandlePacketStatusPing(cByteBuffer & a_ByteBuffer)
void cProtocol172::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer)
{
// Send the response:
- AString Response = "{\"version\":{\"name\":\"1.7.2\",\"protocol\":4},\"players\":{";
+ AString Response = "{\"version\":{\"name\":\"1.7.2\", \"protocol\":4}, \"players\":{";
cServer * Server = cRoot::Get()->GetServer();
- AppendPrintf(Response, "\"max\":%u,\"online\":%u,\"sample\":[]},",
+ AppendPrintf(Response, "\"max\":%u, \"online\":%u, \"sample\":[]},",
Server->GetMaxPlayers(),
Server->GetNumPlayers()
);
AppendPrintf(Response, "\"description\":{\"text\":\"%s\"},",
Server->GetDescription().c_str()
);
- AppendPrintf(Response, "\"favicon\":\"data:image/png;base64,%s\"",
+ AppendPrintf(Response, "\"favicon\": \"data:image/png;base64,%s\"",
Server->GetFaviconData().c_str()
);
Response.append("}");
@@ -1950,11 +1959,11 @@ void cProtocol172::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer)
switch (Action)
{
- case 1: m_Client->HandleEntityCrouch(PlayerID, true); break; // Crouch
- case 2: m_Client->HandleEntityCrouch(PlayerID, false); break; // Uncrouch
- case 3: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed
- case 4: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting
- case 5: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting
+ case 1: m_Client->HandleEntityCrouch(PlayerID, true); break; // Crouch
+ case 2: m_Client->HandleEntityCrouch(PlayerID, false); break; // Uncrouch
+ case 3: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed
+ case 4: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting
+ case 5: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting
}
}
@@ -2052,7 +2061,10 @@ void cProtocol172::HandlePacketPluginMessage(cByteBuffer & a_ByteBuffer)
HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Channel);
HANDLE_READ(a_ByteBuffer, ReadBEShort, short, Length);
AString Data;
- a_ByteBuffer.ReadString(Data, Length);
+ if (!a_ByteBuffer.ReadString(Data, Length))
+ {
+ return;
+ }
m_Client->HandlePluginMessage(Channel, Data);
}
@@ -2311,7 +2323,7 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
{
case TAG_List:
{
- if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags
+ if ((TagName == "ench") || (TagName == "StoredEnchantments")) // Enchantments tags
{
EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag);
}
@@ -2319,21 +2331,21 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
}
case TAG_Compound:
{
- if (TagName == "display") // Custom name and lore tag
+ if (TagName == "display") // Custom name and lore tag
{
for (int displaytag = NBT.GetFirstChild(tag); displaytag >= 0; displaytag = NBT.GetNextSibling(displaytag))
{
- if ((NBT.GetType(displaytag) == TAG_String) && (NBT.GetName(displaytag) == "Name")) // Custon name tag
+ if ((NBT.GetType(displaytag) == TAG_String) && (NBT.GetName(displaytag) == "Name")) // Custon name tag
{
a_Item.m_CustomName = NBT.GetString(displaytag);
}
- else if ((NBT.GetType(displaytag) == TAG_List) && (NBT.GetName(displaytag) == "Lore")) // Lore tag
+ else if ((NBT.GetType(displaytag) == TAG_List) && (NBT.GetName(displaytag) == "Lore")) // Lore tag
{
AString Lore;
- for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings
+ for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings
{
- AppendPrintf(Lore, "%s`", NBT.GetString(loretag).c_str()); // Append the lore with a grave accent/backtick, used internally by MCS to display a new line in the client; don't forget to c_str ;)
+ AppendPrintf(Lore, "%s`", NBT.GetString(loretag).c_str()); // Append the lore with a grave accent/backtick, used internally by MCS to display a new line in the client; don't forget to c_str ;)
}
a_Item.m_Lore = Lore;
@@ -2463,7 +2475,7 @@ void cProtocol172::AddChatPartStyle(Json::Value & a_Value, const AString & a_Par
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol172::cPacketizer:
cProtocol172::cPacketizer::~cPacketizer()
@@ -2533,7 +2545,7 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
if (!a_Item.m_Enchantments.IsEmpty())
{
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
- EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments,Writer, TagName);
+ EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName);
}
if (!a_Item.IsBothNameAndLoreEmpty())
{
@@ -2581,11 +2593,24 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
switch (a_BlockEntity.GetBlockType())
{
+ case E_BLOCK_BEACON:
+ {
+ cBeaconEntity & BeaconEntity = (cBeaconEntity &)a_BlockEntity;
+
+ Writer.AddInt("x", BeaconEntity.GetPosX());
+ Writer.AddInt("y", BeaconEntity.GetPosY());
+ Writer.AddInt("z", BeaconEntity.GetPosZ());
+ Writer.AddInt("Primary", BeaconEntity.GetPrimaryEffect());
+ Writer.AddInt("Secondary", BeaconEntity.GetSecondaryEffect());
+ Writer.AddInt("Levels", BeaconEntity.GetBeaconLevel());
+ Writer.AddString("id", "Beacon"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
+ break;
+ }
case E_BLOCK_COMMAND_BLOCK:
{
cCommandBlockEntity & CommandBlockEntity = (cCommandBlockEntity &)a_BlockEntity;
- Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
+ Writer.AddByte("TrackOutput", 1); // Neither I nor the MC wiki has any idea about this
Writer.AddInt("SuccessCount", CommandBlockEntity.GetResult());
Writer.AddInt("x", CommandBlockEntity.GetPosX());
Writer.AddInt("y", CommandBlockEntity.GetPosY());
@@ -2595,7 +2620,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
// For a command block, this would be the 'name' prepended to anything it outputs into global chat
// MCS doesn't have this, so just leave it @ '@'. (geddit?)
Writer.AddString("CustomName", "@");
- Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
+ Writer.AddString("id", "Control"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
if (!CommandBlockEntity.GetLastOutput().empty())
{
@@ -2616,7 +2641,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
Writer.AddByte("SkullType", MobHeadEntity.GetType() & 0xFF);
Writer.AddByte("Rot", MobHeadEntity.GetRotation() & 0xFF);
Writer.AddString("ExtraType", MobHeadEntity.GetOwner().c_str());
- Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
+ Writer.AddString("id", "Skull"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
break;
}
case E_BLOCK_FLOWER_POT:
@@ -2628,7 +2653,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
Writer.AddInt("z", FlowerPotEntity.GetPosZ());
Writer.AddInt("Item", (Int32) FlowerPotEntity.GetItem().m_ItemType);
Writer.AddInt("Data", (Int32) FlowerPotEntity.GetItem().m_ItemDamage);
- Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
+ Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
break;
}
default: break;
@@ -2707,15 +2732,16 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity)
// The following expression makes Minecarts shake more with less health or higher damage taken
// It gets half the maximum health, and takes it away from the current health minus the half health:
- /* Health: 5 | 3 - (5 - 3) = 1 (shake power)
- Health: 3 | 3 - (3 - 3) = 3
- Health: 1 | 3 - (1 - 3) = 5
+ /*
+ Health: 5 | 3 - (5 - 3) = 1 (shake power)
+ Health: 3 | 3 - (3 - 3) = 3
+ Health: 1 | 3 - (1 - 3) = 5
*/
WriteInt((((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4);
WriteByte(0x52);
- WriteInt(1); // Shaking direction, doesn't seem to affect anything
+ WriteInt(1); // Shaking direction, doesn't seem to affect anything
WriteByte(0x73);
- WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
+ WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpNone)
{
@@ -2903,9 +2929,9 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob)
case cMonster::mtWither:
{
- WriteByte(0x54); // Int at index 20
+ WriteByte(0x54); // Int at index 20
WriteInt(((const cWither &)a_Mob).GetWitherInvulnerableTicks());
- WriteByte(0x66); // Float at index 6
+ WriteByte(0x66); // Float at index 6
WriteFloat((float)(a_Mob.GetHealth()));
break;
}
@@ -2985,7 +3011,7 @@ void cProtocol172::cPacketizer::WriteEntityProperties(const cEntity & a_Entity)
return;
}
- //const cMonster & Mob = (const cMonster &)a_Entity;
+ // const cMonster & Mob = (const cMonster &)a_Entity;
// TODO: Send properties and modifiers based on the mob type
@@ -2996,7 +3022,7 @@ void cProtocol172::cPacketizer::WriteEntityProperties(const cEntity & a_Entity)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cProtocol176:
cProtocol176::cProtocol176(cClientHandle * a_Client, const AString &a_ServerAddress, UInt16 a_ServerPort, UInt32 a_State) :
@@ -3013,9 +3039,19 @@ void cProtocol176::SendPlayerSpawn(const cPlayer & a_Player)
// Called to spawn another player for the client
cPacketizer Pkt(*this, 0x0c); // Spawn Player packet
Pkt.WriteVarInt(a_Player.GetUniqueID());
- Pkt.WriteString(a_Player.GetClientHandle()->GetUUID());
+ Pkt.WriteString(cMojangAPI::MakeUUIDDashed(a_Player.GetClientHandle()->GetUUID()));
Pkt.WriteString(a_Player.GetName());
- Pkt.WriteVarInt(0); // We have no data to send here
+
+ const Json::Value & Properties = a_Player.GetClientHandle()->GetProperties();
+ Pkt.WriteVarInt(Properties.size());
+
+ for (Json::Value::iterator itr = Properties.begin(), end = Properties.end(); itr != end; ++itr)
+ {
+ Pkt.WriteString(((Json::Value)*itr).get("name", "").asString());
+ Pkt.WriteString(((Json::Value)*itr).get("value", "").asString());
+ Pkt.WriteString(((Json::Value)*itr).get("signature", "").asString());
+ }
+
Pkt.WriteFPInt(a_Player.GetPosX());
Pkt.WriteFPInt(a_Player.GetPosY());
Pkt.WriteFPInt(a_Player.GetPosZ());
@@ -3035,15 +3071,15 @@ void cProtocol176::SendPlayerSpawn(const cPlayer & a_Player)
void cProtocol176::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer)
{
// Send the response:
- AString Response = "{\"version\":{\"name\":\"1.7.6\",\"protocol\":5},\"players\":{";
- AppendPrintf(Response, "\"max\":%u,\"online\":%u,\"sample\":[]},",
+ AString Response = "{\"version\": {\"name\": \"1.7.6\", \"protocol\":5}, \"players\": {";
+ AppendPrintf(Response, "\"max\": %u, \"online\": %u, \"sample\": []},",
cRoot::Get()->GetServer()->GetMaxPlayers(),
cRoot::Get()->GetServer()->GetNumPlayers()
);
- AppendPrintf(Response, "\"description\":{\"text\":\"%s\"},",
+ AppendPrintf(Response, "\"description\": {\"text\": \"%s\"},",
cRoot::Get()->GetServer()->GetDescription().c_str()
);
- AppendPrintf(Response, "\"favicon\":\"data:image/png;base64,%s\"",
+ AppendPrintf(Response, "\"favicon\": \"data:image/png;base64,%s\"",
cRoot::Get()->GetServer()->GetFaviconData().c_str()
);
Response.append("}");
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 1a65cfa1c..ccfa19eb6 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -104,8 +104,8 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
- virtual void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false) override;
- virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
+ virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override;
+ virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
@@ -120,11 +120,11 @@ public:
virtual void SendTabCompletionResults(const AStringVector & a_Results) override;
virtual void SendTeleportEntity (const cEntity & a_Entity) override;
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
- virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override;
+ virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override;
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override;
- virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override;
+ virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendWeather (eWeather a_Weather) override;
virtual void SendWholeInventory (const cWindow & a_Window) override;
virtual void SendWindowClose (const cWindow & a_Window) override;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index c0c9e08ee..18694572a 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -1,7 +1,7 @@
// ProtocolRecognizer.cpp
-// Implements the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple
+// Implements the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple
// protocol versions and redirects everything to them
#include "Globals.h"
@@ -331,7 +331,7 @@ void cProtocolRecognizer::SendEntityVelocity(const cEntity & a_Entity)
void cProtocolRecognizer::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion)
{
ASSERT(m_Protocol != NULL);
- m_Protocol->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_Radius, a_BlocksAffected, a_PlayerMotion);
+ m_Protocol->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, a_Radius, a_BlocksAffected, a_PlayerMotion);
}
@@ -556,10 +556,10 @@ void cProtocolRecognizer::SendRemoveEntityEffect(const cEntity & a_Entity, int a
-void cProtocolRecognizer::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
+void cProtocolRecognizer::SendRespawn(eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks)
{
ASSERT(m_Protocol != NULL);
- m_Protocol->SendRespawn(a_World, a_ShouldIgnoreDimensionChecks);
+ m_Protocol->SendRespawn(a_Dimension, a_ShouldIgnoreDimensionChecks);
}
@@ -616,10 +616,10 @@ void cProtocolRecognizer::SendDisplayObjective(const AString & a_Objective, cSco
-void cProtocolRecognizer::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch)
+void cProtocolRecognizer::SendSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch)
{
ASSERT(m_Protocol != NULL);
- m_Protocol->SendSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch);
+ m_Protocol->SendSoundEffect(a_SoundName, a_X, a_Y, a_Z, a_Volume, a_Pitch);
}
@@ -716,10 +716,10 @@ void cProtocolRecognizer::SendThunderbolt(int a_BlockX, int a_BlockY, int a_Bloc
-void cProtocolRecognizer::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay)
+void cProtocolRecognizer::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle)
{
ASSERT(m_Protocol != NULL);
- m_Protocol->SendTimeUpdate(a_WorldAge, a_TimeOfDay);
+ m_Protocol->SendTimeUpdate(a_WorldAge, a_TimeOfDay, a_DoDaylightCycle);
}
@@ -756,7 +756,7 @@ void cProtocolRecognizer::SendUpdateSign(int a_BlockX, int a_BlockY, int a_Block
-void cProtocolRecognizer::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ )
+void cProtocolRecognizer::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
{
ASSERT(m_Protocol != NULL);
m_Protocol->SendUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ);
@@ -828,7 +828,7 @@ void cProtocolRecognizer::SendData(const char * a_Data, size_t a_Size)
bool cProtocolRecognizer::TryRecognizeProtocol(void)
{
- // NOTE: If a new protocol is added or an old one is removed, adjust MCS_CLIENT_VERSIONS and
+ // NOTE: If a new protocol is added or an old one is removed, adjust MCS_CLIENT_VERSIONS and
// MCS_PROTOCOL_VERSIONS macros in the header file, as well as PROTO_VERSION_LATEST macro
// The first packet should be a Handshake, 0x02:
@@ -953,7 +953,6 @@ bool cProtocolRecognizer::TryRecognizeLengthlessProtocol(void)
bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRemaining)
{
UInt32 PacketType;
- UInt32 NumBytesRead = (UInt32)m_Buffer.GetReadableSpace();
if (!m_Buffer.ReadVarInt(PacketType))
{
return false;
@@ -972,7 +971,6 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
{
return false;
}
- NumBytesRead -= (UInt32)m_Buffer.GetReadableSpace();
switch (ProtocolVersion)
{
case PROTO_VERSION_1_7_2:
@@ -1021,11 +1019,11 @@ void cProtocolRecognizer::SendLengthlessServerPing(void)
case PROTO_VERSION_1_3_2:
{
// http://wiki.vg/wiki/index.php?title=Protocol&oldid=3099#Server_List_Ping_.280xFE.29
- Printf(Reply, "%s%s%i%s%i",
+ Printf(Reply, "%s%s%i%s%i",
Server->GetDescription().c_str(),
- cChatColor::Delimiter.c_str(),
+ cChatColor::Delimiter,
Server->GetNumPlayers(),
- cChatColor::Delimiter.c_str(),
+ cChatColor::Delimiter,
Server->GetMaxPlayers()
);
break;
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index 0a9a42e93..28572a8fd 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -1,7 +1,7 @@
// ProtocolRecognizer.h
-// Interfaces to the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple
+// Interfaces to the cProtocolRecognizer class representing the meta-protocol that recognizes possibly multiple
// protocol versions and redirects everything to them
@@ -107,13 +107,13 @@ public:
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
- virtual void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false) override;
+ virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override;
virtual void SendExperience (void) override;
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override;
virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override;
- virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override;
+ virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
@@ -123,11 +123,11 @@ public:
virtual void SendTabCompletionResults(const AStringVector & a_Results) override;
virtual void SendTeleportEntity (const cEntity & a_Entity) override;
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
- virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay) override;
+ virtual void SendTimeUpdate (Int64 a_WorldAge, Int64 a_TimeOfDay, bool a_DoDaylightCycle) override;
virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override;
- virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override;
+ virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendWeather (eWeather a_Weather) override;
virtual void SendWholeInventory (const cWindow & a_Window) override;
virtual void SendWindowClose (const cWindow & a_Window) override;
@@ -139,8 +139,8 @@ public:
virtual void SendData(const char * a_Data, size_t a_Size) override;
protected:
- cProtocol * m_Protocol; //< The recognized protocol
- cByteBuffer m_Buffer; //< Buffer for the incoming data until we recognize the protocol
+ cProtocol * m_Protocol; ///< The recognized protocol
+ cByteBuffer m_Buffer; ///< Buffer for the incoming data until we recognize the protocol
/// Tries to recognize protocol based on m_Buffer contents; returns true if recognized
bool TryRecognizeProtocol(void);
diff --git a/src/RCONServer.cpp b/src/RCONServer.cpp
index c511968be..141c67d1b 100644
--- a/src/RCONServer.cpp
+++ b/src/RCONServer.cpp
@@ -38,7 +38,7 @@ enum
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cRCONCommandOutput:
class cRCONCommandOutput :
@@ -73,13 +73,13 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cRCONServer:
cRCONServer::cRCONServer(cServer & a_Server) :
m_Server(a_Server),
- m_ListenThread4(*this, cSocket::IPv4, "RCON IPv4"),
- m_ListenThread6(*this, cSocket::IPv6, "RCON IPv6")
+ m_ListenThread4(*this, cSocket::IPv4, "RCON"),
+ m_ListenThread6(*this, cSocket::IPv6, "RCON")
{
}
@@ -154,7 +154,7 @@ void cRCONServer::OnConnectionAccepted(cSocket & a_Socket)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cRCONServer::cConnection:
cRCONServer::cConnection::cConnection(cRCONServer & a_RCONServer, cSocket & a_Socket) :
diff --git a/src/Root.cpp b/src/Root.cpp
index c82b05a66..ee0d9b835 100644
--- a/src/Root.cpp
+++ b/src/Root.cpp
@@ -18,6 +18,7 @@
#include "CommandOutput.h"
#include "DeadlockDetect.h"
#include "OSSupport/Timer.h"
+#include "LoggerListeners.h"
#include "inifile/iniFile.h"
@@ -30,8 +31,6 @@
#include <mach/mach.h>
#endif
-extern bool g_TERMINATE_EVENT_RAISED;
-
@@ -53,7 +52,6 @@ cRoot::cRoot(void) :
m_FurnaceRecipe(NULL),
m_WebAdmin(NULL),
m_PluginManager(NULL),
- m_Log(NULL),
m_bStop(false),
m_bRestart(false)
{
@@ -79,17 +77,17 @@ void cRoot::InputThread(void * a_Params)
cLogCommandOutputCallback Output;
- while (!self.m_bStop && !self.m_bRestart && !g_TERMINATE_EVENT_RAISED && std::cin.good())
+ while (!self.m_bStop && !self.m_bRestart && !m_TerminateEventRaised && std::cin.good())
{
AString Command;
std::getline(std::cin, Command);
if (!Command.empty())
- {
+ {
self.ExecuteConsoleCommand(TrimString(Command), Output);
}
}
- if (g_TERMINATE_EVENT_RAISED || !std::cin.good())
+ if (m_TerminateEventRaised || !std::cin.good())
{
// We have come here because the std::cin has received an EOF / a terminate signal has been sent, and the server is still running; stop the server:
self.m_bStop = true;
@@ -105,12 +103,17 @@ void cRoot::Start(void)
#ifdef _WIN32
HWND hwnd = GetConsoleWindow();
HMENU hmenu = GetSystemMenu(hwnd, FALSE);
- EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling
+ EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling
#endif
+
+ cLogger::cListener * consoleLogListener = MakeConsoleListener();
+ cLogger::cListener * fileLogListener = new cFileListener();
+ cLogger::GetInstance().AttachListener(consoleLogListener);
+ cLogger::GetInstance().AttachListener(fileLogListener);
+
+ LOG("--- Started Log ---\n");
cDeadlockDetect dd;
- delete m_Log;
- m_Log = new cMCLogger();
m_bStop = false;
while (!m_bStop)
@@ -147,6 +150,7 @@ void cRoot::Start(void)
}
LOG("Starting server...");
+ m_MojangAPI.Start(IniFile); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init
if (!m_Server->InitServer(IniFile))
{
LOGERROR("Failure starting server, aborting...");
@@ -193,8 +197,8 @@ void cRoot::Start(void)
#if !defined(ANDROID_NDK)
LOGD("Starting InputThread...");
- m_InputThread = new cThread( InputThread, this, "cRoot::InputThread" );
- m_InputThread->Start( false ); // We should NOT wait? Otherwise we can't stop the server from other threads than the input thread
+ m_InputThread = new cThread( InputThread, this, "cRoot::InputThread");
+ m_InputThread->Start( false); // We should NOT wait? Otherwise we can't stop the server from other threads than the input thread
#endif
long long finishmseconds = Time.GetNowTime();
@@ -202,15 +206,15 @@ void cRoot::Start(void)
LOG("Startup complete, took %lld ms!", finishmseconds);
#ifdef _WIN32
- EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED); // Re-enable close button
+ EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED); // Re-enable close button
#endif
- while (!m_bStop && !m_bRestart && !g_TERMINATE_EVENT_RAISED) // These are modified by external threads
+ while (!m_bStop && !m_bRestart && !m_TerminateEventRaised) // These are modified by external threads
{
cSleep::MilliSleep(1000);
}
- if (g_TERMINATE_EVENT_RAISED)
+ if (m_TerminateEventRaised)
{
m_bStop = true;
}
@@ -250,8 +254,13 @@ void cRoot::Start(void)
delete m_Server; m_Server = NULL;
LOG("Shutdown successful!");
}
-
- delete m_Log; m_Log = NULL;
+
+ LOG("--- Stopped Log ---");
+
+ cLogger::GetInstance().DetachListener(consoleLogListener);
+ delete consoleLogListener;
+ cLogger::GetInstance().DetachListener(fileLogListener);
+ delete fileLogListener;
}
@@ -271,32 +280,32 @@ void cRoot::LoadWorlds(cIniFile & IniFile)
{
// First get the default world
AString DefaultWorldName = IniFile.GetValueSet("Worlds", "DefaultWorld", "world");
- m_pDefaultWorld = new cWorld( DefaultWorldName.c_str() );
+ m_pDefaultWorld = new cWorld(DefaultWorldName.c_str());
m_WorldsByName[ DefaultWorldName ] = m_pDefaultWorld;
// Then load the other worlds
- unsigned int KeyNum = IniFile.FindKey("Worlds");
- unsigned int NumWorlds = IniFile.GetNumValues( KeyNum );
+ int KeyNum = IniFile.FindKey("Worlds");
+ int NumWorlds = IniFile.GetNumValues(KeyNum);
if (NumWorlds <= 0)
{
return;
}
bool FoundAdditionalWorlds = false;
- for (unsigned int i = 0; i < NumWorlds; i++)
+ for (int i = 0; i < NumWorlds; i++)
{
- AString ValueName = IniFile.GetValueName(KeyNum, i );
+ AString ValueName = IniFile.GetValueName(KeyNum, i);
if (ValueName.compare("World") != 0)
{
continue;
}
- AString WorldName = IniFile.GetValue(KeyNum, i );
+ AString WorldName = IniFile.GetValue(KeyNum, i);
if (WorldName.empty())
{
continue;
}
FoundAdditionalWorlds = true;
- cWorld* NewWorld = new cWorld( WorldName.c_str() );
+ cWorld* NewWorld = new cWorld( WorldName.c_str());
m_WorldsByName[ WorldName ] = NewWorld;
} // for i - Worlds
@@ -314,13 +323,15 @@ void cRoot::LoadWorlds(cIniFile & IniFile)
-cWorld * cRoot::CreateAndInitializeWorld(const AString & a_WorldName)
+cWorld * cRoot::CreateAndInitializeWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_OverworldName)
{
- if (m_WorldsByName[a_WorldName] != NULL)
+ cWorld * World = m_WorldsByName[a_WorldName];
+ if (World != NULL)
{
- return NULL;
+ return World;
}
- cWorld* NewWorld = new cWorld(a_WorldName.c_str());
+
+ cWorld * NewWorld = new cWorld(a_WorldName.c_str(), a_Dimension, a_OverworldName);
m_WorldsByName[a_WorldName] = NewWorld;
NewWorld->Start();
NewWorld->InitializeSpawn();
@@ -361,7 +372,7 @@ void cRoot::StopWorlds(void)
void cRoot::UnloadWorlds(void)
{
m_pDefaultWorld = NULL;
- for( WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr )
+ for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
{
delete itr->second;
}
@@ -372,7 +383,7 @@ void cRoot::UnloadWorlds(void)
-cWorld* cRoot::GetDefaultWorld()
+cWorld * cRoot::GetDefaultWorld()
{
return m_pDefaultWorld;
}
@@ -381,12 +392,19 @@ cWorld* cRoot::GetDefaultWorld()
-cWorld* cRoot::GetWorld( const AString & a_WorldName )
+cWorld * cRoot::GetWorld(const AString & a_WorldName, bool a_SearchForFolder)
{
- WorldMap::iterator itr = m_WorldsByName.find( a_WorldName );
- if( itr != m_WorldsByName.end() )
+ WorldMap::iterator itr = m_WorldsByName.find(a_WorldName);
+ if (itr != m_WorldsByName.end())
+ {
return itr->second;
- return 0;
+ }
+
+ if (a_SearchForFolder && cFile::IsFolder(FILE_IO_PREFIX + a_WorldName))
+ {
+ return CreateAndInitializeWorld(a_WorldName);
+ }
+ return NULL;
}
@@ -398,9 +416,12 @@ bool cRoot::ForEachWorld(cWorldListCallback & a_Callback)
for (WorldMap::iterator itr = m_WorldsByName.begin(), itr2 = itr; itr != m_WorldsByName.end(); itr = itr2)
{
++itr2;
- if (a_Callback.Item(itr->second))
+ if (itr->second != NULL)
{
- return false;
+ if (a_Callback.Item(itr->second))
+ {
+ return false;
+ }
}
}
return true;
@@ -499,9 +520,9 @@ void cRoot::KickUser(int a_ClientID, const AString & a_Reason)
-void cRoot::AuthenticateUser(int a_ClientID, const AString & a_Name, const AString & a_UUID)
+void cRoot::AuthenticateUser(int a_ClientID, const AString & a_Name, const AString & a_UUID, const Json::Value & a_Properties)
{
- m_Server->AuthenticateUser(a_ClientID, a_Name, a_UUID);
+ m_Server->AuthenticateUser(a_ClientID, a_Name, a_UUID, a_Properties);
}
@@ -511,7 +532,7 @@ void cRoot::AuthenticateUser(int a_ClientID, const AString & a_Name, const AStri
int cRoot::GetTotalChunkCount(void)
{
int res = 0;
- for ( WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr )
+ for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end(); ++itr)
{
res += itr->second->GetNumChunks();
}
@@ -607,7 +628,7 @@ bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallbac
m_BestRating = Rating;
++m_NumMatches;
}
- if (Rating == m_NameLength) // Perfect match
+ if (Rating == m_NameLength) // Perfect match
{
return true;
}
@@ -687,7 +708,7 @@ int cRoot::GetVirtualRAMUsage(void)
&t_info_count
))
{
- return (int)(t_info.virtual_size / 1024);
+ return (int)(t_info.virtual_size / 1024);
}
return -1;
#else
@@ -739,7 +760,7 @@ int cRoot::GetPhysicalRAMUsage(void)
&t_info_count
))
{
- return (int)(t_info.resident_size / 1024);
+ return (int)(t_info.resident_size / 1024);
}
return -1;
#else
diff --git a/src/Root.h b/src/Root.h
index d2a4d1eed..6840efcbe 100644
--- a/src/Root.h
+++ b/src/Root.h
@@ -2,6 +2,7 @@
#pragma once
#include "Protocol/Authenticator.h"
+#include "Protocol/MojangAPI.h"
#include "HTTPServer/HTTPServer.h"
#include "Defines.h"
@@ -26,25 +27,45 @@ class cCompositeChat;
typedef cItemCallback<cPlayer> cPlayerListCallback;
typedef cItemCallback<cWorld> cWorldListCallback;
+namespace Json
+{
+ class Value;
+}
+
/// The root of the object hierarchy
-class cRoot // tolua_export
-{ // tolua_export
+// tolua_begin
+class cRoot
+{
public:
- static cRoot * Get() { return s_Root; } // tolua_export
+ static bool m_TerminateEventRaised;
+
+ static cRoot * Get() { return s_Root; }
+ // tolua_end
cRoot(void);
~cRoot();
void Start(void);
- cServer * GetServer(void) { return m_Server; } // tolua_export
- cWorld * GetDefaultWorld(void); // tolua_export
- cWorld * GetWorld(const AString & a_WorldName); // tolua_export
- cWorld * CreateAndInitializeWorld(const AString & a_WorldName); // tolua_export
+ // tolua_begin
+ cServer * GetServer(void) { return m_Server; }
+ cWorld * GetDefaultWorld(void);
+
+ /** Returns a pointer to the world specified
+ If no world of that name was currently loaded and a_SearchForFolder was true, it will consult cFile::IsFolder() to see if a world folder of that name exists and if so, initialise a world based on that name
+ */
+ cWorld * GetWorld(const AString & a_WorldName, bool a_SearchForFolder = false);
+
+ /** Returns a pointer to a world of specified name - will search loaded worlds first, then create anew if not found
+ The dimension parameter is used to create a world with a specific dimension
+ a_OverworldName should be set for non-overworld dimensions if one wishes that world to link back to an overworld via portals
+ */
+ cWorld * CreateAndInitializeWorld(const AString & a_WorldName, eDimension a_Dimension = dimOverworld, const AString & a_OverworldName = "");
+ // tolua_end
/// Calls the callback for each world; returns true if the callback didn't abort (return true)
bool ForEachWorld(cWorldListCallback & a_Callback); // >> Exported in ManualBindings <<
@@ -67,6 +88,7 @@ public:
cWebAdmin * GetWebAdmin (void) { return m_WebAdmin; } // tolua_export
cPluginManager * GetPluginManager (void) { return m_PluginManager; } // tolua_export
cAuthenticator & GetAuthenticator (void) { return m_Authenticator; }
+ cMojangAPI & GetMojangAPI (void) { return m_MojangAPI; }
/** Queues a console command for execution through the cServer class.
The command will be executed in the tick thread
@@ -89,7 +111,7 @@ public:
void KickUser(int a_ClientID, const AString & a_Reason);
/// Called by cAuthenticator to auth the specified user
- void AuthenticateUser(int a_ClientID, const AString & a_Name, const AString & a_UUID);
+ void AuthenticateUser(int a_ClientID, const AString & a_Name, const AString & a_UUID, const Json::Value & a_Properties);
/// Executes commands queued in the command queue
void TickCommands(void);
@@ -101,13 +123,13 @@ public:
void SaveAllChunks(void); // tolua_export
/// Reloads all the groups
- void ReloadGroups(void); // tolua_export
+ void ReloadGroups(void); // tolua_export
/// Calls the callback for each player in all worlds
- bool ForEachPlayer(cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
+ bool ForEachPlayer(cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
/// Finds a player from a partial or complete player name and calls the callback - case-insensitive
- bool FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
+ bool FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
// tolua_begin
@@ -171,10 +193,9 @@ private:
cWebAdmin * m_WebAdmin;
cPluginManager * m_PluginManager;
cAuthenticator m_Authenticator;
+ cMojangAPI m_MojangAPI;
cHTTPServer m_HTTPServer;
- cMCLogger * m_Log;
-
bool m_bStop;
bool m_bRestart;
@@ -197,8 +218,8 @@ private:
static void InputThread(void* a_Params);
- static cRoot* s_Root;
-}; // tolua_export
+ static cRoot* s_Root;
+}; // tolua_export
diff --git a/src/Scoreboard.cpp b/src/Scoreboard.cpp
index 250f63aa9..def952029 100644
--- a/src/Scoreboard.cpp
+++ b/src/Scoreboard.cpp
@@ -45,7 +45,8 @@ AString cObjective::TypeToString(eType a_Type)
cObjective::eType cObjective::StringToType(const AString & a_Name)
{
- static struct {
+ static struct
+ {
eType m_Type;
const char * m_String;
} TypeMap [] =
@@ -197,15 +198,18 @@ void cObjective::SendTo(cClientHandle & a_Client)
-cTeam::cTeam(const AString & a_Name, const AString & a_DisplayName,
- const AString & a_Prefix, const AString & a_Suffix)
+cTeam::cTeam(
+ const AString & a_Name, const AString & a_DisplayName,
+ const AString & a_Prefix, const AString & a_Suffix
+)
: m_AllowsFriendlyFire(true)
, m_CanSeeFriendlyInvisible(false)
, m_DisplayName(a_DisplayName)
, m_Name(a_Name)
, m_Prefix(a_Prefix)
, m_Suffix(a_Suffix)
-{}
+{
+}
diff --git a/src/Scoreboard.h b/src/Scoreboard.h
index 1e1973a10..f53b8c803 100644
--- a/src/Scoreboard.h
+++ b/src/Scoreboard.h
@@ -118,7 +118,7 @@ private:
friend class cScoreboardSerializer;
-}; // tolua_export
+}; // tolua_export
@@ -197,7 +197,7 @@ private:
friend class cScoreboardSerializer;
-}; // tolua_export
+}; // tolua_export
@@ -259,25 +259,22 @@ public:
/** Send this scoreboard to the specified client */
void SendTo(cClientHandle & a_Client);
- cTeam * QueryPlayerTeam(const AString & a_Name); // WARNING: O(n logn)
+ cTeam * QueryPlayerTeam(const AString & a_Name); // WARNING: O(n logn)
- /** Execute callback for each objective with the specified type
- *
- * Returns true if all objectives processed, false if the callback aborted by returning true.
- */
+ /** Execute callback for each objective with the specified type
+ Returns true if all objectives processed, false if the callback aborted by returning true.
+ */
bool ForEachObjectiveWith(cObjective::eType a_Type, cObjectiveCallback& a_Callback);
/** Execute callback for each objective.
- *
- * Returns true if all objectives have been processed, false if the callback aborted by returning true.
- */
- bool ForEachObjective(cObjectiveCallback& a_Callback); // Exported in ManualBindings.cpp
+ Returns true if all objectives have been processed, false if the callback aborted by returning true.
+ */
+ bool ForEachObjective(cObjectiveCallback& a_Callback); // Exported in ManualBindings.cpp
/** Execute callback for each team.
- *
- * Returns true if all teams have been processed, false if the callback aborted by returning true.
- */
- bool ForEachTeam(cTeamCallback& a_Callback); // Exported in ManualBindings.cpp
+ Returns true if all teams have been processed, false if the callback aborted by returning true.
+ */
+ bool ForEachTeam(cTeamCallback& a_Callback); // Exported in ManualBindings.cpp
void SetDisplay(cObjective * a_Objective, eDisplaySlot a_Slot);
@@ -304,7 +301,7 @@ private:
friend class cScoreboardSerializer;
-}; // tolua_export
+}; // tolua_export
diff --git a/src/Server.cpp b/src/Server.cpp
index 2c695cc70..42ad133f1 100644
--- a/src/Server.cpp
+++ b/src/Server.cpp
@@ -30,7 +30,8 @@
#include <sstream>
#include <iostream>
-extern "C" {
+extern "C"
+{
#include "zlib/zlib.h"
}
@@ -60,7 +61,7 @@ typedef std::list< cClientHandle* > ClientList;
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cServer::cTickThread:
cServer::cTickThread::cTickThread(cServer & a_Server) :
@@ -101,12 +102,12 @@ void cServer::cTickThread::Execute(void)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cServer:
cServer::cServer(void) :
- m_ListenThreadIPv4(*this, cSocket::IPv4, "Client IPv4"),
- m_ListenThreadIPv6(*this, cSocket::IPv6, "Client IPv6"),
+ m_ListenThreadIPv4(*this, cSocket::IPv4, "Client"),
+ m_ListenThreadIPv6(*this, cSocket::IPv6, "Client"),
m_PlayerCount(0),
m_PlayerCountDiff(0),
m_ClientViewDistance(0),
@@ -202,7 +203,7 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
m_PlayerCount = 0;
m_PlayerCountDiff = 0;
- m_FaviconData = Base64Encode(cFile::ReadWholeFile(FILE_IO_PREFIX + AString("favicon.png"))); // Will return empty string if file nonexistant; client doesn't mind
+ m_FaviconData = Base64Encode(cFile::ReadWholeFile(FILE_IO_PREFIX + AString("favicon.png"))); // Will return empty string if file nonexistant; client doesn't mind
if (m_bIsConnected)
{
@@ -213,7 +214,7 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
LOGINFO("Compatible clients: %s", MCS_CLIENT_VERSIONS);
LOGINFO("Compatible protocol versions %s", MCS_PROTOCOL_VERSIONS);
- if (cSocket::WSAStartup() != 0) // Only does anything on Windows, but whatever
+ if (cSocket::WSAStartup() != 0) // Only does anything on Windows, but whatever
{
LOGERROR("WSAStartup() != 0");
return false;
@@ -258,6 +259,9 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
m_ServerID.resize(16, '0');
}
+ m_ShouldLoadOfflinePlayerData = a_SettingsIni.GetValueSetB("PlayerData", "LoadOfflinePlayerData", false);
+ m_ShouldLoadNamedPlayerData = a_SettingsIni.GetValueSetB("PlayerData", "LoadNamedPlayerData", true);
+
m_ClientViewDistance = a_SettingsIni.GetValueSetI("Server", "DefaultViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE);
if (m_ClientViewDistance < cClientHandle::MIN_VIEW_DISTANCE)
{
@@ -394,7 +398,7 @@ void cServer::TickClients(float a_Dt)
{
if ((*itr)->IsDestroyed())
{
- // Remove the client later, when CS is not held, to avoid deadlock ( http://forum.mc-server.org/showthread.php?tid=374 )
+ // Remove the client later, when CS is not held, to avoid deadlock: http://forum.mc-server.org/showthread.php?tid=374
RemoveClients.push_back(*itr);
itr = m_Clients.erase(itr);
continue;
@@ -408,7 +412,7 @@ void cServer::TickClients(float a_Dt)
for (cClientHandleList::iterator itr = RemoveClients.begin(); itr != RemoveClients.end(); ++itr)
{
delete *itr;
- } // for itr - RemoveClients[]
+ } // for itr - RemoveClients[]
}
@@ -627,7 +631,7 @@ void cServer::Shutdown(void)
cRoot::Get()->SaveAllChunks();
cCSLock Lock(m_CSClients);
- for( ClientList::iterator itr = m_Clients.begin(); itr != m_Clients.end(); ++itr )
+ for (ClientList::iterator itr = m_Clients.begin(); itr != m_Clients.end(); ++itr)
{
(*itr)->Destroy();
delete *itr;
@@ -655,14 +659,14 @@ void cServer::KickUser(int a_ClientID, const AString & a_Reason)
-void cServer::AuthenticateUser(int a_ClientID, const AString & a_Name, const AString & a_UUID)
+void cServer::AuthenticateUser(int a_ClientID, const AString & a_Name, const AString & a_UUID, const Json::Value & a_Properties)
{
cCSLock Lock(m_CSClients);
for (ClientList::iterator itr = m_Clients.begin(); itr != m_Clients.end(); ++itr)
{
if ((*itr)->GetUniqueID() == a_ClientID)
{
- (*itr)->Authenticate(a_Name, a_UUID);
+ (*itr)->Authenticate(a_Name, a_UUID, a_Properties);
return;
}
} // for itr - m_Clients[]
@@ -672,7 +676,7 @@ void cServer::AuthenticateUser(int a_ClientID, const AString & a_Name, const ASt
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cServer::cNotifyWriteThread:
cServer::cNotifyWriteThread::cNotifyWriteThread(void) :
diff --git a/src/Server.h b/src/Server.h
index 3d76c8ccf..c1640b388 100644
--- a/src/Server.h
+++ b/src/Server.h
@@ -37,18 +37,23 @@
class cPlayer;
class cClientHandle;
class cIniFile;
-class cCommandOutputCallback ;
+class cCommandOutputCallback;
typedef std::list<cClientHandle *> cClientHandleList;
+namespace Json
+{
+ class Value;
+}
-class cServer // tolua_export
+
+class cServer // tolua_export
: public cListenThread::cCallback
-{ // tolua_export
-public: // tolua_export
+{ // tolua_export
+public: // tolua_export
virtual ~cServer() {}
bool InitServer(cIniFile & a_SettingsIni);
@@ -58,12 +63,12 @@ public: // tolua_export
const AString & GetDescription(void) const {return m_Description; }
// Player counts:
- int GetMaxPlayers(void) const {return m_MaxPlayers; }
+ int GetMaxPlayers(void) const { return m_MaxPlayers; }
int GetNumPlayers(void) const;
void SetMaxPlayers(int a_MaxPlayers) { m_MaxPlayers = a_MaxPlayers; }
// Hardcore mode or not:
- bool IsHardcore(void) const {return m_bIsHardcore; }
+ bool IsHardcore(void) const { return m_bIsHardcore; }
// tolua_end
@@ -83,7 +88,9 @@ public: // tolua_export
void Shutdown(void);
void KickUser(int a_ClientID, const AString & a_Reason);
- void AuthenticateUser(int a_ClientID, const AString & a_Name, const AString & a_UUID); // Called by cAuthenticator to auth the specified user
+
+ /** Authenticates the specified user, called by cAuthenticator */
+ void AuthenticateUser(int a_ClientID, const AString & a_Name, const AString & a_UUID, const Json::Value & a_Properties);
const AString & GetServerID(void) const { return m_ServerID; } // tolua_export
@@ -112,11 +119,21 @@ public: // tolua_export
cRsaPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
const AString & GetPublicKeyDER(void) const { return m_PublicKeyDER; }
+ /** Returns true if authentication has been turned on in server settings. */
bool ShouldAuthenticate(void) const { return m_ShouldAuthenticate; }
+ /** Returns true if offline UUIDs should be used to load data for players whose normal UUIDs cannot be found.
+ Loaded from the settings.ini [PlayerData].LoadOfflinePlayerData setting. */
+ bool ShouldLoadOfflinePlayerData(void) const { return m_ShouldLoadOfflinePlayerData; }
+
+ /** Returns true if old-style playernames should be used to load data for players whose regular datafiles cannot be found.
+ This allows a seamless transition from name-based to UUID-based player storage.
+ Loaded from the settings.ini [PlayerData].LoadNamedPlayerData setting. */
+ bool ShouldLoadNamedPlayerData(void) const { return m_ShouldLoadNamedPlayerData; }
+
private:
- friend class cRoot; // so cRoot can create and destroy cServer
+ friend class cRoot; // so cRoot can create and destroy cServer
/** When NotifyClientWrite() is called, it is queued for this thread to process (to avoid deadlocks between cSocketThreads, cClientHandle and cChunkMap) */
class cNotifyWriteThread :
@@ -132,7 +149,7 @@ private:
virtual void Execute(void);
- public:
+ public:
cNotifyWriteThread(void);
~cNotifyWriteThread();
@@ -177,7 +194,7 @@ private:
int m_ClientViewDistance; // The default view distance for clients; settable in Settings.ini
- bool m_bIsConnected; // true - connected false - not connected
+ bool m_bIsConnected; // true - connected false - not connected
bool m_bRestarting;
@@ -204,6 +221,16 @@ private:
This setting is the same as the "online-mode" setting in Vanilla. */
bool m_ShouldAuthenticate;
+ /** True if offline UUIDs should be used to load data for players whose normal UUIDs cannot be found.
+ This allows transitions from an offline (no-auth) server to an online one.
+ Loaded from the settings.ini [PlayerData].LoadOfflinePlayerData setting. */
+ bool m_ShouldLoadOfflinePlayerData;
+
+ /** True if old-style playernames should be used to load data for players whose regular datafiles cannot be found.
+ This allows a seamless transition from name-based to UUID-based player storage.
+ Loaded from the settings.ini [PlayerData].LoadNamedPlayerData setting. */
+ bool m_ShouldLoadNamedPlayerData;
+
cServer(void);
@@ -217,7 +244,7 @@ private:
// cListenThread::cCallback overrides:
virtual void OnConnectionAccepted(cSocket & a_Socket) override;
-}; // tolua_export
+}; // tolua_export
diff --git a/src/SetChunkData.cpp b/src/SetChunkData.cpp
new file mode 100644
index 000000000..6e0c2733e
--- /dev/null
+++ b/src/SetChunkData.cpp
@@ -0,0 +1,115 @@
+
+// SetChunkData.cpp
+
+// Implements the cSetChunkData class used for sending loaded / generated chunk
+
+#include "Globals.h"
+#include "SetChunkData.h"
+
+
+
+
+
+cSetChunkData::cSetChunkData(int a_ChunkX, int a_ChunkZ, bool a_ShouldMarkDirty) :
+ m_ChunkX(a_ChunkX),
+ m_ChunkZ(a_ChunkZ),
+ m_ShouldMarkDirty(a_ShouldMarkDirty)
+{
+}
+
+
+
+
+
+cSetChunkData::cSetChunkData(
+ int a_ChunkX, int a_ChunkZ,
+ const BLOCKTYPE * a_BlockTypes,
+ const NIBBLETYPE * a_BlockMetas,
+ const NIBBLETYPE * a_BlockLight,
+ const NIBBLETYPE * a_SkyLight,
+ const cChunkDef::HeightMap * a_HeightMap,
+ const cChunkDef::BiomeMap * a_Biomes,
+ cEntityList & a_Entities,
+ cBlockEntityList & a_BlockEntities,
+ bool a_ShouldMarkDirty
+) :
+ m_ChunkX(a_ChunkX),
+ m_ChunkZ(a_ChunkZ),
+ m_ShouldMarkDirty(a_ShouldMarkDirty)
+{
+ // Check the params' validity:
+ ASSERT(a_BlockTypes != NULL);
+ ASSERT(a_BlockMetas != NULL);
+ ASSERT(a_Biomes != NULL);
+
+ // Copy block types and metas:
+ memcpy(m_BlockTypes, a_BlockTypes, sizeof(cChunkDef::BlockTypes));
+ memcpy(m_BlockMetas, a_BlockMetas, sizeof(cChunkDef::BlockNibbles));
+
+ // Copy lights, if both given:
+ if ((a_BlockLight != NULL) && (a_SkyLight != NULL))
+ {
+ memcpy(m_BlockLight, a_BlockLight, sizeof(m_BlockLight));
+ memcpy(m_SkyLight, a_SkyLight, sizeof(m_SkyLight));
+ m_IsLightValid = true;
+ }
+ else
+ {
+ m_IsLightValid = false;
+ }
+
+ // Copy the heightmap, if available:
+ if (a_HeightMap != NULL)
+ {
+ memcpy(m_HeightMap, a_HeightMap, sizeof(m_HeightMap));
+ m_IsHeightMapValid = true;
+ }
+ else
+ {
+ m_IsHeightMapValid = false;
+ }
+
+ // Copy biomes, if available:
+ if (a_Biomes != NULL)
+ {
+ memcpy(m_Biomes, a_Biomes, sizeof(m_Biomes));
+ m_AreBiomesValid = true;
+ }
+ else
+ {
+ m_AreBiomesValid = false;
+ }
+
+ // Move entities and blockentities:
+ std::swap(m_Entities, a_Entities);
+ std::swap(m_BlockEntities, a_BlockEntities);
+}
+
+
+
+
+
+void cSetChunkData::CalculateHeightMap(void)
+{
+ for (int x = 0; x < cChunkDef::Width; x++)
+ {
+ for (int z = 0; z < cChunkDef::Width; z++)
+ {
+ for (int y = cChunkDef::Height - 1; y > -1; y--)
+ {
+ int index = cChunkDef::MakeIndexNoCheck(x, y, z);
+ if (m_BlockTypes[index] != E_BLOCK_AIR)
+ {
+ m_HeightMap[x + z * cChunkDef::Width] = (HEIGHTTYPE)y;
+ break;
+ }
+ } // for y
+ } // for z
+ } // for x
+ m_IsHeightMapValid = true;
+}
+
+
+
+
+
diff --git a/src/SetChunkData.h b/src/SetChunkData.h
new file mode 100644
index 000000000..a2f776f6b
--- /dev/null
+++ b/src/SetChunkData.h
@@ -0,0 +1,120 @@
+
+// SetChunkData.h
+
+// Declares the cSetChunkData class used for sending loaded / generated chunk data into cWorld
+
+
+
+
+
+#pragma once
+
+
+
+
+
+class cSetChunkData
+{
+public:
+ /** Constructs a new instance with empty data.
+ Allocates new buffers for the block data.
+ Prefer to use this constructor, then fill the object with data and then send it to cWorld, as this will
+ reduce the copying required to queue the set operation. */
+ cSetChunkData(int a_ChunkX, int a_ChunkZ, bool a_ShouldMarkDirty);
+
+ /** Constructs a new instance based on data existing elsewhere, will copy all the memory. Prefer to use the
+ other constructor as much as possible.
+ Will move the entity and blockentity lists into the internal storage, and empty the a_Entities and
+ a_BlockEntities lists.
+ a_BlockTypes and a_BlockMetas must always be valid.
+ If either of the light arrays are NULL, the chunk data will be marked as not having any light at all and
+ will be scheduled for re-lighting once it is set into the chunkmap.
+ If a_Biomes is not valid, the internal flag is set and the world will calculate the biomes using the chunk
+ generator when setting the chunk data.
+ If a_HeightMap is not assigned, the world will calculate the heightmap based on the blocktypes when setting
+ the chunk data. */
+ cSetChunkData(
+ int a_ChunkX, int a_ChunkZ,
+ const BLOCKTYPE * a_BlockTypes,
+ const NIBBLETYPE * a_BlockMetas,
+ const NIBBLETYPE * a_BlockLight,
+ const NIBBLETYPE * a_SkyLight,
+ const cChunkDef::HeightMap * a_HeightMap,
+ const cChunkDef::BiomeMap * a_Biomes,
+ cEntityList & a_Entities,
+ cBlockEntityList & a_BlockEntities,
+ bool a_ShouldMarkDirty
+ );
+
+ int GetChunkX(void) const { return m_ChunkX; }
+ int GetChunkZ(void) const { return m_ChunkZ; }
+
+ /** Returns the internal storage of the block types, read-only. */
+ const cChunkDef::BlockTypes & GetBlockTypes(void) const { return m_BlockTypes; }
+
+ /** Returns the internal storage of the block types, read-only. */
+ const cChunkDef::BlockNibbles & GetBlockMetas(void) const { return m_BlockMetas; }
+
+ /** Returns the internal storage of the block light, read-only. */
+ const cChunkDef::BlockNibbles & GetBlockLight(void) const { return m_BlockLight; }
+
+ /** Returns the internal storage of the block types, read-only. */
+ const cChunkDef::BlockNibbles & GetSkyLight(void) const { return m_SkyLight; }
+
+ /** Returns the internal storage for heightmap, read-only. */
+ const cChunkDef::HeightMap & GetHeightMap(void) const { return m_HeightMap; }
+
+ /** Returns the internal storage for biomes, read-write. */
+ cChunkDef::BiomeMap & GetBiomes(void) { return m_Biomes; }
+
+ /** Returns the internal storage for entities, read-write. */
+ cEntityList & GetEntities(void) { return m_Entities; }
+
+ /** Returns the internal storage for block entities, read-write. */
+ cBlockEntityList & GetBlockEntities(void) { return m_BlockEntities; }
+
+ /** Returns whether both light arrays stored in this object are valid. */
+ bool IsLightValid(void) const { return m_IsLightValid; }
+
+ /** Returns whether the heightmap stored in this object is valid. */
+ bool IsHeightMapValid(void) const { return m_IsHeightMapValid; }
+
+ /** Returns whether the biomes stored in this object are valid. */
+ bool AreBiomesValid(void) const { return m_AreBiomesValid; }
+
+ /** Returns whether the chunk should be marked as dirty after its data is set.
+ Used by the generator to save chunks after generating. */
+ bool ShouldMarkDirty(void) const { return m_ShouldMarkDirty; }
+
+ /** Marks the biomes stored in this object as valid. */
+ void MarkBiomesValid(void) { m_AreBiomesValid = true; }
+
+ /** Calculates the heightmap based on the contained blocktypes and marks it valid. */
+ void CalculateHeightMap(void);
+
+protected:
+ int m_ChunkX;
+ int m_ChunkZ;
+
+ cChunkDef::BlockTypes m_BlockTypes;
+ cChunkDef::BlockNibbles m_BlockMetas;
+ cChunkDef::BlockNibbles m_BlockLight;
+ cChunkDef::BlockNibbles m_SkyLight;
+ cChunkDef::HeightMap m_HeightMap;
+ cChunkDef::BiomeMap m_Biomes;
+ cEntityList m_Entities;
+ cBlockEntityList m_BlockEntities;
+
+ bool m_IsLightValid;
+ bool m_IsHeightMapValid;
+ bool m_AreBiomesValid;
+ bool m_ShouldMarkDirty;
+};
+
+typedef SharedPtr<cSetChunkData> cSetChunkDataPtr; // TODO: Change to unique_ptr once we go C++11
+typedef std::vector<cSetChunkDataPtr> cSetChunkDataPtrs;
+
+
+
+
+
diff --git a/src/Simulator/CMakeLists.txt b/src/Simulator/CMakeLists.txt
index b2a29d45c..521b145b6 100644
--- a/src/Simulator/CMakeLists.txt
+++ b/src/Simulator/CMakeLists.txt
@@ -4,9 +4,34 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ DelayedFluidSimulator.cpp
+ FireSimulator.cpp
+ FloodyFluidSimulator.cpp
+ FluidSimulator.cpp
+ IncrementalRedstoneSimulator.cpp
+ RedstoneSimulator.cpp
+ SandSimulator.cpp
+ Simulator.cpp
+ SimulatorManager.cpp
+ VanillaFluidSimulator.cpp
+ VaporizeFluidSimulator.cpp)
-add_library(Simulator ${SOURCE})
+SET (HDRS
+ DelayedFluidSimulator.h
+ FireSimulator.h
+ FloodyFluidSimulator.h
+ FluidSimulator.h
+ IncrementalRedstoneSimulator.h
+ NoopFluidSimulator.h
+ NoopRedstoneSimulator.h
+ RedstoneSimulator.h
+ SandSimulator.h
+ Simulator.h
+ SimulatorManager.h
+ VanillaFluidSimulator.h
+ VaporizeFluidSimulator.h)
+
+if(NOT MSVC)
+ add_library(Simulator ${SRCS} ${HDRS})
+endif()
diff --git a/src/Simulator/DelayedFluidSimulator.cpp b/src/Simulator/DelayedFluidSimulator.cpp
index 5ff736231..59ea51aa0 100644
--- a/src/Simulator/DelayedFluidSimulator.cpp
+++ b/src/Simulator/DelayedFluidSimulator.cpp
@@ -14,7 +14,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cDelayedFluidSimulatorChunkData::cSlot
bool cDelayedFluidSimulatorChunkData::cSlot::Add(int a_RelX, int a_RelY, int a_RelZ)
@@ -40,7 +40,7 @@ bool cDelayedFluidSimulatorChunkData::cSlot::Add(int a_RelX, int a_RelY, int a_R
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cDelayedFluidSimulatorChunkData:
cDelayedFluidSimulatorChunkData::cDelayedFluidSimulatorChunkData(int a_TickDelay) :
@@ -62,7 +62,7 @@ cDelayedFluidSimulatorChunkData::~cDelayedFluidSimulatorChunkData()
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cDelayedFluidSimulator:
cDelayedFluidSimulator::cDelayedFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, int a_TickDelay) :
@@ -131,7 +131,7 @@ void cDelayedFluidSimulator::Simulate(float a_Dt)
void cDelayedFluidSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
-{
+{
void * ChunkDataRaw = (m_FluidBlock == E_BLOCK_WATER) ? a_Chunk->GetWaterSimulatorData() : a_Chunk->GetLavaSimulatorData();
cDelayedFluidSimulatorChunkData * ChunkData = (cDelayedFluidSimulatorChunkData *)ChunkDataRaw;
cDelayedFluidSimulatorChunkData::cSlot & Slot = ChunkData->m_Slots[m_SimSlotNum];
diff --git a/src/Simulator/DelayedFluidSimulator.h b/src/Simulator/DelayedFluidSimulator.h
index c81500741..8a6c26c7a 100644
--- a/src/Simulator/DelayedFluidSimulator.h
+++ b/src/Simulator/DelayedFluidSimulator.h
@@ -50,7 +50,7 @@ class cDelayedFluidSimulator :
{
typedef cFluidSimulator super;
-public:
+public:
cDelayedFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, int a_TickDelay);
// cSimulator overrides:
@@ -70,7 +70,7 @@ protected:
/*
Slots:
| 0 | 1 | ... | m_AddSlotNum | m_SimSlotNum | ... | m_TickDelay - 1 |
- adding blocks here ^ | ^ simulating here
+ | adding blocks here ^ | ^ simulating here
*/
/// Called from SimulateChunk() to simulate each block in one slot of blocks. Descendants override this method to provide custom simulation.
diff --git a/src/Simulator/FireSimulator.cpp b/src/Simulator/FireSimulator.cpp
index 311f8b4c4..cdb5abde2 100644
--- a/src/Simulator/FireSimulator.cpp
+++ b/src/Simulator/FireSimulator.cpp
@@ -63,7 +63,7 @@ static const struct
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFireSimulator:
cFireSimulator::cFireSimulator(cWorld & a_World, cIniFile & a_IniFile) :
@@ -98,7 +98,7 @@ void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChun
int x = itr->x;
int y = itr->y;
int z = itr->z;
- BLOCKTYPE BlockType = a_Chunk->GetBlock(x,y,z);
+ BLOCKTYPE BlockType = a_Chunk->GetBlock(x, y, z);
if (!IsAllowedBlock(BlockType))
{
@@ -140,7 +140,7 @@ void cFireSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChun
continue;
}
- if((itr->y > 0) && (!DoesBurnForever(a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z))))
+ if ((itr->y > 0) && (!DoesBurnForever(a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z))))
{
a_Chunk->SetMeta(x, y, z, BlockMeta + 1);
}
@@ -306,14 +306,14 @@ void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int
// No need to check the coords for equality with the parent block,
// it cannot catch fire anyway (because it's not an air block)
- if (m_World.GetTickRandomNumber(MAX_CHANCE_FLAMMABILITY) > m_Flammability)
+ if (m_World.GetTickRandomNumber(MAX_CHANCE_FLAMMABILITY) > m_Flammability)
{
continue;
}
// Start the fire in the neighbor {x, y, z}
/*
- FLOG("FS: Trying to start fire at {%d, %d, %d}.",
+ FLOG("FS: Trying to start fire at {%d, %d, %d}.",
x + a_Chunk->GetPosX() * cChunkDef::Width, y, z + a_Chunk->GetPosZ() * cChunkDef::Width
);
*/
@@ -359,18 +359,26 @@ void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_Rel
continue;
}
+ int AbsX = (Neighbour->GetPosX() * cChunkDef::Width) + X;
+ int Y = a_RelY + gNeighborCoords[i].y;
+ int AbsZ = (Neighbour->GetPosZ() * cChunkDef::Width) + Z;
+
if (BlockType == E_BLOCK_TNT)
{
- int AbsX = X + Neighbour->GetPosX() * cChunkDef::Width;
- int AbsZ = Z + Neighbour->GetPosZ() * cChunkDef::Width;
-
- m_World.SpawnPrimedTNT(AbsX, a_RelY + gNeighborCoords[i].y, AbsZ, 0);
- Neighbour->SetBlock(X, a_RelY + gNeighborCoords[i].y, Z, E_BLOCK_AIR, 0);
+ m_World.SpawnPrimedTNT(AbsX, Y, AbsZ, 0);
+ Neighbour->SetBlock(X, a_RelY + Y, Z, E_BLOCK_AIR, 0);
return;
}
bool ShouldReplaceFuel = (m_World.GetTickRandomNumber(MAX_CHANCE_REPLACE_FUEL) < m_ReplaceFuelChance);
- Neighbour->SetBlock(X, a_RelY + gNeighborCoords[i].y, Z, ShouldReplaceFuel ? E_BLOCK_FIRE : E_BLOCK_AIR, 0);
+ if (ShouldReplaceFuel && !cRoot::Get()->GetPluginManager()->CallHookBlockSpread(&m_World, AbsX, Y, AbsZ, ssFireSpread))
+ {
+ Neighbour->SetBlock(X, Y, Z, E_BLOCK_FIRE, 0);
+ }
+ else
+ {
+ Neighbour->SetBlock(X, Y, Z, E_BLOCK_AIR, 0);
+ }
} // for i - Coords[]
}
diff --git a/src/Simulator/FloodyFluidSimulator.cpp b/src/Simulator/FloodyFluidSimulator.cpp
index 4ffda2365..2c5c4b658 100644
--- a/src/Simulator/FloodyFluidSimulator.cpp
+++ b/src/Simulator/FloodyFluidSimulator.cpp
@@ -48,7 +48,7 @@ cFloodyFluidSimulator::cFloodyFluidSimulator(
void cFloodyFluidSimulator::SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
- FLOG("Simulating block {%d, %d, %d}: block %d, meta %d",
+ FLOG("Simulating block {%d, %d, %d}: block %d, meta %d",
a_Chunk->GetPosX() * cChunkDef::Width + a_RelX, a_RelY, a_Chunk->GetPosZ() * cChunkDef::Width + a_RelZ,
a_Chunk->GetBlock(a_RelX, a_RelY, a_RelZ),
a_Chunk->GetMeta(a_RelX, a_RelY, a_RelZ)
@@ -248,13 +248,13 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
{
// Lava flowing into water, change to stone / cobblestone based on direction:
BLOCKTYPE NewBlock = (a_NewMeta == 8) ? E_BLOCK_STONE : E_BLOCK_COBBLESTONE;
- FLOG(" Lava flowing into water, turning water at rel {%d, %d, %d} into stone",
+ FLOG(" Lava flowing into water, turning water at rel {%d, %d, %d} into stone",
a_RelX, a_RelY, a_RelZ,
ItemTypeToString(NewBlock).c_str()
);
a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);
- a_NearChunk->BroadcastSoundEffect("random.fizz", BlockX * 8, a_RelY * 8, BlockZ * 8, 0.5f, 1.5f);
+ a_NearChunk->BroadcastSoundEffect("random.fizz", (double)BlockX, (double)a_RelY, (double)BlockZ, 0.5f, 1.5f);
return;
}
}
@@ -264,12 +264,12 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
{
// Water flowing into lava, change to cobblestone / obsidian based on dest block:
BLOCKTYPE NewBlock = (BlockMeta == 0) ? E_BLOCK_OBSIDIAN : E_BLOCK_COBBLESTONE;
- FLOG(" Water flowing into lava, turning lava at rel {%d, %d, %d} into %s",
+ FLOG(" Water flowing into lava, turning lava at rel {%d, %d, %d} into %s",
a_RelX, a_RelY, a_RelZ, ItemTypeToString(NewBlock).c_str()
);
a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);
- a_NearChunk->BroadcastSoundEffect("random.fizz", BlockX * 8, a_RelY * 8, BlockZ * 8, 0.5f, 1.5f);
+ a_NearChunk->BroadcastSoundEffect("random.fizz", (double)BlockX, (double)a_RelY, (double)BlockZ, 0.5f, 1.5f);
return;
}
}
@@ -296,8 +296,8 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
ChunkInterface,
m_World,
PluginInterface,
- NULL,
- BlockX,
+ NULL,
+ BlockX,
a_RelY,
BlockZ
);
diff --git a/src/Simulator/FluidSimulator.cpp b/src/Simulator/FluidSimulator.cpp
index f64955cb2..58501326f 100644
--- a/src/Simulator/FluidSimulator.cpp
+++ b/src/Simulator/FluidSimulator.cpp
@@ -125,31 +125,31 @@ Direction cFluidSimulator::GetFlowingDirection(int a_X, int a_Y, int a_Z, bool a
return NONE;
}
BLOCKTYPE BlockID = m_World.GetBlock(a_X, a_Y, a_Z);
- if (!IsAllowedBlock(BlockID)) // No Fluid -> No Flowing direction :D
+ if (!IsAllowedBlock(BlockID)) // No Fluid -> No Flowing direction :D
{
return NONE;
}
/*
Disabled because of causing problems and being useless atm
- char BlockBelow = m_World.GetBlock(a_X, a_Y - 1, a_Z); //If there is nothing or fluid below it -> dominating flow is down :D
+ char BlockBelow = m_World.GetBlock(a_X, a_Y - 1, a_Z); // If there is nothing or fluid below it -> dominating flow is down :D
if (BlockBelow == E_BLOCK_AIR || IsAllowedBlock(BlockBelow))
return Y_MINUS;
*/
- NIBBLETYPE LowestPoint = m_World.GetBlockMeta(a_X, a_Y, a_Z); //Current Block Meta so only lower points will be counted
- int X = 0, Z = 0; //Lowest Pos will be stored here
+ NIBBLETYPE LowestPoint = m_World.GetBlockMeta(a_X, a_Y, a_Z); // Current Block Meta so only lower points will be counted
+ int X = 0, Z = 0; // Lowest Pos will be stored here
- if (IsAllowedBlock(m_World.GetBlock(a_X, a_Y + 1, a_Z)) && a_Over) //check for upper block to flow because this also affects the flowing direction
+ if (IsAllowedBlock(m_World.GetBlock(a_X, a_Y + 1, a_Z)) && a_Over) // check for upper block to flow because this also affects the flowing direction
{
return GetFlowingDirection(a_X, a_Y + 1, a_Z, false);
}
std::vector< Vector3i * > Points;
- Points.reserve(4); //Already allocate 4 places :D
+ Points.reserve(4); // Already allocate 4 places :D
- //add blocks around the checking pos
+ // add blocks around the checking pos
Points.push_back(new Vector3i(a_X - 1, a_Y, a_Z));
Points.push_back(new Vector3i(a_X + 1, a_Y, a_Z));
Points.push_back(new Vector3i(a_X, a_Y, a_Z + 1));
@@ -159,20 +159,20 @@ Direction cFluidSimulator::GetFlowingDirection(int a_X, int a_Y, int a_Z, bool a
{
Vector3i *Pos = (*it);
char BlockID = m_World.GetBlock(Pos->x, Pos->y, Pos->z);
- if(IsAllowedBlock(BlockID))
+ if (IsAllowedBlock(BlockID))
{
char Meta = m_World.GetBlockMeta(Pos->x, Pos->y, Pos->z);
- if(Meta > LowestPoint)
+ if (Meta > LowestPoint)
{
LowestPoint = Meta;
X = Pos->x;
Z = Pos->z;
}
}
- else if(BlockID == E_BLOCK_AIR)
+ else if (BlockID == E_BLOCK_AIR)
{
- LowestPoint = 9; //This always dominates
+ LowestPoint = 9; // This always dominates
X = Pos->x;
Z = Pos->z;
diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp
index 5af9a295d..7b3a2c2fa 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.cpp
+++ b/src/Simulator/IncrementalRedstoneSimulator.cpp
@@ -3,10 +3,9 @@
#include "IncrementalRedstoneSimulator.h"
#include "BoundingBox.h"
-#include "../BlockEntities/DropSpenserEntity.h"
-#include "../BlockEntities/NoteEntity.h"
+#include "../BlockEntities/RedstonePoweredEntity.h"
+#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
-#include "../Entities/TNTEntity.h"
#include "../Entities/Pickup.h"
#include "../Blocks/BlockTorch.h"
#include "../Blocks/BlockDoor.h"
@@ -15,8 +14,6 @@
#include "../Blocks/BlockPiston.h"
#include "../Blocks/BlockTripwireHook.h"
-#define WAKE_SIMULATOR_IF_DIRTY(a_Chunk, a_BlockX, a_BlockY, a_BlockZ) if (a_Chunk->IsRedstoneDirty()) WakeUp(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
-
@@ -60,17 +57,19 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
// Use that Chunk pointer to get a relative position
int RelX = 0;
- int RelZ = 0;
+ int RelZ = 0;
BLOCKTYPE Block;
NIBBLETYPE Meta;
- cChunk * OtherChunk = a_Chunk;
if (a_OtherChunk != NULL)
{
RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width;
RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width;
a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta);
- OtherChunk = a_OtherChunk;
+
+ // If a_OtherChunk is passed (not NULL), it is the chunk that had a block change, and a_Chunk will be the neighbouring chunk of that block
+ // Because said neighbouring chunk does not know of this change but still needs to update its redstone, we set it to dirty
+ a_Chunk->SetIsRedstoneDirty(true);
}
else
{
@@ -95,8 +94,6 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
{
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
itr = PoweredBlocks->erase(itr);
- a_Chunk->SetIsRedstoneDirty(true);
- OtherChunk->SetIsRedstoneDirty(true);
continue;
}
else if (
@@ -105,34 +102,13 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) ||
((Block == E_BLOCK_DETECTOR_RAIL) && ((Meta & 0x08) == 0)) ||
(((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) ||
- (((Block == E_BLOCK_STONE_PRESSURE_PLATE) || (Block == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (Meta == 0)) ||
- (((Block == E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE) || (Block == E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE)) && (Meta == 0)) ||
((Block == E_BLOCK_TRIPWIRE_HOOK) && ((Meta & 0x08) == 0))
)
{
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
itr = PoweredBlocks->erase(itr);
- a_Chunk->SetIsRedstoneDirty(true);
- OtherChunk->SetIsRedstoneDirty(true);
continue;
}
- else if (Block == E_BLOCK_DAYLIGHT_SENSOR)
- {
- if (!m_World.IsChunkLighted(OtherChunk->GetPosX(), OtherChunk->GetPosZ()))
- {
- m_World.QueueLightChunk(OtherChunk->GetPosX(), OtherChunk->GetPosZ());
- }
- else
- {
- if (OtherChunk->GetTimeAlteredLight(OtherChunk->GetSkyLight(RelX, a_BlockY + 1, RelZ)) <= 7)
- {
- itr = PoweredBlocks->erase(itr);
- a_Chunk->SetIsRedstoneDirty(true);
- OtherChunk->SetIsRedstoneDirty(true);
- continue;
- }
- }
- }
++itr;
}
@@ -146,23 +122,17 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
{
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
itr = LinkedPoweredBlocks->erase(itr);
- a_Chunk->SetIsRedstoneDirty(true);
- OtherChunk->SetIsRedstoneDirty(true);
continue;
}
else if (
// Things that can send power through a block but which depends on meta
((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) ||
((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) ||
- (((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) ||
- (((Block == E_BLOCK_STONE_PRESSURE_PLATE) || (Block == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (Meta == 0)) ||
- (((Block == E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE) || (Block == E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE)) && (Meta == 0))
+ (((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta)))
)
{
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
itr = LinkedPoweredBlocks->erase(itr);
- a_Chunk->SetIsRedstoneDirty(true);
- OtherChunk->SetIsRedstoneDirty(true);
continue;
}
}
@@ -172,8 +142,6 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
{
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer powered through a valid middle block", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
itr = LinkedPoweredBlocks->erase(itr);
- a_Chunk->SetIsRedstoneDirty(true);
- OtherChunk->SetIsRedstoneDirty(true);
continue;
}
}
@@ -220,16 +188,16 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
cRedstoneSimulatorChunkData * RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData();
for (cRedstoneSimulatorChunkData::iterator itr = RedstoneSimulatorChunkData->begin(); itr != RedstoneSimulatorChunkData->end(); ++itr)
{
- if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block
+ if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block
{
if (!IsAllowedBlock(Block))
{
- itr->DataTwo = true; // The new blocktype is not redstone; it must be queued to be removed from this list
+ itr->DataTwo = true; // The new blocktype is not redstone; it must be queued to be removed from this list
}
else
{
itr->DataTwo = false;
- itr->Data = Block; // Update block information
+ itr->Data = Block; // Update block information
}
return;
}
@@ -311,7 +279,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
if (ShouldUpdateSimulateOnceBlocks)
{
switch (dataitr->Data)
- {
+ {
case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->x, dataitr->y, dataitr->z); break;
@@ -320,6 +288,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
case E_BLOCK_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_ACTIVATOR_RAIL:
case E_BLOCK_DETECTOR_RAIL:
@@ -382,18 +351,13 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
- if (
- ((a_BlockX % cChunkDef::Width) <= 1) ||
- ((a_BlockX % cChunkDef::Width) >= 14) ||
- ((a_BlockZ % cChunkDef::Width) <= 1) ||
- ((a_BlockZ % cChunkDef::Width) >= 14)
- ) // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks
+ if (AreCoordsOnChunkBoundary(a_BlockX, a_BlockY, a_BlockZ))
{
// On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk)
AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
// Pass the original coordinates, because when adding things to our simulator lists, we get the chunk that they are in, and therefore any updates need to preseve their position
- // RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordiantes are in and +- 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries
+ // RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordinates are in and +- 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries
RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 2, a_BlockZ), a_Chunk);
RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 2, a_BlockZ), a_Chunk);
RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 2), a_Chunk);
@@ -412,7 +376,7 @@ void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_Blo
void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState)
{
- static const struct // Define which directions the torch can power
+ static const struct // Define which directions the torch can power
{
int x, y, z;
} gCrossCoords[] =
@@ -426,11 +390,17 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_R
if (a_MyState == E_BLOCK_REDSTONE_TORCH_ON)
{
- // Check if the block the torch is on is powered
+ // Check if the block the torch is on is powered
int X = a_RelBlockX; int Y = a_RelBlockY; int Z = a_RelBlockZ;
- AddFaceDirection(X, Y, Z, cBlockTorchHandler::MetaDataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)), true); // Inverse true to get the block torch is on
+ AddFaceDirection(X, Y, Z, cBlockTorchHandler::MetaDataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)), true); // Inverse true to get the block torch is on
- if (AreCoordsDirectlyPowered(X, Y, Z))
+ cChunk * Neighbour = m_Chunk->GetRelNeighborChunk(X, Z);
+ if ((Neighbour == NULL) || !Neighbour->IsValid())
+ {
+ return;
+ }
+
+ if (AreCoordsDirectlyPowered(X, Y, Z, Neighbour))
{
// There was a match, torch goes off
m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_TORCH_OFF, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ));
@@ -445,11 +415,11 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_R
{
continue;
}
- if (i + 1 < ARRAYCOUNT(gCrossCoords)) // Sides of torch, not top (top is last)
+ if (i + 1 < ARRAYCOUNT(gCrossCoords)) // Sides of torch, not top (top is last)
{
if (
- ((IsMechanism(Type)) || (Type == E_BLOCK_REDSTONE_WIRE)) && // Is it a mechanism or wire? Not block/other torch etc.
- (!Vector3i(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z).Equals(Vector3i(X, Y, Z))) // CAN'T power block is that it is on
+ IsMechanism(Type) && // Is it a mechanism? Not block/other torch etc.
+ (!Vector3i(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z).Equals(Vector3i(X, Y, Z))) // CAN'T power block is that it is on
)
{
SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ);
@@ -464,11 +434,11 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_R
}
}
- if (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) != 0x5) // Is torch standing on ground? If NOT (i.e. on wall), power block beneath
+ if (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) != 0x5) // Is torch standing on ground? If NOT (i.e. on wall), power block beneath
{
BLOCKTYPE Type = m_Chunk->GetBlock(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ);
- if ((IsMechanism(Type)) || (Type == E_BLOCK_REDSTONE_WIRE)) // Still can't make a normal block powered though!
+ if (IsMechanism(Type)) // Still can't make a normal block powered though!
{
SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ);
}
@@ -476,14 +446,20 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_R
}
else
{
- // Check if the block the torch is on is powered
+ // Check if the block the torch is on is powered
int X = a_RelBlockX; int Y = a_RelBlockY; int Z = a_RelBlockZ;
- AddFaceDirection(X, Y, Z, cBlockTorchHandler::MetaDataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)), true); // Inverse true to get the block torch is on
-
+ AddFaceDirection(X, Y, Z, cBlockTorchHandler::MetaDataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)), true); // Inverse true to get the block torch is on
+
+ cChunk * Neighbour = m_Chunk->GetRelNeighborChunk(X, Z);
+ if ((Neighbour == NULL) || !Neighbour->IsValid())
+ {
+ return;
+ }
+
// See if off state torch can be turned on again
- if (AreCoordsDirectlyPowered(X, Y, Z))
+ if (AreCoordsDirectlyPowered(X, Y, Z, Neighbour))
{
- return; // Something matches, torch still powered
+ return; // Something matches, torch still powered
}
// Block torch on not powered, can be turned on again!
@@ -498,7 +474,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_R
void cIncrementalRedstoneSimulator::HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
- SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); // Set self as powered
+ SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); // Set self as powered
}
@@ -579,7 +555,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneButton(int a_RelBlockX, int a_
void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- static const struct // Define which directions the wire can receive power from
+ static const struct // Define which directions the wire can receive power from
{
int x, y, z;
} gCrossCoords[] =
@@ -592,13 +568,13 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re
{-1, 1, 0},
{ 0, 1, 1},
{ 0, 1, -1}, /* Wires one higher, surrounding self stop */
- { 1,-1, 0}, /* Wires one lower, surrounding self start */
- {-1,-1, 0},
- { 0,-1, 1},
- { 0,-1, -1}, /* Wires one lower, surrounding self stop */
+ { 1, -1, 0}, /* Wires one lower, surrounding self start */
+ {-1, -1, 0},
+ { 0, -1, 1},
+ { 0, -1, -1}, /* Wires one lower, surrounding self stop */
} ;
- static const struct // Define which directions the wire will check for repeater prescence
+ static const struct // Define which directions the wire will check for repeater prescence
{
int x, y, z;
} gSideCoords[] =
@@ -606,7 +582,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re
{ 1, 0, 0 },
{-1, 0, 0 },
{ 0, 0, 1 },
- { 0, 0,-1 },
+ { 0, 0, -1 },
{ 0, 1, 0 },
};
@@ -630,9 +606,9 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re
MyPower--;
- for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power
+ for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power
{
- if ((i >= 4) && (i <= 7)) // If we are currently checking for wire surrounding ourself one block above...
+ if ((i >= 4) && (i <= 7)) // If we are currently checking for wire surrounding ourself one block above...
{
BLOCKTYPE Type = 0;
if (a_RelBlockY + 1 >= cChunkDef::Height)
@@ -643,12 +619,12 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re
{
continue;
}
- if (cBlockInfo::IsSolid(Type)) // If there is something solid above us (wire cut off)...
+ if (cBlockInfo::IsSolid(Type)) // If there is something solid above us (wire cut off)...
{
- continue; // We don't receive power from that wire
+ continue; // We don't receive power from that wire
}
}
- else if ((i >= 8) && (i <= 11)) // See above, but this is for wire below us
+ else if ((i >= 8) && (i <= 11)) // See above, but this is for wire below us
{
BLOCKTYPE Type = 0;
if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY, a_RelBlockZ + gCrossCoords[i].z, Type))
@@ -672,7 +648,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re
}
}
- for (size_t i = 0; i < ARRAYCOUNT(gSideCoords); i++) // Look for repeaters immediately surrounding self and try to power them
+ for (size_t i = 0; i < ARRAYCOUNT(gSideCoords); i++) // Look for repeaters immediately surrounding self and try to power them
{
BLOCKTYPE Type = 0;
if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gSideCoords[i].x, a_RelBlockY + gSideCoords[i].y, a_RelBlockZ + gSideCoords[i].z, Type))
@@ -746,7 +722,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int
X Axis ---->
- Repeater directions, values from a cWorld::GetBlockMeta(a_RelBlockX , a_RelBlockY, a_RelBlockZ) lookup:
+ Repeater directions, values from a cWorld::GetBlockMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) lookup:
East (Right) (X+): 0x1
West (Left) (X-): 0x3
@@ -761,15 +737,15 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int
// Create a variable holding my meta to avoid multiple lookups.
NIBBLETYPE a_Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
bool IsOn = (a_MyState == E_BLOCK_REDSTONE_REPEATER_ON);
-
- if (!IsRepeaterLocked(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta)) // If we're locked, change nothing. Otherwise:
+
+ if (!IsRepeaterLocked(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta)) // If we're locked, change nothing. Otherwise:
{
bool IsSelfPowered = IsRepeaterPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta);
- if (IsSelfPowered && !IsOn) // Queue a power change if powered, but not on and not locked.
+ if (IsSelfPowered && !IsOn) // Queue a power change if powered, but not on and not locked.
{
QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, true);
}
- else if (!IsSelfPowered && IsOn) // Queue a power change if unpowered, on, and not locked.
+ else if (!IsSelfPowered && IsOn) // Queue a power change if unpowered, on, and not locked.
{
QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false);
}
@@ -780,19 +756,22 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
{
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end();)
{
-
- if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
+ if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
{
int RelBlockX = itr->a_RelBlockPos.x;
int RelBlockY = itr->a_RelBlockPos.y;
int RelBlockZ = itr->a_RelBlockPos.z;
- NIBBLETYPE Meta = m_Chunk->GetMeta(RelBlockX, RelBlockY, RelBlockZ);
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ m_Chunk->GetBlockTypeMeta(RelBlockX, RelBlockY, RelBlockZ, Block, Meta);
if (itr->ShouldPowerOn)
{
-
- m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta); // For performance
+ if (Block != E_BLOCK_REDSTONE_REPEATER_ON) // For performance
+ {
+ m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta);
+ }
- switch (Meta & 0x3) // We only want the direction (bottom) bits
+ switch (Meta & 0x3) // We only want the direction (bottom) bits
{
case 0x0:
{
@@ -820,7 +799,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
}
}
}
- else
+ else if (Block != E_BLOCK_REDSTONE_REPEATER_OFF)
{
m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta);
}
@@ -828,9 +807,6 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
}
else
{
- // Apparently, incrementing ticks only works reliably here, and not in SimChunk;
- // With a world with lots of redstone, the repeaters simply do not delay
- // I am confounded to say why. Perhaps optimisation failure.
LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks);
itr->a_ElapsedTicks++;
itr++;
@@ -843,11 +819,11 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
void cIncrementalRedstoneSimulator::HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
-{
+{
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
- if (IsPistonPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7)) // We only want the bottom three bits (4th controls extended-ness)
+ if (IsPistonPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7)) // We only want the bottom three bits (4th controls extended-ness)
{
cBlockPistonHandler::ExtendPiston(BlockX, a_RelBlockY, BlockZ, &m_World);
}
@@ -864,13 +840,13 @@ void cIncrementalRedstoneSimulator::HandlePiston(int a_RelBlockX, int a_RelBlock
void cIncrementalRedstoneSimulator::HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
class cSetPowerToDropSpenser :
- public cDropSpenserCallback
+ public cRedstonePoweredCallback
{
bool m_IsPowered;
public:
cSetPowerToDropSpenser(bool a_IsPowered) : m_IsPowered(a_IsPowered) {}
-
- virtual bool Item(cDropSpenserEntity * a_DropSpenser) override
+
+ virtual bool Item(cRedstonePoweredEntity * a_DropSpenser) override
{
a_DropSpenser->SetRedstonePower(m_IsPowered);
return false;
@@ -879,7 +855,7 @@ void cIncrementalRedstoneSimulator::HandleDropSpenser(int a_RelBlockX, int a_Rel
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
- m_Chunk->DoWithDropSpenserAt(BlockX, a_RelBlockY, BlockZ, DrSpSP);
+ m_Chunk->DoWithRedstonePoweredEntityAt(BlockX, a_RelBlockY, BlockZ, DrSpSP);
}
@@ -915,7 +891,7 @@ void cIncrementalRedstoneSimulator::HandleTNT(int a_RelBlockX, int a_RelBlockY,
if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
{
- m_Chunk->BroadcastSoundEffect("game.tnt.primed", BlockX * 8, a_RelBlockY * 8, BlockZ * 8, 0.5f, 0.6f);
+ m_Chunk->BroadcastSoundEffect("game.tnt.primed", (double)BlockX, (double)a_RelBlockY, (double)BlockZ, 0.5f, 0.6f);
m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_AIR, 0);
m_World.SpawnPrimedTNT(BlockX + 0.5, a_RelBlockY + 0.5, BlockZ + 0.5); // 80 ticks to boom
}
@@ -970,7 +946,7 @@ void cIncrementalRedstoneSimulator::HandleCommandBlock(int a_RelBlockX, int a_Re
bool m_IsPowered;
public:
cSetPowerToCommandBlock(bool a_IsPowered) : m_IsPowered(a_IsPowered) {}
-
+
virtual bool Item(cCommandBlockEntity * a_CommandBlock) override
{
a_CommandBlock->SetRedstonePower(m_IsPowered);
@@ -1056,25 +1032,21 @@ void cIncrementalRedstoneSimulator::HandleNoteBlock(int a_RelBlockX, int a_RelBl
if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true))
{
class cSetPowerToNoteBlock :
- public cNoteBlockCallback
+ public cRedstonePoweredCallback
{
- bool m_IsPowered;
public:
- cSetPowerToNoteBlock(bool a_IsPowered) : m_IsPowered(a_IsPowered) {}
+ cSetPowerToNoteBlock() {}
- virtual bool Item(cNoteEntity * a_NoteBlock) override
+ virtual bool Item(cRedstonePoweredEntity * a_NoteBlock) override
{
- if (m_IsPowered)
- {
- a_NoteBlock->MakeSound();
- }
+ a_NoteBlock->SetRedstonePower(true);
return false;
}
- } NoteBlockSP(m_bAreCoordsPowered);
+ } NoteBlockSP;
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
- m_Chunk->DoWithNoteBlockAt(BlockX, a_RelBlockY, BlockZ, NoteBlockSP);
+ m_Chunk->DoWithRedstonePoweredEntityAt(BlockX, a_RelBlockY, BlockZ, NoteBlockSP);
SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true);
}
}
@@ -1139,7 +1111,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
else
{
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x0);
- WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
}
break;
}
@@ -1193,7 +1165,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
{
if (Meta == E_META_PRESSURE_PLATE_RAISED)
{
- m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.5F);
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F);
}
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Power);
@@ -1203,10 +1175,10 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
{
if (Meta == E_META_PRESSURE_PLATE_DEPRESSED)
{
- m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F);
}
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
- WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
}
break;
@@ -1261,7 +1233,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
{
if (Meta == E_META_PRESSURE_PLATE_RAISED)
{
- m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.5F);
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F);
}
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Power);
@@ -1271,10 +1243,10 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
{
if (Meta == E_META_PRESSURE_PLATE_DEPRESSED)
{
- m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F);
}
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
- WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
}
break;
@@ -1302,7 +1274,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
if (Distance <= 0.5)
{
m_FoundEntity = true;
- return true; // Break out, we only need to know for plates that at least one entity is on top
+ return true; // Break out, we only need to know for plates that at least one entity is on top
}
return false;
}
@@ -1328,7 +1300,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
{
if (Meta == E_META_PRESSURE_PLATE_RAISED)
{
- m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.5F);
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F);
}
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
@@ -1338,10 +1310,10 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
{
if (Meta == E_META_PRESSURE_PLATE_DEPRESSED)
{
- m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F);
}
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
- WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
}
break;
}
@@ -1365,7 +1337,7 @@ void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_Re
bool FoundActivated = false;
eBlockFace FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ));
- for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks
+ for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks
{
BLOCKTYPE Type;
NIBBLETYPE Meta;
@@ -1384,14 +1356,14 @@ void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_Re
{
if (ReverseBlockFace(cBlockTripwireHookHandler::MetadataToDirection(Meta)) == FaceToGoTowards)
{
- // Other hook not facing in opposite direction
+ // Other hook facing in opposite direction - circuit completed!
break;
}
else
{
// Tripwire hook not connected at all, AND away all the power state bits
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3);
- WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
return;
}
}
@@ -1399,7 +1371,7 @@ void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_Re
{
// Tripwire hook not connected at all, AND away all the power state bits
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3);
- WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
return;
}
}
@@ -1414,7 +1386,51 @@ void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_Re
{
// Connected but not activated, AND away the highest bit
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7) | 0x4);
- WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
+ }
+}
+
+
+
+
+
+void cIncrementalRedstoneSimulator::HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
+{
+ class cGetTrappedChestPlayers :
+ public cChestCallback
+ {
+ public:
+ cGetTrappedChestPlayers(void) :
+ m_NumberOfPlayers(0)
+ {
+ }
+
+ virtual bool Item(cChestEntity * a_Chest) override
+ {
+ ASSERT(a_Chest->GetBlockType() == E_BLOCK_TRAPPED_CHEST);
+ m_NumberOfPlayers = a_Chest->GetNumberOfPlayers();
+ return (m_NumberOfPlayers <= 0);
+ }
+
+ unsigned char GetPowerLevel(void) const
+ {
+ return std::min(m_NumberOfPlayers, MAX_POWER_LEVEL);
+ }
+
+ private:
+ int m_NumberOfPlayers;
+
+ } GTCP;
+
+ int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
+ int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
+ if (m_Chunk->DoWithChestAt(BlockX, a_RelBlockY, BlockZ, GTCP))
+ {
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, GTCP.GetPowerLevel());
+ }
+ else
+ {
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
}
}
@@ -1447,7 +1463,7 @@ void cIncrementalRedstoneSimulator::HandleTripwire(int a_RelBlockX, int a_RelBlo
if (bbEntity.DoesIntersect(bbWire))
{
m_FoundEntity = true;
- return true; // One entity is sufficient to trigger the wire
+ return true; // One entity is sufficient to trigger the wire
}
return false;
}
@@ -1482,20 +1498,21 @@ void cIncrementalRedstoneSimulator::HandleTripwire(int a_RelBlockX, int a_RelBlo
-bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
+bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk)
{
+ // Torches want to access neighbour's data when on a wall, hence the extra chunk parameter
+
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
- PoweredBlocksList * Powered = m_Chunk->GetNeighborChunk(BlockX, BlockZ)->GetRedstoneSimulatorPoweredBlocksList(); // Torches want to access neighbour's data when on a wall
- for (PoweredBlocksList::const_iterator itr = Powered->begin(); itr != Powered->end(); ++itr) // Check powered list
+ for (PoweredBlocksList::const_iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end(); ++itr) // Check powered list
{
if (itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
return true;
}
}
- return false;
+ return false;
}
@@ -1507,7 +1524,7 @@ bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_RelBlockX, int
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
- for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list
+ for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list
{
if (itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
@@ -1585,7 +1602,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel
}
}
}
- return false; // Couldn't find power source behind repeater
+ return false; // Couldn't find power source behind repeater
}
@@ -1593,8 +1610,8 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_Rel
bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta)
-{
- switch (a_Meta & 0x3) // We only want the 'direction' part of our metadata
+{
+ switch (a_Meta & 0x3) // We only want the 'direction' part of our metadata
{
// If the repeater is looking up or down (If parallel to the Z axis)
case 0x0:
@@ -1602,17 +1619,17 @@ bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_RelBlockX, int a_RelB
{
// Check if eastern(right) neighbor is a powered on repeater who is facing us
BLOCKTYPE Block = 0;
- if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) // Is right neighbor a powered repeater?
+ if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) // Is right neighbor a powered repeater?
{
NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ) & 0x3;
- if (OtherRepeaterDir == 0x3) { return true; } // If so, I am latched/locked
+ if (OtherRepeaterDir == 0x3) { return true; } // If so, I am latched/locked
}
// Check if western(left) neighbor is a powered on repeater who is facing us
if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON))
{
NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX -1, a_RelBlockY, a_RelBlockZ) & 0x3;
- if (OtherRepeaterDir == 0x1) { return true; } // If so, I am latched/locked
+ if (OtherRepeaterDir == 0x1) { return true; } // If so, I am latched/locked
}
break;
@@ -1625,23 +1642,23 @@ bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_RelBlockX, int a_RelB
// Check if southern(down) neighbor is a powered on repeater who is facing us
BLOCKTYPE Block = 0;
if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON))
- {
+ {
NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1) & 0x3;
- if (OtherRepeaterDir == 0x0) { return true; } // If so, am latched/locked
+ if (OtherRepeaterDir == 0x0) { return true; } // If so, am latched/locked
}
// Check if northern(up) neighbor is a powered on repeater who is facing us
if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON))
- {
+ {
NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1) & 0x3;
- if (OtherRepeaterDir == 0x2) { return true; } // If so, I am latched/locked
+ if (OtherRepeaterDir == 0x2) { return true; } // If so, I am latched/locked
}
break;
}
}
- return false; // None of the checks succeeded, I am not a locked repeater
+ return false; // None of the checks succeeded, I am not a locked repeater
}
@@ -1682,7 +1699,7 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl
AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face, true);
}
- return false; // Source was in front of the piston's front face
+ return false; // Source was in front of the piston's front face
}
@@ -1691,28 +1708,36 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl
bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel)
{
a_PowerLevel = 0;
- int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
- int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+ int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
+ int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
- for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) // Check powered list
+ for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) // Check powered list
{
if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
continue;
}
- a_PowerLevel = std::max(itr->a_PowerLevel , a_PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block)
+ a_PowerLevel = std::max(itr->a_PowerLevel, a_PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block)
}
- for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list
+ for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list
{
if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
continue;
}
+
+ BLOCKTYPE Type = E_BLOCK_AIR;
+ int RelSourceX = itr->a_SourcePos.x - m_Chunk->GetPosX() * cChunkDef::Width;
+ int RelSourceZ = itr->a_SourcePos.z - m_Chunk->GetPosZ() * cChunkDef::Width;
+ if (!m_Chunk->UnboundedRelGetBlockType(RelSourceX, itr->a_SourcePos.y, RelSourceZ, Type) || (Type == E_BLOCK_REDSTONE_WIRE))
+ {
+ continue;
+ }
a_PowerLevel = std::max(itr->a_PowerLevel, a_PowerLevel);
}
- return (a_PowerLevel != 0); // Answer the inital question: is the wire powered?
+ return (a_PowerLevel != 0); // Answer the inital question: is the wire powered?
}
@@ -1725,17 +1750,17 @@ bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_RelBlockX, int a_Re
{
if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
{
- if (itr->WasLastStatePowered != IsCurrentStatePowered) // Was the last power state different to the current?
+ if (itr->WasLastStatePowered != IsCurrentStatePowered) // Was the last power state different to the current?
{
- return false; // It was, coordinates are no longer simulated
+ return false; // It was, coordinates are no longer simulated
}
else
{
- return true; // It wasn't, don't resimulate block, and allow players to toggle
+ return true; // It wasn't, don't resimulate block, and allow players to toggle
}
}
}
- return false; // Block wasn't even in the list, not simulated
+ return false; // Block wasn't even in the list, not simulated
}
@@ -1813,7 +1838,7 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_RelBlockX, i
{
return;
}
-
+
SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 2, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
@@ -1839,7 +1864,7 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_RelBlockX, i
}
default:
{
- ASSERT(!"Unhandled face direction when attempting to set blocks as linked powered!"); // Zombies, that wasn't supposed to happen...
+ ASSERT(!"Unhandled face direction when attempting to set blocks as linked powered!"); // Zombies, that wasn't supposed to happen...
break;
}
}
@@ -1864,7 +1889,7 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_R
{ 0, -1, 0 }
};
- for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions
+ for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions
{
SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_PowerLevel);
}
@@ -1881,20 +1906,14 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBl
int SourceX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelSourceX;
int SourceZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelSourceZ;
- BLOCKTYPE Block = 0;
- if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Block))
- {
- return;
- }
- if (Block == E_BLOCK_AIR)
+ cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockX, a_RelBlockZ); // Adjust coordinates for the later call using these values
+ if ((Neighbour == NULL) || !Neighbour->IsValid())
{
- // Don't set air, fixes some bugs (wires powering themselves)
return;
}
- cChunk * Neighbour = m_Chunk->GetNeighborChunk(BlockX, BlockZ);
- PoweredBlocksList * Powered = Neighbour->GetRedstoneSimulatorPoweredBlocksList();
- for (PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr) // Check powered list
+ PoweredBlocksList * Powered = Neighbour->GetRedstoneSimulatorPoweredBlocksList(); // We need to insert the value into the chunk who owns the block position
+ for (PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr)
{
if (
itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) &&
@@ -1907,16 +1926,33 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBl
}
}
- PoweredBlocksList * OtherPowered = m_Chunk->GetNeighborChunk(SourceX, SourceZ)->GetRedstoneSimulatorPoweredBlocksList();
- for (PoweredBlocksList::const_iterator itr = OtherPowered->begin(); itr != OtherPowered->end(); ++itr) // Check powered list
+ // No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk
+ // TODO: on C++11 support, change this to a llama function pased to a std::remove_if
+ for (PoweredBlocksList::iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr)
{
if (
itr->a_BlockPos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ)) &&
- itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))
+ itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) &&
+ (m_Chunk->GetBlock(a_RelSourceX, a_RelSourceY, a_RelSourceZ) == E_BLOCK_REDSTONE_WIRE)
)
{
- // Powered wires try to power their source - don't let them!
- return;
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ Neighbour->GetBlockTypeMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Block, Meta);
+
+ if (Block == E_BLOCK_REDSTONE_WIRE)
+ {
+ if (Meta < a_PowerLevel)
+ {
+ m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it
+ break;
+ }
+ else
+ {
+ // Powered wires try to power their source - don't let them!
+ return;
+ }
+ }
}
}
@@ -1947,26 +1983,17 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
int SourceX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelSourceX;
int SourceZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelSourceZ;
- BLOCKTYPE DestBlock = 0;
- if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ, DestBlock))
- {
- return;
- }
- if (DestBlock == E_BLOCK_AIR)
- {
- // Don't set air, fixes some bugs (wires powering themselves)
- return;
- }
- if ((DestBlock == E_BLOCK_REDSTONE_WIRE) && (m_Chunk->GetBlock(a_RelSourceX, a_RelSourceY, a_RelSourceZ) == E_BLOCK_REDSTONE_WIRE))
+ if (!IsViableMiddleBlock(a_MiddleBlock))
{
return;
}
- if (!IsViableMiddleBlock(a_MiddleBlock))
+
+ cChunk * Neighbour = m_Chunk->GetNeighborChunk(BlockX, BlockZ);
+ if ((Neighbour == NULL) || !Neighbour->IsValid())
{
return;
}
- cChunk * Neighbour = m_Chunk->GetNeighborChunk(BlockX, BlockZ);
LinkedBlocksList * Linked = Neighbour->GetRedstoneSimulatorLinkedBlocksList();
for (LinkedBlocksList::iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list
{
@@ -2035,13 +2062,13 @@ bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, in
{
if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
{
- if (ShouldPowerOn == itr->ShouldPowerOn) // We are queued already for the same thing, don't replace entry
+ if (ShouldPowerOn == itr->ShouldPowerOn) // We are queued already for the same thing, don't replace entry
{
return false;
}
// Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit
- itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description
+ itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description
itr->a_ElapsedTicks = 0;
itr->ShouldPowerOn = ShouldPowerOn;
return false;
@@ -2049,11 +2076,11 @@ bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, in
}
// Self not in list, add self to list
- sRepeatersDelayList RC;
+ sRepeatersDelayList RC;
RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
// Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.)
- // * 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility
+ // Multiply by 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility
RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2;
RC.a_ElapsedTicks = 0;
@@ -2066,6 +2093,52 @@ bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, in
+void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_SourceX, int a_SourceY, int a_SourceZ, cChunk * a_Chunk, bool a_IsFirstCall)
+{
+ if (!a_IsFirstCall) // The neighbouring chunks passed when this parameter is false may be invalid
+ {
+ if ((a_Chunk == NULL) || !a_Chunk->IsValid())
+ {
+ return;
+ }
+ }
+ // TODO: on C++11 support, change both of these to llama functions pased to a std::remove_if
+
+ for (PoweredBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end();)
+ {
+ if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)))
+ {
+ itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->erase(itr);
+ a_Chunk->SetIsRedstoneDirty(true);
+ continue;
+ }
+ ++itr;
+ }
+ for (LinkedBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->end();)
+ {
+ if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)))
+ {
+ itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->erase(itr);
+ a_Chunk->SetIsRedstoneDirty(true);
+ continue;
+ }
+ ++itr;
+ }
+
+ if (a_IsFirstCall && AreCoordsOnChunkBoundary(a_SourceX, a_SourceY, a_SourceZ))
+ {
+ // +- 2 to accomodate linked powered blocks
+ SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX - 2, a_SourceZ), false);
+ SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX + 2, a_SourceZ), false);
+ SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ - 2), false);
+ SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ + 2), false);
+ }
+}
+
+
+
+
+
cIncrementalRedstoneSimulator::eRedstoneDirection cIncrementalRedstoneSimulator::GetWireDirection(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
int Dir = REDSTONE_NONE;
diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h
index 6cefdebf2..79740a8f6 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.h
+++ b/src/Simulator/IncrementalRedstoneSimulator.h
@@ -38,33 +38,33 @@ private:
#define MAX_POWER_LEVEL 15
- struct sPoweredBlocks // Define structure of the directly powered blocks list
+ struct sPoweredBlocks // Define structure of the directly powered blocks list
{
- Vector3i a_BlockPos; // Position of powered block
- Vector3i a_SourcePos; // Position of source powering the block at a_BlockPos
+ Vector3i a_BlockPos; // Position of powered block
+ Vector3i a_SourcePos; // Position of source powering the block at a_BlockPos
unsigned char a_PowerLevel;
};
- struct sLinkedPoweredBlocks // Define structure of the indirectly powered blocks list (i.e. repeaters powering through a block to the block at the other side)
+ struct sLinkedPoweredBlocks // Define structure of the indirectly powered blocks list (i.e. repeaters powering through a block to the block at the other side)
{
Vector3i a_BlockPos;
- Vector3i a_MiddlePos; // Position of block that is betwixt a source and the destination
+ Vector3i a_MiddlePos; // Position of block that is betwixt a source and the destination
Vector3i a_SourcePos;
unsigned char a_PowerLevel;
};
- struct sSimulatedPlayerToggleableList // Define structure of the list containing simulate-on-update blocks (such as trapdoors that respond once to a block update, and can be toggled by a player)
+ struct sSimulatedPlayerToggleableList // Define structure of the list containing simulate-on-update blocks (such as trapdoors that respond once to a block update, and can be toggled by a player)
{
Vector3i a_RelBlockPos;
- bool WasLastStatePowered; // Was the last state powered or not? Determines whether a source update has happened and if I should resimulate
+ bool WasLastStatePowered; // Was the last state powered or not? Determines whether a source update has happened and if I should resimulate
};
- struct sRepeatersDelayList // Define structure of list containing repeaters' delay states
+ struct sRepeatersDelayList // Define structure of list containing repeaters' delay states
{
Vector3i a_RelBlockPos;
- unsigned char a_DelayTicks; // For how many ticks should the repeater delay
- unsigned char a_ElapsedTicks; // How much of the previous has been elapsed?
- bool ShouldPowerOn; // What happens when the delay time is fulfilled?
+ unsigned char a_DelayTicks; // For how many ticks should the repeater delay
+ unsigned char a_ElapsedTicks; // How much of the previous has been elapsed?
+ bool ShouldPowerOn; // What happens when the delay time is fulfilled?
};
public:
@@ -107,6 +107,8 @@ private:
If this line is complete, it verifies that at least on wire reports an entity is on top (via its meta), and performs its task
*/
void HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles trapped chests */
+ void HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/* ==================== */
/* ====== CARRIERS ====== */
@@ -114,8 +116,6 @@ private:
void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles repeaters */
void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
- /** Handles delayed updates to Repeaters **/
- void HandleRedstoneRepeaterDelays();
/* ====================== */
/* ====== DEVICES ====== */
@@ -156,11 +156,15 @@ private:
void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
/** Queues a repeater to be powered or unpowered and returns if the m_RepeatersDelayList iterators were invalidated */
bool QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
+ /** Removes a block from the Powered and LinkedPowered lists
+ Used for variable sources such as tripwire hooks, daylight sensors, and trapped chests
+ */
+ void SetSourceUnpowered(int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, cChunk * a_Chunk, bool a_IsFirstCall = true);
/** Returns if a coordinate is powered or linked powered */
- bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
+ bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
/** Returns if a coordinate is in the directly powered blocks list */
- bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk);
/** Returns if a coordinate is in the indirectly powered blocks list */
bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */
@@ -174,7 +178,8 @@ private:
/** Returns if a wire is powered
The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */
bool IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel);
-
+ /** Handles delayed updates to repeaters **/
+ void HandleRedstoneRepeaterDelays(void);
/** Returns if lever metadata marks it as emitting power */
bool IsLeverOn(NIBBLETYPE a_BlockMeta);
@@ -186,7 +191,9 @@ private:
/** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */
inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return cBlockInfo::FullyOccupiesVoxel(Block); }
- /** Returns if a block is a mechanism (something that accepts power and does something) */
+ /** Returns if a block is a mechanism (something that accepts power and does something)
+ Used by torches to determine if they power a block whilst not standing on the ground
+ */
inline static bool IsMechanism(BLOCKTYPE Block)
{
switch (Block)
@@ -209,6 +216,7 @@ private:
case E_BLOCK_REDSTONE_REPEATER_OFF:
case E_BLOCK_REDSTONE_REPEATER_ON:
case E_BLOCK_POWERED_RAIL:
+ case E_BLOCK_REDSTONE_WIRE:
{
return true;
}
@@ -235,6 +243,7 @@ private:
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
case E_BLOCK_STONE_PRESSURE_PLATE:
case E_BLOCK_WOODEN_PRESSURE_PLATE:
+ case E_BLOCK_TRAPPED_CHEST:
{
return true;
}
@@ -277,6 +286,7 @@ private:
case E_BLOCK_STONE_PRESSURE_PLATE:
case E_BLOCK_TNT:
case E_BLOCK_TRAPDOOR:
+ case E_BLOCK_TRAPPED_CHEST:
case E_BLOCK_TRIPWIRE_HOOK:
case E_BLOCK_TRIPWIRE:
case E_BLOCK_WOODEN_BUTTON:
@@ -284,11 +294,21 @@ private:
case E_BLOCK_WOODEN_PRESSURE_PLATE:
case E_BLOCK_PISTON:
{
- return true;
+ return true;
}
default: return false;
}
}
+
+ inline static bool AreCoordsOnChunkBoundary(int a_BlockX, int a_BlockY, int a_BlockZ)
+ {
+ return ( // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks
+ ((a_BlockX % cChunkDef::Width) <= 1) ||
+ ((a_BlockX % cChunkDef::Width) >= 14) ||
+ ((a_BlockZ % cChunkDef::Width) <= 1) ||
+ ((a_BlockZ % cChunkDef::Width) >= 14)
+ );
+ }
};
diff --git a/src/Simulator/NoopFluidSimulator.h b/src/Simulator/NoopFluidSimulator.h
index 9113aec3c..9fe2f9040 100644
--- a/src/Simulator/NoopFluidSimulator.h
+++ b/src/Simulator/NoopFluidSimulator.h
@@ -27,7 +27,7 @@ public:
}
// cSimulator overrides:
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override
{
UNUSED(a_BlockX);
UNUSED(a_BlockY);
diff --git a/src/Simulator/NoopRedstoneSimulator.h b/src/Simulator/NoopRedstoneSimulator.h
index fe3949198..f9ed47982 100644
--- a/src/Simulator/NoopRedstoneSimulator.h
+++ b/src/Simulator/NoopRedstoneSimulator.h
@@ -18,17 +18,17 @@ public:
{
}
- //~cRedstoneNoopSimulator();
+ // ~cRedstoneNoopSimulator();
virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used
- virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override
+ virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override
{
UNUSED(a_Dt);
UNUSED(a_ChunkX);
UNUSED(a_ChunkZ);
UNUSED(a_Chunk);
}
- virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType ) override { return false; }
+ virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType) override { return false; }
virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override
{
UNUSED(a_BlockX);
diff --git a/src/Simulator/SandSimulator.h b/src/Simulator/SandSimulator.h
index 6e64aa425..1262f2792 100644
--- a/src/Simulator/SandSimulator.h
+++ b/src/Simulator/SandSimulator.h
@@ -37,7 +37,7 @@ public:
based on the block currently present in the world at the dest specified coords
*/
static void FinishFalling(
- cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ,
+ cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ,
BLOCKTYPE a_FallingBlockType, NIBBLETYPE a_FallingBlockMeta
);
diff --git a/src/Simulator/Simulator.h b/src/Simulator/Simulator.h
index a2e2a5742..4d9a18867 100644
--- a/src/Simulator/Simulator.h
+++ b/src/Simulator/Simulator.h
@@ -26,13 +26,13 @@ public:
/// Called in each tick for each chunk, a_Dt is the time passed since the last tick, in msec; direct access to chunk data available
virtual void SimulateChunk(float a_Dt, int a_ChunkX,
- int a_ChunkZ, cChunk * a_Chunk)
+ int a_ChunkZ, cChunk * a_Chunk)
{
UNUSED(a_Dt);
UNUSED(a_ChunkX);
UNUSED(a_ChunkZ);
UNUSED(a_Chunk);
- };
+ }
/// Called when a block changes
virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk);
diff --git a/src/Simulator/SimulatorManager.cpp b/src/Simulator/SimulatorManager.cpp
index 2bc483cbd..918bac7a1 100644
--- a/src/Simulator/SimulatorManager.cpp
+++ b/src/Simulator/SimulatorManager.cpp
@@ -29,7 +29,7 @@ cSimulatorManager::~cSimulatorManager()
void cSimulatorManager::Simulate(float a_Dt)
{
m_Ticks++;
- for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr )
+ for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr)
{
if ((m_Ticks % itr->second) == 0)
{
@@ -45,7 +45,7 @@ void cSimulatorManager::Simulate(float a_Dt)
void cSimulatorManager::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
{
// m_Ticks has already been increased in Simulate()
- for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr )
+ for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr)
{
if ((m_Ticks % itr->second) == 0)
{
@@ -60,7 +60,7 @@ void cSimulatorManager::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cC
void cSimulatorManager::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
- for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr )
+ for (cSimulators::iterator itr = m_Simulators.begin(); itr != m_Simulators.end(); ++itr)
{
itr->first->WakeUp(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
}
diff --git a/src/Simulator/VaporizeFluidSimulator.cpp b/src/Simulator/VaporizeFluidSimulator.cpp
index 4206c64d1..484cac334 100644
--- a/src/Simulator/VaporizeFluidSimulator.cpp
+++ b/src/Simulator/VaporizeFluidSimulator.cpp
@@ -27,7 +27,7 @@ void cVaporizeFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ,
return;
}
int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
- int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
+ int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
BLOCKTYPE BlockType = a_Chunk->GetBlock(RelX, a_BlockY, RelZ);
if (
(BlockType == m_FluidBlock) ||
@@ -35,7 +35,7 @@ void cVaporizeFluidSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ,
)
{
a_Chunk->SetBlock(RelX, a_BlockY, RelZ, E_BLOCK_AIR, 0);
- a_Chunk->BroadcastSoundEffect("random.fizz", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.6f);
+ a_Chunk->BroadcastSoundEffect("random.fizz", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0f, 0.6f);
}
}
diff --git a/src/Statistics.cpp b/src/Statistics.cpp
index 5c0524f9e..e0c0dd925 100644
--- a/src/Statistics.cpp
+++ b/src/Statistics.cpp
@@ -7,7 +7,8 @@
-cStatInfo cStatInfo::ms_Info[statCount] = {
+cStatInfo cStatInfo::ms_Info[statCount] =
+{
// The order must match the order of enum eStatistic
// http://minecraft.gamepedia.com/Achievements
diff --git a/src/Statistics.h b/src/Statistics.h
index f37f32e1e..d70a2aeab 100644
--- a/src/Statistics.h
+++ b/src/Statistics.h
@@ -62,7 +62,7 @@ enum eStatistic
statDistDove,
statDistMinecart,
statDistBoat,
- statDistPig,
+ statDistPig,
statDistHorse,
statJumps,
statItemsDropped,
@@ -118,7 +118,7 @@ private:
/* Signed (?) integral value. */
-typedef int StatValue; // tolua_export
+typedef int StatValue; // tolua_export
@@ -143,10 +143,9 @@ public:
/** Reset everything. */
void Reset();
- /** Increment the specified stat.
- *
- * Returns the new value.
- */
+ /** Increments the specified stat.
+ Returns the new value.
+ */
StatValue AddValue(const eStatistic a_Stat, const StatValue a_Delta = 1);
// tolua_end
@@ -158,7 +157,7 @@ private:
// TODO 10-05-2014 xdot: Use, mine, craft statistics
-}; // tolua_export
+}; // tolua_export
diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp
index 7488a3073..5f88cbf64 100644
--- a/src/StringUtils.cpp
+++ b/src/StringUtils.cpp
@@ -196,16 +196,19 @@ AString TrimString(const AString & str)
-AString & StrToUpper(AString & s)
+AString & InPlaceLowercase(AString & s)
{
- AString::iterator i = s.begin();
- AString::iterator end = s.end();
+ std::transform(s.begin(), s.end(), s.begin(), ::tolower);
+ return s;
+}
- while (i != end)
- {
- *i = (char)toupper(*i);
- ++i;
- }
+
+
+
+
+AString & InPlaceUppercase(AString & s)
+{
+ std::transform(s.begin(), s.end(), s.begin(), ::toupper);
return s;
}
@@ -213,17 +216,22 @@ AString & StrToUpper(AString & s)
-AString & StrToLower(AString & s)
+AString StrToLower(const AString & s)
{
- AString::iterator i = s.begin();
- AString::iterator end = s.end();
+ AString res(s);
+ std::transform(res.begin(), res.end(), res.begin(), ::tolower);
+ return res;
+}
- while (i != end)
- {
- *i = (char)tolower(*i);
- ++i;
- }
- return s;
+
+
+
+
+AString StrToUpper(const AString & s)
+{
+ AString res(s);
+ std::transform(res.begin(), res.end(), res.begin(), ::toupper);
+ return res;
}
@@ -233,13 +241,11 @@ AString & StrToLower(AString & s)
int NoCaseCompare(const AString & s1, const AString & s2)
{
#ifdef _MSC_VER
- // MSVC has stricmp that compares case-insensitive:
- return _stricmp(s1.c_str(), s2.c_str());
- #else
- // Do it the hard way:
- AString s1Copy(s1);
- AString s2Copy(s2);
- return StrToUpper(s1Copy).compare(StrToUpper(s2Copy));
+ // MSVC has stricmp that compares case-insensitive:
+ return _stricmp(s1.c_str(), s2.c_str());
+ #else
+ // Do it the hard way - convert both strings to lowercase:
+ return StrToLower(s1).compare(StrToLower(s2));
#endif // else _MSC_VER
}
@@ -339,16 +345,16 @@ AString & RawBEToUTF8(const char * a_RawData, size_t a_NumShorts, AString & a_UT
// UTF-8 conversion code adapted from:
// http://stackoverflow.com/questions/2867123/convert-utf-16-to-utf-8-under-windows-and-linux-in-c
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Begin of Unicode, Inc.'s code / information
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
/*
Notice from the original file:
* Copyright 2001-2004 Unicode, Inc.
-*
+*
* Disclaimer
-*
+*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
@@ -356,9 +362,9 @@ Notice from the original file:
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
-*
+*
* Limitations on Rights to Redistribute This Code
-*
+*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
@@ -378,13 +384,13 @@ Notice from the original file:
static const char trailingBytesForUTF8[256] =
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
};
@@ -394,7 +400,7 @@ static const char trailingBytesForUTF8[256] =
static const unsigned int offsetsFromUTF8[6] =
{
- 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL
};
@@ -502,27 +508,27 @@ AString & UTF8ToRawBEUTF16(const char * a_UTF8, size_t a_UTF8Length, AString & a
return a_UTF16;
}
-/* ---------------------------------------------------------------------
-
- Note A.
- The fall-through switches in UTF-8 reading code save a
- temp variable, some decrements & conditionals. The switches
- are equivalent to the following loop:
- {
- int tmpBytesToRead = extraBytesToRead+1;
- do {
- ch += *source++;
- --tmpBytesToRead;
- if (tmpBytesToRead) ch <<= 6;
- } while (tmpBytesToRead > 0);
- }
-
- ---------------------------------------------------------------------
+/*
+---------------------------------------------------------------------
+Note A.
+The fall-through switches in UTF-8 reading code save a
+temp variable, some decrements & conditionals. The switches
+are equivalent to the following loop:
+{
+ int tmpBytesToRead = extraBytesToRead + 1;
+ do
+ {
+ ch += *source++;
+ --tmpBytesToRead;
+ if (tmpBytesToRead) ch <<= 6;
+ } while (tmpBytesToRead > 0);
+}
+---------------------------------------------------------------------
*/
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// End of Unicode, Inc.'s code / information
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
@@ -761,7 +767,7 @@ AString Base64Decode(const AString & a_Base64String)
{
switch (o & 7)
{
- case 0: res[o >> 3] |= (c << 2); break;
+ case 0: res[o >> 3] |= (c << 2); break;
case 6: res[o >> 3] |= (c >> 4); res[(o >> 3) + 1] |= (c << 4); break;
case 4: res[o >> 3] |= (c >> 2); res[(o >> 3) + 1] |= (c << 6); break;
case 2: res[o >> 3] |= c; break;
@@ -785,11 +791,12 @@ AString Base64Decode(const AString & a_Base64String)
AString Base64Encode(const AString & a_Input)
{
- static const char BASE64[64] = {
- 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
- 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
- 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
- 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
+ static const char BASE64[64] =
+ {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
AString output;
diff --git a/src/StringUtils.h b/src/StringUtils.h
index 87b574a34..3d4379352 100644
--- a/src/StringUtils.h
+++ b/src/StringUtils.h
@@ -6,16 +6,12 @@
-#ifndef STRINGUTILS_H_INCLUDED
-#define STRINGUTILS_H_INCLUDED
-
-
+#pragma once
#include <string>
-
typedef std::string AString;
typedef std::vector<AString> AStringVector;
typedef std::list<AString> AStringList;
@@ -46,10 +42,16 @@ extern AStringVector StringSplitAndTrim(const AString & str, const AString & del
extern AString TrimString(const AString & str); // tolua_export
/// In-place string conversion to uppercase; returns the same string
-extern AString & StrToUpper(AString & s);
+extern AString & InPlaceUppercase(AString & s);
/// In-place string conversion to lowercase; returns the same string
-extern AString & StrToLower(AString & s);
+extern AString & InPlaceLowercase(AString & s);
+
+/** Returns an upper-cased copy of the string */
+extern AString StrToUpper(const AString & s);
+
+/** Returns a lower-cased copy of the string */
+extern AString StrToLower(const AString & s);
/// Case-insensitive string comparison; returns 0 if the strings are the same
extern int NoCaseCompare(const AString & s1, const AString & s2); // tolua_export
@@ -101,8 +103,3 @@ extern void SetBEInt(char * a_Mem, Int32 a_Value);
-#endif // STRINGUTILS_H_INCLUDED
-
-
-
-
diff --git a/src/Tracer.cpp b/src/Tracer.cpp
index be42430a5..756147a7b 100644
--- a/src/Tracer.cpp
+++ b/src/Tracer.cpp
@@ -7,7 +7,7 @@
#include "Entities/Entity.h"
#ifndef _WIN32
- #include <stdlib.h> // abs()
+ #include <stdlib.h>
#endif
@@ -18,11 +18,11 @@ cTracer::cTracer(cWorld * a_World)
: m_World(a_World)
{
m_NormalTable[0].Set(-1, 0, 0);
- m_NormalTable[1].Set( 0, 0,-1);
+ m_NormalTable[1].Set( 0, 0, -1);
m_NormalTable[2].Set( 1, 0, 0);
m_NormalTable[3].Set( 0, 0, 1);
m_NormalTable[4].Set( 0, 1, 0);
- m_NormalTable[5].Set( 0,-1, 0);
+ m_NormalTable[5].Set( 0, -1, 0);
}
@@ -37,7 +37,7 @@ cTracer::~cTracer()
-float cTracer::SigNum( float a_Num )
+float cTracer::SigNum( float a_Num)
{
if (a_Num < 0.f) return -1.f;
if (a_Num > 0.f) return 1.f;
@@ -59,7 +59,7 @@ void cTracer::SetValues(const Vector3f & a_Start, const Vector3f & a_Direction)
step.z = (int) SigNum(dir.z);
// normalize the direction vector
- if( dir.SqrLength() > 0.f ) dir.Normalize();
+ if (dir.SqrLength() > 0.f) dir.Normalize();
// how far we must move in the ray direction before
// we encounter a new voxel in x-direction
@@ -192,7 +192,7 @@ bool cTracer::Trace( const Vector3f & a_Start, const Vector3f & a_Direction, int
if (step.y > 0.0f)
{
- if(pos.y >= end1.y)
+ if (pos.y >= end1.y)
{
reachedY = true;
}
@@ -229,7 +229,7 @@ bool cTracer::Trace( const Vector3f & a_Start, const Vector3f & a_Direction, int
if ((!a_LineOfSight && cBlockInfo::IsSolid(BlockID)) || (a_LineOfSight && (BlockID != E_BLOCK_AIR) && !IsBlockWater(BlockID)))
{
BlockHitPosition = pos;
- int Normal = GetHitNormal(a_Start, End, pos );
+ int Normal = GetHitNormal(a_Start, End, pos);
if (Normal > 0)
{
HitNormal = m_NormalTable[Normal-1];
@@ -245,9 +245,9 @@ bool cTracer::Trace( const Vector3f & a_Start, const Vector3f & a_Direction, int
// return 1 = hit, other is not hit
-int LinesCross(float x0,float y0,float x1,float y1,float x2,float y2,float x3,float y3)
+int LinesCross(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
- //float linx, liny;
+ // float linx, liny;
float d=(x1-x0)*(y3-y2)-(y1-y0)*(x3-x2);
if (abs(d)<0.001) {return 0;}
@@ -257,8 +257,8 @@ int LinesCross(float x0,float y0,float x1,float y1,float x2,float y2,float x3,fl
float CD=((y0-y2)*(x1-x0)-(x0-x2)*(y1-y0))/d;
if (CD>=0.0 && CD<=1.0)
{
- //linx=x0+AB*(x1-x0);
- //liny=y0+AB*(y1-y0);
+ // linx=x0+AB*(x1-x0);
+ // liny=y0+AB*(y1-y0);
return 1;
}
}
@@ -271,38 +271,52 @@ int LinesCross(float x0,float y0,float x1,float y1,float x2,float y2,float x3,fl
// Return: 0 = disjoint (no intersection)
// 1 = intersection in the unique point *I0
// 2 = the segment lies in the plane
-int cTracer::intersect3D_SegmentPlane( const Vector3f & a_Origin, const Vector3f & a_End, const Vector3f & a_PlanePos, const Vector3f & a_PlaneNormal )
+int cTracer::intersect3D_SegmentPlane( const Vector3f & a_Origin, const Vector3f & a_End, const Vector3f & a_PlanePos, const Vector3f & a_PlaneNormal)
{
- Vector3f u = a_End - a_Origin;//a_Ray.P1 - S.P0;
- Vector3f w = a_Origin - a_PlanePos;//S.P0 - Pn.V0;
+ Vector3f u = a_End - a_Origin; // a_Ray.P1 - S.P0;
+ Vector3f w = a_Origin - a_PlanePos; // S.P0 - Pn.V0;
- float D = a_PlaneNormal.Dot( u );//dot(Pn.n, u);
- float N = -(a_PlaneNormal.Dot( w ) );//-dot(a_Plane.n, w);
+ float D = a_PlaneNormal.Dot( u); // dot(Pn.n, u);
+ float N = -(a_PlaneNormal.Dot( w)); // -dot(a_Plane.n, w);
const float EPSILON = 0.0001f;
- if (fabs(D) < EPSILON) { // segment is parallel to plane
- if (N == 0) // segment lies in plane
+ if (fabs(D) < EPSILON)
+ {
+ // segment is parallel to plane
+ if (N == 0)
+ {
+ // segment lies in plane
return 2;
- return 0; // no intersection
+ }
+ return 0; // no intersection
}
+
// they are not parallel
// compute intersect param
float sI = N / D;
if (sI < 0 || sI > 1)
- return 0; // no intersection
+ {
+ return 0; // no intersection
+ }
- //Vector3f I ( a_Ray->GetOrigin() + sI * u );//S.P0 + sI * u; // compute segment intersect point
+ // Vector3f I ( a_Ray->GetOrigin() + sI * u);// S.P0 + sI * u; // compute segment intersect point
RealHit = a_Origin + u * sI;
return 1;
}
+
+
+
+
int cTracer::GetHitNormal(const Vector3f & start, const Vector3f & end, const Vector3i & a_BlockPos)
{
Vector3i SmallBlockPos = a_BlockPos;
- char BlockID = m_World->GetBlock( a_BlockPos.x, a_BlockPos.y, a_BlockPos.z );
+ char BlockID = m_World->GetBlock( a_BlockPos.x, a_BlockPos.y, a_BlockPos.z);
- if( BlockID == E_BLOCK_AIR || IsBlockWater(BlockID))
+ if (BlockID == E_BLOCK_AIR || IsBlockWater(BlockID))
+ {
return 0;
+ }
Vector3f BlockPos;
BlockPos = Vector3f(SmallBlockPos);
@@ -310,86 +324,86 @@ int cTracer::GetHitNormal(const Vector3f & start, const Vector3f & end, const Ve
Vector3f Look = (end - start);
Look.Normalize();
- float dot = Look.Dot( Vector3f(-1, 0, 0) ); // first face normal is x -1
- if(dot < 0)
+ float dot = Look.Dot( Vector3f(-1, 0, 0)); // first face normal is x -1
+ if (dot < 0)
{
- int Lines = LinesCross( start.x, start.y, end.x, end.y, BlockPos.x, BlockPos.y, BlockPos.x, BlockPos.y + 1 );
- if(Lines == 1)
+ int Lines = LinesCross( start.x, start.y, end.x, end.y, BlockPos.x, BlockPos.y, BlockPos.x, BlockPos.y + 1);
+ if (Lines == 1)
{
- Lines = LinesCross( start.x, start.z, end.x, end.z, BlockPos.x, BlockPos.z, BlockPos.x, BlockPos.z + 1 );
- if(Lines == 1)
+ Lines = LinesCross( start.x, start.z, end.x, end.z, BlockPos.x, BlockPos.z, BlockPos.x, BlockPos.z + 1);
+ if (Lines == 1)
{
- intersect3D_SegmentPlane( start, end, BlockPos, Vector3f(-1, 0, 0) );
+ intersect3D_SegmentPlane( start, end, BlockPos, Vector3f(-1, 0, 0));
return 1;
}
}
}
- dot = Look.Dot( Vector3f(0, 0, -1) ); // second face normal is z -1
- if(dot < 0)
+ dot = Look.Dot( Vector3f(0, 0, -1)); // second face normal is z -1
+ if (dot < 0)
{
- int Lines = LinesCross( start.z, start.y, end.z, end.y, BlockPos.z, BlockPos.y, BlockPos.z, BlockPos.y + 1 );
- if(Lines == 1)
+ int Lines = LinesCross( start.z, start.y, end.z, end.y, BlockPos.z, BlockPos.y, BlockPos.z, BlockPos.y + 1);
+ if (Lines == 1)
{
- Lines = LinesCross( start.z, start.x, end.z, end.x, BlockPos.z, BlockPos.x, BlockPos.z, BlockPos.x + 1 );
- if(Lines == 1)
+ Lines = LinesCross( start.z, start.x, end.z, end.x, BlockPos.z, BlockPos.x, BlockPos.z, BlockPos.x + 1);
+ if (Lines == 1)
{
- intersect3D_SegmentPlane( start, end, BlockPos, Vector3f(0, 0, -1) );
+ intersect3D_SegmentPlane( start, end, BlockPos, Vector3f(0, 0, -1));
return 2;
}
}
}
- dot = Look.Dot( Vector3f(1, 0, 0) ); // third face normal is x 1
- if(dot < 0)
+ dot = Look.Dot( Vector3f(1, 0, 0)); // third face normal is x 1
+ if (dot < 0)
{
- int Lines = LinesCross( start.x, start.y, end.x, end.y, BlockPos.x + 1, BlockPos.y, BlockPos.x + 1, BlockPos.y + 1 );
- if(Lines == 1)
+ int Lines = LinesCross( start.x, start.y, end.x, end.y, BlockPos.x + 1, BlockPos.y, BlockPos.x + 1, BlockPos.y + 1);
+ if (Lines == 1)
{
- Lines = LinesCross( start.x, start.z, end.x, end.z, BlockPos.x + 1, BlockPos.z, BlockPos.x + 1, BlockPos.z + 1 );
- if(Lines == 1)
+ Lines = LinesCross( start.x, start.z, end.x, end.z, BlockPos.x + 1, BlockPos.z, BlockPos.x + 1, BlockPos.z + 1);
+ if (Lines == 1)
{
- intersect3D_SegmentPlane( start, end, BlockPos + Vector3f(1, 0, 0), Vector3f(1, 0, 0) );
+ intersect3D_SegmentPlane( start, end, BlockPos + Vector3f(1, 0, 0), Vector3f(1, 0, 0));
return 3;
}
}
}
- dot = Look.Dot( Vector3f(0, 0, 1) ); // fourth face normal is z 1
- if(dot < 0)
+ dot = Look.Dot( Vector3f(0, 0, 1)); // fourth face normal is z 1
+ if (dot < 0)
{
- int Lines = LinesCross( start.z, start.y, end.z, end.y, BlockPos.z + 1, BlockPos.y, BlockPos.z + 1, BlockPos.y + 1 );
- if(Lines == 1)
+ int Lines = LinesCross( start.z, start.y, end.z, end.y, BlockPos.z + 1, BlockPos.y, BlockPos.z + 1, BlockPos.y + 1);
+ if (Lines == 1)
{
- Lines = LinesCross( start.z, start.x, end.z, end.x, BlockPos.z + 1, BlockPos.x, BlockPos.z + 1, BlockPos.x + 1 );
- if(Lines == 1)
+ Lines = LinesCross( start.z, start.x, end.z, end.x, BlockPos.z + 1, BlockPos.x, BlockPos.z + 1, BlockPos.x + 1);
+ if (Lines == 1)
{
- intersect3D_SegmentPlane( start, end, BlockPos + Vector3f(0, 0, 1), Vector3f(0, 0, 1) );
+ intersect3D_SegmentPlane( start, end, BlockPos + Vector3f(0, 0, 1), Vector3f(0, 0, 1));
return 4;
}
}
}
- dot = Look.Dot( Vector3f(0, 1, 0) ); // fifth face normal is y 1
- if(dot < 0)
+ dot = Look.Dot( Vector3f(0, 1, 0)); // fifth face normal is y 1
+ if (dot < 0)
{
- int Lines = LinesCross( start.y, start.x, end.y, end.x, BlockPos.y + 1, BlockPos.x, BlockPos.y + 1, BlockPos.x + 1 );
- if(Lines == 1)
+ int Lines = LinesCross( start.y, start.x, end.y, end.x, BlockPos.y + 1, BlockPos.x, BlockPos.y + 1, BlockPos.x + 1);
+ if (Lines == 1)
{
- Lines = LinesCross( start.y, start.z, end.y, end.z, BlockPos.y + 1, BlockPos.z, BlockPos.y + 1, BlockPos.z + 1 );
- if(Lines == 1)
+ Lines = LinesCross( start.y, start.z, end.y, end.z, BlockPos.y + 1, BlockPos.z, BlockPos.y + 1, BlockPos.z + 1);
+ if (Lines == 1)
{
- intersect3D_SegmentPlane( start, end, BlockPos + Vector3f(0, 1, 0), Vector3f(0, 1, 0) );
+ intersect3D_SegmentPlane( start, end, BlockPos + Vector3f(0, 1, 0), Vector3f(0, 1, 0));
return 5;
}
}
}
- dot = Look.Dot( Vector3f(0, -1, 0) ); // sixth face normal is y -1
- if(dot < 0)
+ dot = Look.Dot( Vector3f(0, -1, 0)); // sixth face normal is y -1
+ if (dot < 0)
{
- int Lines = LinesCross( start.y, start.x, end.y, end.x, BlockPos.y, BlockPos.x, BlockPos.y, BlockPos.x + 1 );
- if(Lines == 1)
+ int Lines = LinesCross( start.y, start.x, end.y, end.x, BlockPos.y, BlockPos.x, BlockPos.y, BlockPos.x + 1);
+ if (Lines == 1)
{
- Lines = LinesCross( start.y, start.z, end.y, end.z, BlockPos.y, BlockPos.z, BlockPos.y, BlockPos.z + 1 );
- if(Lines == 1)
+ Lines = LinesCross( start.y, start.z, end.y, end.z, BlockPos.y, BlockPos.z, BlockPos.y, BlockPos.z + 1);
+ if (Lines == 1)
{
- intersect3D_SegmentPlane( start, end, BlockPos, Vector3f(0, -1, 0) );
+ intersect3D_SegmentPlane( start, end, BlockPos, Vector3f(0, -1, 0));
return 6;
}
}
diff --git a/src/Tracer.h b/src/Tracer.h
index bdb080f0d..ec87d449e 100644
--- a/src/Tracer.h
+++ b/src/Tracer.h
@@ -48,20 +48,20 @@ public:
private:
/// Preps Tracer object for call of Trace function. Only used internally.
- void SetValues( const Vector3f & a_Start, const Vector3f & a_Direction );
+ void SetValues( const Vector3f & a_Start, const Vector3f & a_Direction);
/// Calculates where on the block a collision occured, if it does occur
/// Returns 0 if no intersection occured
/// Returns 1 if an intersection occured at a single point
- /// Returns 2 if the line segment lies in the plane being checked
- int intersect3D_SegmentPlane( const Vector3f & a_Origin, const Vector3f & a_End, const Vector3f & a_PlanePos, const Vector3f & a_PlaneNormal );
+ /// Returns 2 if the line segment lies in the plane being checked
+ int intersect3D_SegmentPlane( const Vector3f & a_Origin, const Vector3f & a_End, const Vector3f & a_PlanePos, const Vector3f & a_PlaneNormal);
/// Determines which face on the block a collision occured, if it does occur
/// Returns 0 if the block is air, water or no collision occured
/// Return 1 through 6 for the following block faces, repectively: -x, -z, x, z, y, -y
int GetHitNormal( const Vector3f & start, const Vector3f & end, const Vector3i & a_BlockPos);
- float SigNum( float a_Num );
+ float SigNum( float a_Num);
cWorld* m_World;
Vector3f m_NormalTable[6];
diff --git a/src/UI/CMakeLists.txt b/src/UI/CMakeLists.txt
index 5b5b8cc18..2b094ef1d 100644
--- a/src/UI/CMakeLists.txt
+++ b/src/UI/CMakeLists.txt
@@ -4,9 +4,15 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ SlotArea.cpp
+ Window.cpp)
-add_library(UI ${SOURCE})
+SET (HDRS
+ SlotArea.h
+ Window.h
+ WindowOwner.h)
+
+if(NOT MSVC)
+ add_library(UI ${SRCS} ${HDRS})
+endif()
diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp
index e220960ff..4199bbf56 100644
--- a/src/UI/SlotArea.cpp
+++ b/src/UI/SlotArea.cpp
@@ -5,6 +5,7 @@
#include "Globals.h"
#include "SlotArea.h"
#include "../Entities/Player.h"
+#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/EnderChestEntity.h"
@@ -20,7 +21,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotArea:
cSlotArea::cSlotArea(int a_NumSlots, cWindow & a_ParentWindow) :
@@ -36,8 +37,8 @@ cSlotArea::cSlotArea(int a_NumSlots, cWindow & a_ParentWindow) :
void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
{
/*
- LOGD("Slot area with %d slots clicked at slot number %d, clicked item %s, slot item %s",
- GetNumSlots(), a_SlotNum,
+ LOGD("Slot area with %d slots clicked at slot number %d, clicked item %s, slot item %s",
+ GetNumSlots(), a_SlotNum,
ItemToFullString(a_ClickedItem).c_str(),
ItemToFullString(*GetSlot(a_SlotNum, a_Player)).c_str()
);
@@ -108,9 +109,9 @@ void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickA
{
case caRightClick:
{
- if (DraggingItem.m_ItemType <= 0) // Empty-handed?
+ if (DraggingItem.m_ItemType <= 0) // Empty-handed?
{
- DraggingItem = Slot.CopyOne(); // Obtain copy of slot to preserve lore, enchantments, etc.
+ DraggingItem = Slot.CopyOne(); // Obtain copy of slot to preserve lore, enchantments, etc.
DraggingItem.m_ItemCount = (char)(((float)Slot.m_ItemCount) / 2.f + 0.5f);
Slot.m_ItemCount -= DraggingItem.m_ItemCount;
@@ -128,7 +129,7 @@ void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickA
{
char OldSlotCount = Slot.m_ItemCount;
- Slot = DraggingItem.CopyOne(); // See above
+ Slot = DraggingItem.CopyOne(); // See above
OldSlotCount++;
Slot.m_ItemCount = OldSlotCount;
@@ -409,7 +410,7 @@ bool cSlotArea::CollectItemsToHand(cItem & a_Dragging, cPlayer & a_Player, bool
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaChest:
cSlotAreaChest::cSlotAreaChest(cChestEntity * a_Chest, cWindow & a_ParentWindow) :
@@ -441,7 +442,7 @@ void cSlotAreaChest::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaDoubleChest:
cSlotAreaDoubleChest::cSlotAreaDoubleChest(cChestEntity * a_TopChest, cChestEntity * a_BottomChest, cWindow & a_ParentWindow) :
@@ -488,7 +489,7 @@ void cSlotAreaDoubleChest::SetSlot(int a_SlotNum, cPlayer & a_Player, const cIte
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaCrafting:
cSlotAreaCrafting::cSlotAreaCrafting(int a_GridSize, cWindow & a_ParentWindow) :
@@ -764,7 +765,7 @@ void cSlotAreaCrafting::HandleCraftItem(const cItem & a_Result, cPlayer & a_Play
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaAnvil:
cSlotAreaAnvil::cSlotAreaAnvil(cAnvilWindow & a_ParentWindow) :
@@ -1190,8 +1191,202 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
+////////////////////////////////////////////////////////////////////////////////
+// cSlotAreaBeacon:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+cSlotAreaBeacon::cSlotAreaBeacon(cBeaconEntity * a_Beacon, cWindow & a_ParentWindow) :
+ cSlotArea(1, a_ParentWindow),
+ m_Beacon(a_Beacon)
+{
+ m_Beacon->GetContents().AddListener(*this);
+}
+
+
+
+
+
+cSlotAreaBeacon::~cSlotAreaBeacon()
+{
+ m_Beacon->GetContents().RemoveListener(*this);
+}
+
+
+
+
+bool cSlotAreaBeacon::IsPlaceableItem(short a_ItemType)
+{
+ switch (a_ItemType)
+ {
+ case E_ITEM_EMERALD:
+ case E_ITEM_DIAMOND:
+ case E_ITEM_GOLD:
+ case E_ITEM_IRON:
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
+void cSlotAreaBeacon::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
+{
+ ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots()));
+
+ bool bAsync = false;
+ if (GetSlot(a_SlotNum, a_Player) == NULL)
+ {
+ LOGWARNING("GetSlot(%d) returned NULL! Ignoring click", a_SlotNum);
+ return;
+ }
+
+ switch (a_ClickAction)
+ {
+ case caShiftLeftClick:
+ case caShiftRightClick:
+ {
+ ShiftClicked(a_Player, a_SlotNum, a_ClickedItem);
+ return;
+ }
+ case caMiddleClick:
+ {
+ MiddleClicked(a_Player, a_SlotNum);
+ return;
+ }
+ case caDropKey:
+ case caCtrlDropKey:
+ {
+ DropClicked(a_Player, a_SlotNum, false);
+ return;
+ }
+ case caNumber1:
+ case caNumber2:
+ case caNumber3:
+ case caNumber4:
+ case caNumber5:
+ case caNumber6:
+ case caNumber7:
+ case caNumber8:
+ case caNumber9:
+ {
+ NumberClicked(a_Player, a_SlotNum, a_ClickAction);
+ return;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ cItem Slot(*GetSlot(a_SlotNum, a_Player));
+ if (!Slot.IsSameType(a_ClickedItem))
+ {
+ LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots);
+ LOGWARNING("My item: %s", ItemToFullString(Slot).c_str());
+ LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str());
+ bAsync = true;
+ }
+ cItem & DraggingItem = a_Player.GetDraggingItem();
+
+ if (DraggingItem.IsEmpty())
+ {
+ DraggingItem = Slot;
+ Slot.Empty();
+ }
+ else if (Slot.IsEmpty())
+ {
+ if (!IsPlaceableItem(DraggingItem.m_ItemType))
+ {
+ return;
+ }
+
+ Slot = DraggingItem.CopyOne();
+ DraggingItem.m_ItemCount -= 1;
+ if (DraggingItem.m_ItemCount <= 0)
+ {
+ DraggingItem.Empty();
+ }
+ }
+ else if (DraggingItem.m_ItemCount == 1)
+ {
+ if (!IsPlaceableItem(DraggingItem.m_ItemCount))
+ {
+ return;
+ }
+
+ // Switch contents
+ cItem tmp(DraggingItem);
+ DraggingItem = Slot;
+ Slot = tmp;
+ }
+
+ SetSlot(a_SlotNum, a_Player, Slot);
+ if (bAsync)
+ {
+ m_ParentWindow.BroadcastWholeWindow();
+ }
+}
+
+
+
+
+
+void cSlotAreaBeacon::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
+{
+ const cItem * Slot = GetSlot(0, a_Player);
+ if (!Slot->IsEmpty() || !IsPlaceableItem(a_ItemStack.m_ItemType) || (a_ItemStack.m_ItemCount != 1))
+ {
+ return;
+ }
+
+ if (a_ShouldApply)
+ {
+ SetSlot(0, a_Player, a_ItemStack.CopyOne());
+ }
+ a_ItemStack.Empty();
+}
+
+
+
+
+
+const cItem * cSlotAreaBeacon::GetSlot(int a_SlotNum, cPlayer & a_Player) const
+{
+ UNUSED(a_Player);
+ return &(m_Beacon->GetSlot(a_SlotNum));
+}
+
+
+
+
+
+void cSlotAreaBeacon::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
+{
+ UNUSED(a_Player);
+ m_Beacon->SetSlot(a_SlotNum, a_Item);
+}
+
+
+
+
+
+void cSlotAreaBeacon::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
+{
+ UNUSED(a_SlotNum);
+ // Something has changed in the window, broadcast the entire window to all clients
+ ASSERT(a_ItemGrid == &(m_Beacon->GetContents()));
+
+ m_ParentWindow.BroadcastWholeWindow();
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaEnchanting:
cSlotAreaEnchanting::cSlotAreaEnchanting(cEnchantingWindow & a_ParentWindow) :
@@ -1280,7 +1475,7 @@ void cSlotAreaEnchanting::Clicked(cPlayer & a_Player, int a_SlotNum, eClickActio
}
case caLeftClick:
- {
+ {
// Left-clicked
if (DraggingItem.IsEmpty())
{
@@ -1496,7 +1691,7 @@ int cSlotAreaEnchanting::GetBookshelvesCount(cWorld * a_World)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaEnderChest:
cSlotAreaEnderChest::cSlotAreaEnderChest(cEnderChestEntity * a_EnderChest, cWindow & a_ParentWindow) :
@@ -1527,7 +1722,7 @@ void cSlotAreaEnderChest::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaFurnace:
cSlotAreaFurnace::cSlotAreaFurnace(cFurnaceEntity * a_Furnace, cWindow & a_ParentWindow) :
@@ -1763,7 +1958,7 @@ void cSlotAreaFurnace::HandleSmeltItem(const cItem & a_Result, cPlayer & a_Playe
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaInventoryBase:
cSlotAreaInventoryBase::cSlotAreaInventoryBase(int a_NumSlots, int a_SlotOffset, cWindow & a_ParentWindow) :
@@ -1819,7 +2014,7 @@ void cSlotAreaInventoryBase::SetSlot(int a_SlotNum, cPlayer & a_Player, const cI
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaArmor:
void cSlotAreaArmor::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots)
@@ -1866,6 +2061,19 @@ void cSlotAreaArmor::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_C
{
ASSERT((a_SlotNum >= 0) && (a_SlotNum < GetNumSlots()));
+ // When the player is in creative mode, the client sends the new item as a_ClickedItem, not the current item in the slot.
+ if (a_Player.IsGameModeCreative() && (m_ParentWindow.GetWindowType() == cWindow::wtInventory))
+ {
+ if ((a_ClickAction == caDropKey) || (a_ClickAction == caCtrlDropKey))
+ {
+ DropClicked(a_Player, a_SlotNum, (a_ClickAction == caCtrlDropKey));
+ return;
+ }
+
+ SetSlot(a_SlotNum, a_Player, a_ClickedItem);
+ return;
+ }
+
bool bAsync = false;
if (GetSlot(a_SlotNum, a_Player) == NULL)
{
@@ -1913,7 +2121,7 @@ void cSlotAreaArmor::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_C
return;
}
- if (DraggingItem.IsEmpty() || CanPlaceInSlot(a_SlotNum, DraggingItem))
+ if (DraggingItem.IsEmpty() || CanPlaceArmorInSlot(a_SlotNum, DraggingItem))
{
// Swap contents
cItem tmp(DraggingItem);
@@ -1932,7 +2140,7 @@ void cSlotAreaArmor::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_C
-bool cSlotAreaArmor::CanPlaceInSlot(int a_SlotNum, const cItem & a_Item)
+bool cSlotAreaArmor::CanPlaceArmorInSlot(int a_SlotNum, const cItem & a_Item)
{
switch (a_SlotNum)
{
@@ -1948,7 +2156,7 @@ bool cSlotAreaArmor::CanPlaceInSlot(int a_SlotNum, const cItem & a_Item)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaItemGrid:
cSlotAreaItemGrid::cSlotAreaItemGrid(cItemGrid & a_ItemGrid, cWindow & a_ParentWindow) :
@@ -1999,7 +2207,7 @@ void cSlotAreaItemGrid::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSlotAreaTemporary:
cSlotAreaTemporary::cSlotAreaTemporary(int a_NumSlots, cWindow & a_ParentWindow) :
@@ -2104,7 +2312,7 @@ void cSlotAreaTemporary::TossItems(cPlayer & a_Player, int a_Begin, int a_End)
double vX = 0, vY = 0, vZ = 0;
EulerToVector(-a_Player.GetYaw(), a_Player.GetPitch(), vZ, vX, vY);
vY = -vY * 2 + 1.f;
- a_Player.GetWorld()->SpawnItemPickups(Drops, a_Player.GetPosX(), a_Player.GetPosY() + 1.6f, a_Player.GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because player created
+ a_Player.GetWorld()->SpawnItemPickups(Drops, a_Player.GetPosX(), a_Player.GetPosY() + 1.6f, a_Player.GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because player created
}
diff --git a/src/UI/SlotArea.h b/src/UI/SlotArea.h
index 3dc5c3849..9a96f2f3c 100644
--- a/src/UI/SlotArea.h
+++ b/src/UI/SlotArea.h
@@ -15,6 +15,7 @@
class cWindow;
class cPlayer;
+class cBeaconEntity;
class cChestEntity;
class cDropSpenserEntity;
class cEnderChestEntity;
@@ -135,7 +136,7 @@ class cSlotAreaHotBar :
typedef cSlotAreaInventoryBase super;
public:
- cSlotAreaHotBar(cWindow & a_ParentWindow) :
+ cSlotAreaHotBar(cWindow & a_ParentWindow) :
cSlotAreaInventoryBase(cInventory::invHotbarCount, cInventory::invHotbarOffset, a_ParentWindow)
{
}
@@ -150,7 +151,7 @@ class cSlotAreaArmor :
public cSlotAreaInventoryBase
{
public:
- cSlotAreaArmor(cWindow & a_ParentWindow) :
+ cSlotAreaArmor(cWindow & a_ParentWindow) :
cSlotAreaInventoryBase(cInventory::invArmorCount, cInventory::invArmorOffset, a_ParentWindow)
{
}
@@ -161,7 +162,7 @@ public:
/** Called when a player clicks in the window. Parameters taken from the click packet. */
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
- bool CanPlaceInSlot(int a_SlotNum, const cItem & a_Item);
+ static bool CanPlaceArmorInSlot(int a_SlotNum, const cItem & a_Item);
} ;
@@ -314,6 +315,34 @@ protected:
+class cSlotAreaBeacon :
+ public cSlotArea,
+ public cItemGrid::cListener
+{
+ typedef cSlotArea super;
+
+public:
+ cSlotAreaBeacon(cBeaconEntity * a_Beacon, cWindow & a_ParentWindow);
+ virtual ~cSlotAreaBeacon();
+
+ bool IsPlaceableItem(short a_ItemType);
+
+ virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
+ virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots) override;
+ virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override;
+ virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
+
+protected:
+ cBeaconEntity * m_Beacon;
+
+ // cItemGrid::cListener overrides:
+ virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override;
+} ;
+
+
+
+
+
class cSlotAreaEnchanting :
public cSlotAreaTemporary
{
diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp
index ebdc1aea8..8f4913030 100644
--- a/src/UI/Window.cpp
+++ b/src/UI/Window.cpp
@@ -9,6 +9,7 @@
#include "../Entities/Pickup.h"
#include "../Inventory.h"
#include "../Items/ItemHandler.h"
+#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/EnderChestEntity.h"
@@ -145,7 +146,7 @@ void cWindow::GetSlots(cPlayer & a_Player, cItems & a_Slots) const
{
int NumSlots = (*itr)->GetNumSlots();
for (int i = 0; i < NumSlots; i++)
- {
+ {
const cItem * Item = (*itr)->GetSlot(i, a_Player);
if (Item == NULL)
{
@@ -164,7 +165,7 @@ void cWindow::GetSlots(cPlayer & a_Player, cItems & a_Slots) const
void cWindow::Clicked(
- cPlayer & a_Player,
+ cPlayer & a_Player,
int a_WindowID, short a_SlotNum, eClickAction a_ClickAction,
const cItem & a_ClickedItem
)
@@ -274,7 +275,7 @@ void cWindow::OpenedByPlayer(cPlayer & a_Player)
bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
{
// Checks whether the player is still holding an item
- if (a_Player.IsDraggingItem())
+ if (!a_Player.GetDraggingItem().IsEmpty())
{
LOGD("Player holds item! Dropping it...");
a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount);
@@ -319,9 +320,9 @@ void cWindow::OwnerDestroyed()
// Close window for each player. Note that the last one needs special handling
while (m_OpenedBy.size() > 1)
{
- (*m_OpenedBy.begin() )->CloseWindow();
+ (*m_OpenedBy.begin())->CloseWindow();
}
- (*m_OpenedBy.begin() )->CloseWindow();
+ (*m_OpenedBy.begin())->CloseWindow();
}
@@ -763,7 +764,7 @@ void cWindow::SetProperty(int a_Property, int a_Value, cPlayer & a_Player)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cInventoryWindow:
cInventoryWindow::cInventoryWindow(cPlayer & a_Player) :
@@ -780,7 +781,7 @@ cInventoryWindow::cInventoryWindow(cPlayer & a_Player) :
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cCraftingWindow:
cCraftingWindow::cCraftingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
@@ -795,7 +796,7 @@ cCraftingWindow::cCraftingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cAnvilWindow:
cAnvilWindow::cAnvilWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
@@ -840,7 +841,37 @@ void cAnvilWindow::GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// cBeaconWindow:
+
+cBeaconWindow::cBeaconWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconEntity * a_Beacon) :
+ cWindow(wtBeacon, "Beacon"),
+ m_Beacon(a_Beacon)
+{
+ m_ShouldDistributeToHotbarFirst = true;
+ m_SlotAreas.push_back(new cSlotAreaBeacon(m_Beacon, *this));
+ m_SlotAreas.push_back(new cSlotAreaInventory(*this));
+ m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
+}
+
+
+
+
+
+void cBeaconWindow::OpenedByPlayer(cPlayer & a_Player)
+{
+ super::OpenedByPlayer(a_Player);
+
+ a_Player.GetClientHandle()->SendWindowProperty(*this, 0, m_Beacon->GetBeaconLevel());
+ a_Player.GetClientHandle()->SendWindowProperty(*this, 1, m_Beacon->GetPrimaryEffect());
+ a_Player.GetClientHandle()->SendWindowProperty(*this, 2, m_Beacon->GetSecondaryEffect());
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
// cEnchantingWindow:
cEnchantingWindow::cEnchantingWindow(int a_BlockX, int a_BlockY, int a_BlockZ) :
@@ -901,25 +932,27 @@ void cEnchantingWindow::GetBlockPos(int & a_PosX, int & a_PosY, int & a_PosZ)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cChestWindow:
cChestWindow::cChestWindow(cChestEntity * a_Chest) :
- cWindow(wtChest, "Chest"),
+ cWindow(wtChest, (a_Chest->GetBlockType() == E_BLOCK_CHEST) ? "Chest" : "Trapped Chest"),
m_World(a_Chest->GetWorld()),
m_BlockX(a_Chest->GetPosX()),
m_BlockY(a_Chest->GetPosY()),
- m_BlockZ(a_Chest->GetPosZ())
+ m_BlockZ(a_Chest->GetPosZ()),
+ m_PrimaryChest(a_Chest),
+ m_SecondaryChest(NULL)
{
m_SlotAreas.push_back(new cSlotAreaChest(a_Chest, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
// Play the opening sound:
- m_World->BroadcastSoundEffect("random.chestopen", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
+ m_World->BroadcastSoundEffect("random.chestopen", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
// Send out the chest-open packet:
- m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_CHEST);
+ m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, a_Chest->GetBlockType());
}
@@ -927,11 +960,13 @@ cChestWindow::cChestWindow(cChestEntity * a_Chest) :
cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest) :
- cWindow(wtChest, "Double Chest"),
+ cWindow(wtChest, (a_PrimaryChest->GetBlockType() == E_BLOCK_CHEST) ? "Double Chest" : "Double Trapped Chest"),
m_World(a_PrimaryChest->GetWorld()),
m_BlockX(a_PrimaryChest->GetPosX()),
m_BlockY(a_PrimaryChest->GetPosY()),
- m_BlockZ(a_PrimaryChest->GetPosZ())
+ m_BlockZ(a_PrimaryChest->GetPosZ()),
+ m_PrimaryChest(a_PrimaryChest),
+ m_SecondaryChest(a_SecondaryChest)
{
m_SlotAreas.push_back(new cSlotAreaDoubleChest(a_PrimaryChest, a_SecondaryChest, *this));
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
@@ -940,10 +975,55 @@ cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_Secon
m_ShouldDistributeToHotbarFirst = false;
// Play the opening sound:
- m_World->BroadcastSoundEffect("random.chestopen", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
+ m_World->BroadcastSoundEffect("random.chestopen", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
// Send out the chest-open packet:
- m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_CHEST);
+ m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, a_PrimaryChest->GetBlockType());
+}
+
+
+
+
+
+void cChestWindow::OpenedByPlayer(cPlayer & a_Player)
+{
+ int ChunkX, ChunkZ;
+
+ m_PrimaryChest->SetNumberOfPlayers(m_PrimaryChest->GetNumberOfPlayers() + 1);
+ cChunkDef::BlockToChunk(m_PrimaryChest->GetPosX(), m_PrimaryChest->GetPosZ(), ChunkX, ChunkZ);
+ m_PrimaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
+
+ if (m_SecondaryChest != NULL)
+ {
+ m_SecondaryChest->SetNumberOfPlayers(m_SecondaryChest->GetNumberOfPlayers() + 1);
+ cChunkDef::BlockToChunk(m_SecondaryChest->GetPosX(), m_SecondaryChest->GetPosZ(), ChunkX, ChunkZ);
+ m_SecondaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
+ }
+
+ cWindow::OpenedByPlayer(a_Player);
+}
+
+
+
+
+
+bool cChestWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
+{
+ int ChunkX, ChunkZ;
+
+ m_PrimaryChest->SetNumberOfPlayers(m_PrimaryChest->GetNumberOfPlayers() - 1);
+ cChunkDef::BlockToChunk(m_PrimaryChest->GetPosX(), m_PrimaryChest->GetPosZ(), ChunkX, ChunkZ);
+ m_PrimaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
+
+ if (m_SecondaryChest != NULL)
+ {
+ m_SecondaryChest->SetNumberOfPlayers(m_SecondaryChest->GetNumberOfPlayers() - 1);
+ cChunkDef::BlockToChunk(m_SecondaryChest->GetPosX(), m_SecondaryChest->GetPosZ(), ChunkX, ChunkZ);
+ m_SecondaryChest->GetWorld()->MarkRedstoneDirty(ChunkX, ChunkZ);
+ }
+
+ cWindow::ClosedByPlayer(a_Player, a_CanRefuse);
+ return true;
}
@@ -953,20 +1033,20 @@ cChestWindow::cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_Secon
cChestWindow::~cChestWindow()
{
// Send out the chest-close packet:
- m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, E_BLOCK_CHEST);
+ m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, m_PrimaryChest->GetBlockType());
- m_World->BroadcastSoundEffect("random.chestclosed", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
+ m_World->BroadcastSoundEffect("random.chestclosed", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
}
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cDropSpenserWindow:
cDropSpenserWindow::cDropSpenserWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserEntity * a_DropSpenser) :
- cWindow(wtDropSpenser, "Dropspenser")
+ cWindow(wtDropSpenser, (a_DropSpenser->GetBlockType() == E_BLOCK_DISPENSER) ? "Dispenser" : "Dropper")
{
m_ShouldDistributeToHotbarFirst = false;
m_SlotAreas.push_back(new cSlotAreaItemGrid(a_DropSpenser->GetContents(), *this));
@@ -978,7 +1058,7 @@ cDropSpenserWindow::cDropSpenserWindow(int a_BlockX, int a_BlockY, int a_BlockZ,
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cEnderChestWindow:
cEnderChestWindow::cEnderChestWindow(cEnderChestEntity * a_EnderChest) :
@@ -993,7 +1073,7 @@ cEnderChestWindow::cEnderChestWindow(cEnderChestEntity * a_EnderChest) :
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
// Play the opening sound:
- m_World->BroadcastSoundEffect("random.chestopen", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
+ m_World->BroadcastSoundEffect("random.chestopen", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
// Send out the chest-open packet:
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 1, E_BLOCK_ENDER_CHEST);
@@ -1009,14 +1089,14 @@ cEnderChestWindow::~cEnderChestWindow()
m_World->BroadcastBlockAction(m_BlockX, m_BlockY, m_BlockZ, 1, 0, E_BLOCK_ENDER_CHEST);
// Play the closing sound
- m_World->BroadcastSoundEffect("random.chestclosed", m_BlockX * 8, m_BlockY * 8, m_BlockZ * 8, 1, 1);
+ m_World->BroadcastSoundEffect("random.chestclosed", (double)m_BlockX, (double)m_BlockY, (double)m_BlockZ, 1, 1);
}
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cHopperWindow:
cHopperWindow::cHopperWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperEntity * a_Hopper) :
@@ -1032,7 +1112,7 @@ cHopperWindow::cHopperWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperEn
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFurnaceWindow:
cFurnaceWindow::cFurnaceWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceEntity * a_Furnace) :
diff --git a/src/UI/Window.h b/src/UI/Window.h
index 542dccb88..9fb0e3b38 100644
--- a/src/UI/Window.h
+++ b/src/UI/Window.h
@@ -23,6 +23,7 @@ class cDropSpenserEntity;
class cEnderChestEntity;
class cFurnaceEntity;
class cHopperEntity;
+class cBeaconEntity;
class cSlotArea;
class cSlotAreaAnvil;
class cWorld;
@@ -36,12 +37,12 @@ typedef std::vector<cSlotArea *> cSlotAreas;
// tolua_begin
-/**
+/**
Represents a UI window.
Each window has a list of players that are currently using it
When there's no player using a window, it is destroyed.
-A window consists of several areas of slots with similar functionality - for example the crafting grid area, or
+A window consists of several areas of slots with similar functionality - for example the crafting grid area, or
the inventory area. Each area knows what its slots are (GetSlot() function) and can handle mouse clicks.
The window acts only as a top-level container for those areas, redirecting the click events to the correct areas.
Inventory painting, introduced in 1.5, is handled by the window, too
@@ -77,7 +78,7 @@ public:
int GetWindowType(void) const { return m_WindowType; } // tolua_export
cWindowOwner * GetOwner(void) { return m_Owner; }
- void SetOwner( cWindowOwner * a_Owner ) { m_Owner = a_Owner; }
+ void SetOwner( cWindowOwner * a_Owner) { m_Owner = a_Owner; }
/// Returns the total number of slots
int GetNumSlots(void) const;
@@ -109,12 +110,12 @@ public:
/// Handles a click event from a player
void Clicked(
- cPlayer & a_Player, int a_WindowID,
+ cPlayer & a_Player, int a_WindowID,
short a_SlotNum, eClickAction a_ClickAction,
const cItem & a_ClickedItem
);
- void OpenedByPlayer(cPlayer & a_Player);
+ virtual void OpenedByPlayer(cPlayer & a_Player);
/// Called when a player closes this window; notifies all slot areas. Returns true if close accepted
virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse);
@@ -134,7 +135,7 @@ public:
// tolua_begin
const AString & GetWindowTitle() const { return m_WindowTitle; }
- void SetWindowTitle(const AString & a_WindowTitle ) { m_WindowTitle = a_WindowTitle; }
+ void SetWindowTitle(const AString & a_WindowTitle) { m_WindowTitle = a_WindowTitle; }
/// Sends the UpdateWindowProperty (0x69) packet to all clients of the window
virtual void SetProperty(int a_Property, int a_Value);
@@ -258,6 +259,26 @@ protected:
+class cBeaconWindow :
+ public cWindow
+{
+ typedef cWindow super;
+public:
+ cBeaconWindow(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconEntity * a_Beacon);
+
+ cBeaconEntity * GetBeaconEntity(void) const { return m_Beacon; }
+
+ // cWindow Overrides:
+ virtual void OpenedByPlayer(cPlayer & a_Player) override;
+
+protected:
+ cBeaconEntity * m_Beacon;
+} ;
+
+
+
+
+
class cEnchantingWindow :
public cWindow
{
@@ -327,10 +348,15 @@ public:
cChestWindow(cChestEntity * a_Chest);
cChestWindow(cChestEntity * a_PrimaryChest, cChestEntity * a_SecondaryChest);
~cChestWindow();
+
+ virtual bool ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse) override;
+ virtual void OpenedByPlayer(cPlayer & a_Player) override;
protected:
cWorld * m_World;
int m_BlockX, m_BlockY, m_BlockZ; // Position of the chest, for the window-close packet
+ cChestEntity * m_PrimaryChest;
+ cChestEntity * m_SecondaryChest;
} ;
diff --git a/src/UI/WindowOwner.h b/src/UI/WindowOwner.h
index e3c73edc4..7a7941e37 100644
--- a/src/UI/WindowOwner.h
+++ b/src/UI/WindowOwner.h
@@ -6,7 +6,7 @@
#include "Window.h"
/*
-Being a descendant of cWindowOwner means that the class can own one window. That window can be
+Being a descendant of cWindowOwner means that the class can own one window. That window can be
queried, opened by other players, closed by players and finally destroyed.
Also, a cWindowOwner can be queried for the block coords where the window is displayed. That will be used
for entities / players in motion to close their windows when they get too far away from the window "source".
diff --git a/src/Vector3.h b/src/Vector3.h
index c175bf135..1dcb38f64 100644
--- a/src/Vector3.h
+++ b/src/Vector3.h
@@ -3,7 +3,7 @@
-#define _USE_MATH_DEFINES // Enable non-standard math defines (MSVC)
+#define _USE_MATH_DEFINES // Enable non-standard math defines (MSVC)
#include <math.h>
#include <list>
#include <vector>
diff --git a/src/WebAdmin.cpp b/src/WebAdmin.cpp
index d80849433..23eedbd14 100644
--- a/src/WebAdmin.cpp
+++ b/src/WebAdmin.cpp
@@ -159,28 +159,6 @@ void cWebAdmin::Stop(void)
-AString cWebAdmin::GetTemplate()
-{
- AString retVal = "";
-
- char SourceFile[] = "webadmin/template.html";
-
- cFile f;
- if (!f.Open(SourceFile, cFile::fmRead))
- {
- return "";
- }
-
- // copy the file into the buffer:
- f.ReadRestOfFile(retVal);
-
- return retVal;
-}
-
-
-
-
-
void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
{
if (!a_Request.HasAuth())
@@ -198,9 +176,9 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
}
// Check if the contents should be wrapped in the template:
- AString URL = a_Request.GetBareURL();
- ASSERT(URL.length() > 0);
- bool ShouldWrapInTemplate = ((URL.length() > 1) && (URL[1] != '~'));
+ AString BareURL = a_Request.GetBareURL();
+ ASSERT(BareURL.length() > 0);
+ bool ShouldWrapInTemplate = ((BareURL.length() > 1) && (BareURL[1] != '~'));
// Retrieve the request data:
cWebadminRequestData * Data = (cWebadminRequestData *)(a_Request.GetUserData());
@@ -215,7 +193,7 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
HTTPTemplateRequest TemplateRequest;
TemplateRequest.Request.Username = a_Request.GetAuthUsername();
TemplateRequest.Request.Method = a_Request.GetMethod();
- TemplateRequest.Request.Path = URL.substr(1);
+ TemplateRequest.Request.Path = BareURL.substr(1);
if (Data->m_Form.Finish())
{
@@ -258,7 +236,7 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
return;
}
- AString BaseURL = GetBaseURL(URL);
+ AString BaseURL = GetBaseURL(BareURL);
AString Menu;
Template = "{CONTENT}";
AString FoundPlugin;
@@ -374,7 +352,7 @@ AString cWebAdmin::GetDefaultPage(void)
{
AString Content;
Content += "<h4>Server Name:</h4>";
- Content += "<p>" + AString( cRoot::Get()->GetServer()->GetServerID() ) + "</p>";
+ Content += "<p>" + AString( cRoot::Get()->GetServer()->GetServerID()) + "</p>";
Content += "<h4>Plugins:</h4><ul>";
cPluginManager * PM = cPluginManager::Get();
@@ -391,8 +369,8 @@ AString cWebAdmin::GetDefaultPage(void)
Content += "<h4>Players:</h4><ul>";
cPlayerAccum PlayerAccum;
- cWorld * World = cRoot::Get()->GetDefaultWorld(); // TODO - Create a list of worlds and players
- if( World != NULL )
+ cWorld * World = cRoot::Get()->GetDefaultWorld(); // TODO - Create a list of worlds and players
+ if (World != NULL)
{
World->ForEachPlayer(PlayerAccum);
Content.append(PlayerAccum.m_Contents);
@@ -404,7 +382,7 @@ AString cWebAdmin::GetDefaultPage(void)
-AString cWebAdmin::GetBaseURL( const AString& a_URL )
+AString cWebAdmin::GetBaseURL( const AString& a_URL)
{
return GetBaseURL(StringSplit(a_URL, "/"));
}
@@ -444,6 +422,38 @@ AString cWebAdmin::GetHTMLEscapedString(const AString & a_Input)
+AString cWebAdmin::GetURLEncodedString(const AString & a_Input)
+{
+ // Translation table from nibble to hex:
+ static const char Hex[] = "0123456789abcdef";
+
+ // Preallocate the output to match input:
+ AString dst;
+ size_t len = a_Input.length();
+ dst.reserve(len);
+
+ // Loop over input and substitute whatever is needed:
+ for (size_t i = 0; i < len; i++)
+ {
+ char ch = a_Input[i];
+ if (isalnum(ch) || (ch == '-') || (ch == '_') || (ch == '.') || (ch == '~'))
+ {
+ dst.push_back(ch);
+ }
+ else
+ {
+ dst.push_back('%');
+ dst.push_back(Hex[(ch >> 4) & 0x0f]);
+ dst.push_back(Hex[ch & 0x0f]);
+ }
+ } // for i - a_Input[]
+ return dst;
+}
+
+
+
+
+
AString cWebAdmin::GetBaseURL(const AStringVector & a_URLSplit)
{
AString BaseURL = "./";
@@ -531,7 +541,7 @@ void cWebAdmin::OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest &
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWebAdmin::cWebadminRequestData
void cWebAdmin::cWebadminRequestData::OnBody(const char * a_Data, size_t a_Size)
diff --git a/src/WebAdmin.h b/src/WebAdmin.h
index d5e45828f..aefc1d145 100644
--- a/src/WebAdmin.h
+++ b/src/WebAdmin.h
@@ -60,11 +60,11 @@ struct HTTPRequest
StringStringMap Params; // >> EXPORTED IN MANUALBINDINGS <<
/** Parameters posted as a part of a form - either in the URL (GET method) or in the body (POST method) */
- StringStringMap PostParams; // >> EXPORTED IN MANUALBINDINGS <<
+ StringStringMap PostParams; // >> EXPORTED IN MANUALBINDINGS <<
/** Same as PostParams */
FormDataMap FormData; // >> EXPORTED IN MANUALBINDINGS <<
-} ; // tolua_export
+} ; // tolua_export
@@ -120,7 +120,7 @@ public:
void RemovePlugin(cWebPlugin * a_Plugin);
// TODO: Convert this to the auto-locking callback mechanism used for looping players in worlds and such
- PluginList GetPlugins() const { return m_Plugins; } // >> EXPORTED IN MANUALBINDINGS <<
+ PluginList GetPlugins() const { return m_Plugins; } // >> EXPORTED IN MANUALBINDINGS <<
// tolua_begin
@@ -132,16 +132,19 @@ public:
/** Returns the prefix needed for making a link point to the webadmin root from the given URL ("../../../webadmin"-style) */
AString GetBaseURL(const AString & a_URL);
- /** Escapes text passed into it, so it can be embedded into html. */
- static AString GetHTMLEscapedString(const AString & a_Input);
-
AString GetIPv4Ports(void) const { return m_PortsIPv4; }
AString GetIPv6Ports(void) const { return m_PortsIPv6; }
// tolua_end
+ /** Escapes text passed into it, so it can be embedded into html. */
+ static AString GetHTMLEscapedString(const AString & a_Input);
+
+ /** Escapes the string for use in an URL */
+ static AString GetURLEncodedString(const AString & a_Input);
+
/** Returns the prefix needed for making a link point to the webadmin root from the given URL ("../../../webadmin"-style) */
- AString GetBaseURL(const AStringVector& a_URLSplit);
+ static AString GetBaseURL(const AStringVector & a_URLSplit);
protected:
/** Common base class for request body data handlers */
@@ -205,9 +208,6 @@ protected:
/** The HTTP server which provides the underlying HTTP parsing, serialization and events */
cHTTPServer m_HTTPServer;
-
- AString GetTemplate(void);
-
/** Handles requests coming to the "/webadmin" or "/~webadmin" URLs */
void HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
@@ -218,7 +218,7 @@ protected:
virtual void OnRequestBegun (cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override;
virtual void OnRequestBody (cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) override;
virtual void OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override;
-} ; // tolua_export
+} ; // tolua_export
diff --git a/src/World.cpp b/src/World.cpp
index f91a15260..2027e215a 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -1,3 +1,4 @@
+
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "BlockID.h"
@@ -11,6 +12,7 @@
#include "ChunkMap.h"
#include "Generating/ChunkDesc.h"
#include "OSSupport/Timer.h"
+#include "SetChunkData.h"
// Serializers
#include "WorldStorage/ScoreboardSerializer.h"
@@ -24,6 +26,7 @@
#include "Entities/TNTEntity.h"
#include "BlockEntities/CommandBlockEntity.h"
+#include "BlockEntities/BeaconEntity.h"
// Simulators:
#include "Simulator/SimulatorManager.h"
@@ -70,7 +73,7 @@ const int TIME_SPAWN_DIVISOR = 148;
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWorldLoadProgress:
/// A simple thread that displays the progress of world loading / saving in cWorld::InitializeSpawn()
@@ -99,7 +102,7 @@ protected:
{
for (;;)
{
- LOG("" SIZE_T_FMT " chunks to load, %d chunks to generate",
+ LOG("" SIZE_T_FMT " chunks to load, %d chunks to generate",
m_World->GetStorage().GetLoadQueueLength(),
m_World->GetGenerator().GetQueueLength()
);
@@ -122,7 +125,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWorldLightingProgress:
/// A simple thread that displays the progress of world lighting in cWorld::InitializeSpawn()
@@ -172,7 +175,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWorld::cLock:
cWorld::cLock::cLock(cWorld & a_World) :
@@ -184,7 +187,7 @@ cWorld::cLock::cLock(cWorld & a_World) :
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWorld::cTickThread:
cWorld::cTickThread::cTickThread(cWorld & a_World) :
@@ -226,11 +229,12 @@ void cWorld::cTickThread::Execute(void)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWorld:
-cWorld::cWorld(const AString & a_WorldName) :
+cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_OverworldName) :
m_WorldName(a_WorldName),
+ m_OverworldName(a_OverworldName),
m_IniFileName(m_WorldName + "/world.ini"),
m_StorageSchema("Default"),
#ifdef __arm__
@@ -238,7 +242,9 @@ cWorld::cWorld(const AString & a_WorldName) :
#else
m_StorageCompressionFactor(6),
#endif
+ m_Dimension(a_Dimension),
m_IsSpawnExplicitlySet(false),
+ m_IsDaylightCycleEnabled(true),
m_WorldAgeSecs(0),
m_TimeOfDaySecs(0),
m_WorldAge(0),
@@ -375,22 +381,20 @@ void cWorld::SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ)
void cWorld::InitializeSpawn(void)
{
- if (!m_IsSpawnExplicitlySet) // Check if spawn position was already explicitly set or not
+ if (!m_IsSpawnExplicitlySet)
{
- GenerateRandomSpawn(); // Generate random solid-land coordinate and then write it to the world configuration
-
+ // Spawn position wasn't already explicitly set, enerate random solid-land coordinate and then write it to the world configuration:
+ GenerateRandomSpawn();
cIniFile IniFile;
IniFile.ReadFile(m_IniFileName);
-
IniFile.SetValueF("SpawnPosition", "X", m_SpawnX);
IniFile.SetValueF("SpawnPosition", "Y", m_SpawnY);
IniFile.SetValueF("SpawnPosition", "Z", m_SpawnZ);
-
IniFile.WriteFile(m_IniFileName);
}
- int ChunkX = 0, ChunkY = 0, ChunkZ = 0;
- BlockToChunk((int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ, ChunkX, ChunkY, ChunkZ);
+ int ChunkX = 0, ChunkZ = 0;
+ cChunkDef::BlockToChunk((int)m_SpawnX, (int)m_SpawnZ, ChunkX, ChunkZ);
// For the debugging builds, don't make the server build too much world upon start:
#if defined(_DEBUG) || defined(ANDROID_NDK)
@@ -519,9 +523,18 @@ void cWorld::Start(void)
if (!IniFile.ReadFile(m_IniFileName))
{
LOGWARNING("Cannot read world settings from \"%s\", defaults will be used.", m_IniFileName.c_str());
+
+ // TODO: More descriptions for each key
+ IniFile.AddHeaderComment(" This is the per-world configuration file, managing settings such as generators, simulators, and spawn points");
+ IniFile.AddKeyComment(" LinkedWorlds", "This section governs portal world linkage; leave a value blank to disabled that associated method of teleportation");
}
- AString Dimension = IniFile.GetValueSet("General", "Dimension", "Overworld");
- m_Dimension = StringToDimension(Dimension);
+
+ // The presence of a configuration value overrides everything
+ // If no configuration value is found, GetDimension() is written to file and the variable is written to again to ensure that cosmic rays haven't sneakily changed its value
+ m_Dimension = StringToDimension(IniFile.GetValueSet("General", "Dimension", DimensionToString(GetDimension())));
+
+ m_BroadcastDeathMessages = IniFile.GetValueSetB("Broadcasting", "BroadcastDeathMessages", true);
+ m_BroadcastAchievementMessages = IniFile.GetValueSetB("Broadcasting", "BroadcastAchievementMessages", true);
// Try to find the "SpawnPosition" key and coord values in the world configuration, set the flag if found
int KeyNum = IniFile.FindKey("SpawnPosition");
@@ -529,8 +542,8 @@ void cWorld::Start(void)
(
(KeyNum >= 0) &&
(
- (IniFile.FindValue(KeyNum, "X") >= 0) ||
- (IniFile.FindValue(KeyNum, "Y") >= 0) ||
+ (IniFile.FindValue(KeyNum, "X") >= 0) &&
+ (IniFile.FindValue(KeyNum, "Y") >= 0) &&
(IniFile.FindValue(KeyNum, "Z") >= 0)
)
);
@@ -565,36 +578,28 @@ void cWorld::Start(void)
m_bEnabledPVP = IniFile.GetValueSetB("Mechanics", "PVPEnabled", true);
m_bUseChatPrefixes = IniFile.GetValueSetB("Mechanics", "UseChatPrefixes", true);
m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true);
+ m_IsDaylightCycleEnabled = IniFile.GetValueSetB("General", "IsDaylightCycleEnabled", true);
int GameMode = IniFile.GetValueSetI("General", "Gamemode", (int)m_GameMode);
+ int Weather = IniFile.GetValueSetI("General", "Weather", (int)m_Weather);
- // Adjust the enum-backed variables into their respective bounds:
- m_GameMode = (eGameMode) Clamp(GameMode, (int)gmSurvival, (int)gmAdventure);
- m_TNTShrapnelLevel = (eShrapnelLevel)Clamp(TNTShrapnelLevel, (int)slNone, (int)slAll);
-
- // Load allowed mobs:
- const char * DefaultMonsters = "";
- switch (m_Dimension)
+ if (GetDimension() == dimOverworld)
{
- case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, enderman, horse, mooshroom, ocelot, pig, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break;
- case dimNether: DefaultMonsters = "blaze, ghast, magmacube, skeleton, zombie, zombiepigman"; break;
- case dimEnd: DefaultMonsters = "enderman"; break;
+ m_NetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", GetName() + "_nether");
+ m_EndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", GetName() + "_end");
}
- m_bAnimals = IniFile.GetValueSetB("Monsters", "AnimalsOn", true);
- AString AllMonsters = IniFile.GetValueSet("Monsters", "Types", DefaultMonsters);
- AStringVector SplitList = StringSplitAndTrim(AllMonsters, ",");
- for (AStringVector::const_iterator itr = SplitList.begin(), end = SplitList.end(); itr != end; ++itr)
+ else
{
- cMonster::eType ToAdd = cMonster::StringToMobType(*itr);
- if (ToAdd != cMonster::mtInvalidType)
- {
- m_AllowedMobs.insert(ToAdd);
- LOGD("Allowed mob: %s", itr->c_str());
- }
- else
- {
- LOG("World \"%s\": Unknown mob type: %s", m_WorldName.c_str(), itr->c_str());
- }
+ m_OverworldName = IniFile.GetValueSet("LinkedWorlds", "OverworldName", GetLinkedOverworldName());
}
+
+ // Adjust the enum-backed variables into their respective bounds:
+ m_GameMode = (eGameMode) Clamp(GameMode, (int)gmSurvival, (int)gmAdventure);
+ m_TNTShrapnelLevel = (eShrapnelLevel)Clamp(TNTShrapnelLevel, (int)slNone, (int)slAll);
+ m_Weather = (eWeather) Clamp(Weather, (int)wSunny, (int)wStorm);
+
+ InitialiseGeneratorDefaults(IniFile);
+ InitialiseAndLoadMobSpawningValues(IniFile);
+ SetTimeOfDay(IniFile.GetValueSetI("General", "TimeInTicks", m_TimeOfDay));
m_ChunkMap = new cChunkMap(this);
@@ -618,7 +623,7 @@ void cWorld::Start(void)
m_SimulatorManager->RegisterSimulator(m_FireSimulator, 1);
m_Lighting.Start(this);
- m_Storage.Start(this, m_StorageSchema, m_StorageCompressionFactor );
+ m_Storage.Start(this, m_StorageSchema, m_StorageCompressionFactor);
m_Generator.Start(m_GeneratorCallbacks, m_GeneratorCallbacks, IniFile);
m_ChunkSender.Start(this);
m_TickThread.Start();
@@ -648,7 +653,7 @@ void cWorld::GenerateRandomSpawn(void)
while (IsBlockWaterOrIce(GetBlock((int)m_SpawnX, GetHeight((int)m_SpawnX, (int)m_SpawnZ), (int)m_SpawnZ)))
{
- if ((GetTickRandomNumber(4) % 2) == 0) // Randomise whether to increment X or Z coords
+ if ((GetTickRandomNumber(4) % 2) == 0) // Randomise whether to increment X or Z coords
{
m_SpawnX += cChunkDef::Width;
}
@@ -658,7 +663,7 @@ void cWorld::GenerateRandomSpawn(void)
}
}
- m_SpawnY = (double)GetHeight((int)m_SpawnX, (int)m_SpawnZ) + 1.6f; // 1.6f to accomodate player height
+ m_SpawnY = (double)GetHeight((int)m_SpawnX, (int)m_SpawnZ) + 1.6f; // 1.6f to accomodate player height
LOGD("Generated random spawnpoint %i %i %i", (int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ);
}
@@ -691,6 +696,82 @@ eWeather cWorld::ChooseNewWeather()
+void cWorld::InitialiseGeneratorDefaults(cIniFile & a_IniFile)
+{
+ switch (GetDimension())
+ {
+ case dimEnd:
+ {
+ a_IniFile.GetValueSet("Generator", "BiomeGen", "Constant");
+ a_IniFile.GetValueSet("Generator", "ConstantBiome", "End");
+ a_IniFile.GetValueSet("Generator", "HeightGen", "Biomal");
+ a_IniFile.GetValueSet("Generator", "CompositionGen", "End");
+ break;
+ }
+ case dimOverworld:
+ {
+ a_IniFile.GetValueSet("Generator", "BiomeGen", "MultiStepMap");
+ a_IniFile.GetValueSet("Generator", "HeightGen", "DistortedHeightmap");
+ a_IniFile.GetValueSet("Generator", "CompositionGen", "DistortedHeightmap");
+ a_IniFile.GetValueSet("Generator", "Finishers", "Ravines, WormNestCaves, WaterLakes, WaterSprings, LavaLakes, LavaSprings, OreNests, Mineshafts, Trees, SprinkleFoliage, Ice, Snow, Lilypads, BottomLava, DeadBushes, PreSimulator");
+ break;
+ }
+ case dimNether:
+ {
+ a_IniFile.GetValueSet("Generator", "BiomeGen", "Constant");
+ a_IniFile.GetValueSet("Generator", "ConstantBiome", "Nether");
+ a_IniFile.GetValueSet("Generator", "HeightGen", "Flat");
+ a_IniFile.GetValueSet("Generator", "FlatHeight", "128");
+ a_IniFile.GetValueSet("Generator", "CompositionGen", "Nether");
+ a_IniFile.GetValueSet("Generator", "Finishers", "WormNestCaves, BottomLava, LavaSprings, NetherClumpFoliage, NetherForts, PreSimulator");
+ a_IniFile.GetValueSet("Generator", "BottomLavaHeight", "30");
+ break;
+ }
+ }
+}
+
+
+
+
+
+void cWorld::InitialiseAndLoadMobSpawningValues(cIniFile & a_IniFile)
+{
+ AString DefaultMonsters;
+ switch (m_Dimension)
+ {
+ case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, enderman, horse, mooshroom, ocelot, pig, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break;
+ case dimNether: DefaultMonsters = "blaze, ghast, magmacube, skeleton, zombie, zombiepigman"; break;
+ case dimEnd: DefaultMonsters = "enderman"; break;
+ }
+
+ m_bAnimals = a_IniFile.GetValueSetB("Monsters", "AnimalsOn", true);
+ AString AllMonsters = a_IniFile.GetValueSet("Monsters", "Types", DefaultMonsters);
+
+ if (!m_bAnimals)
+ {
+ return;
+ }
+
+ AStringVector SplitList = StringSplitAndTrim(AllMonsters, ",");
+ for (AStringVector::const_iterator itr = SplitList.begin(), end = SplitList.end(); itr != end; ++itr)
+ {
+ cMonster::eType ToAdd = cMonster::StringToMobType(*itr);
+ if (ToAdd != cMonster::mtInvalidType)
+ {
+ m_AllowedMobs.insert(ToAdd);
+ LOGD("Allowed mob: %s", itr->c_str());
+ }
+ else
+ {
+ LOG("World \"%s\": Unknown mob type: %s", m_WorldName.c_str(), itr->c_str());
+ }
+ }
+}
+
+
+
+
+
void cWorld::Stop(void)
{
// Delete the clients that have been in this world:
@@ -703,6 +784,26 @@ void cWorld::Stop(void)
} // for itr - m_Clients[]
m_Clients.clear();
}
+
+ // Write settings to file; these are all plugin changeable values - keep updated!
+ cIniFile IniFile;
+ IniFile.ReadFile(m_IniFileName);
+ if (GetDimension() == dimOverworld)
+ {
+ IniFile.SetValue("LinkedWorlds", "NetherWorldName", m_NetherWorldName);
+ IniFile.SetValue("LinkedWorlds", "EndWorldName", m_EndWorldName);
+ }
+ else
+ {
+ IniFile.SetValue("LinkedWorlds", "OverworldName", m_OverworldName);
+ }
+ IniFile.SetValueI("Physics", "TNTShrapnelLevel", (int)m_TNTShrapnelLevel);
+ IniFile.SetValueB("Mechanics", "CommandBlocksEnabled", m_bCommandBlocksEnabled);
+ IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes);
+ IniFile.SetValueB("General", "IsDaylightCycleEnabled", m_IsDaylightCycleEnabled);
+ IniFile.SetValueI("General", "Weather", (int)m_Weather);
+ IniFile.SetValueI("General", "TimeInTicks", m_TimeOfDay);
+ IniFile.WriteFile(m_IniFileName);
m_TickThread.Stop();
m_Lighting.Stop();
@@ -720,27 +821,42 @@ void cWorld::Tick(float a_Dt, int a_LastTickDurationMSec)
// Call the plugins
cPluginManager::Get()->CallHookWorldTick(*this, a_Dt, a_LastTickDurationMSec);
- // We need sub-tick precision here, that's why we store the time in seconds and calculate ticks off of it
- m_WorldAgeSecs += (double)a_Dt / 1000.0;
- m_TimeOfDaySecs += (double)a_Dt / 1000.0;
-
- // Wrap time of day each 20 minutes (1200 seconds)
- if (m_TimeOfDaySecs > 1200.0)
+ // Set any chunk data that has been queued for setting:
+ cSetChunkDataPtrs SetChunkDataQueue;
{
- m_TimeOfDaySecs -= 1200.0;
+ cCSLock Lock(m_CSSetChunkDataQueue);
+ std::swap(SetChunkDataQueue, m_SetChunkDataQueue);
}
+ for (cSetChunkDataPtrs::iterator itr = SetChunkDataQueue.begin(), end = SetChunkDataQueue.end(); itr != end; ++itr)
+ {
+ SetChunkData(**itr);
+ } // for itr - SetChunkDataQueue[]
+ m_WorldAgeSecs += (double)a_Dt / 1000.0;
m_WorldAge = (Int64)(m_WorldAgeSecs * 20.0);
- m_TimeOfDay = (Int64)(m_TimeOfDaySecs * 20.0);
-
- // Updates the sky darkness based on current time of day
- UpdateSkyDarkness();
- // Broadcast time update every 40 ticks (2 seconds)
- if (m_LastTimeUpdate < m_WorldAge - 40)
+ if (m_IsDaylightCycleEnabled)
{
- BroadcastTimeUpdate();
- m_LastTimeUpdate = m_WorldAge;
+ // We need sub-tick precision here, that's why we store the time in seconds and calculate ticks off of it
+ m_TimeOfDaySecs += (double)a_Dt / 1000.0;
+
+ // Wrap time of day each 20 minutes (1200 seconds)
+ if (m_TimeOfDaySecs > 1200.0)
+ {
+ m_TimeOfDaySecs -= 1200.0;
+ }
+
+ m_TimeOfDay = (Int64)(m_TimeOfDaySecs * 20.0);
+
+ // Updates the sky darkness based on current time of day
+ UpdateSkyDarkness();
+
+ // Broadcast time update every 40 ticks (2 seconds)
+ if (m_LastTimeUpdate < m_WorldAge - 40)
+ {
+ BroadcastTimeUpdate();
+ m_LastTimeUpdate = m_WorldAge;
+ }
}
// Add entities waiting in the queue to be added:
@@ -770,12 +886,12 @@ void cWorld::Tick(float a_Dt, int a_LastTickDurationMSec)
m_ChunkMap->FastSetQueuedBlocks();
- if (m_WorldAge - m_LastSave > 60 * 5 * 20) // Save each 5 minutes
+ if (m_WorldAge - m_LastSave > 60 * 5 * 20) // Save each 5 minutes
{
SaveAllChunks();
}
- if (m_WorldAge - m_LastUnload > 10 * 20) // Unload every 10 seconds
+ if (m_WorldAge - m_LastUnload > 10 * 20) // Unload every 10 seconds
{
UnloadUnusedChunks();
}
@@ -861,19 +977,19 @@ void cWorld::TickMobs(float a_Dt)
SpawnMobFinalize(*itr2);
}
}
- } // for i - AllFamilies[]
- } // if (Spawning enabled)
+ } // for i - AllFamilies[]
+ } // if (Spawning enabled)
// move close mobs
cMobProximityCounter::sIterablePair allCloseEnoughToMoveMobs = MobCensus.GetProximityCounter().getMobWithinThosesDistances(-1, 64 * 16);// MG TODO : deal with this magic number (the 16 is the size of a block)
- for(cMobProximityCounter::tDistanceToMonster::const_iterator itr = allCloseEnoughToMoveMobs.m_Begin; itr != allCloseEnoughToMoveMobs.m_End; ++itr)
+ for (cMobProximityCounter::tDistanceToMonster::const_iterator itr = allCloseEnoughToMoveMobs.m_Begin; itr != allCloseEnoughToMoveMobs.m_End; ++itr)
{
itr->second.m_Monster.Tick(a_Dt, itr->second.m_Chunk);
}
// remove too far mobs
cMobProximityCounter::sIterablePair allTooFarMobs = MobCensus.GetProximityCounter().getMobWithinThosesDistances(128 * 16, -1);// MG TODO : deal with this magic number (the 16 is the size of a block)
- for(cMobProximityCounter::tDistanceToMonster::const_iterator itr = allTooFarMobs.m_Begin; itr != allTooFarMobs.m_End; ++itr)
+ for (cMobProximityCounter::tDistanceToMonster::const_iterator itr = allTooFarMobs.m_Begin; itr != allTooFarMobs.m_End; ++itr)
{
itr->second.m_Monster.Destroy(true);
}
@@ -944,11 +1060,7 @@ void cWorld::TickClients(float a_Dt)
// Add clients scheduled for adding:
for (cClientHandleList::iterator itr = m_ClientsToAdd.begin(), end = m_ClientsToAdd.end(); itr != end; ++itr)
{
- if (std::find(m_Clients.begin(), m_Clients.end(), *itr) != m_Clients.end())
- {
- ASSERT(!"Adding a client that is already in the clientlist");
- continue;
- }
+ ASSERT(std::find(m_Clients.begin(), m_Clients.end(), *itr) == m_Clients.end());
m_Clients.push_back(*itr);
} // for itr - m_ClientsToRemove[]
m_ClientsToAdd.clear();
@@ -972,7 +1084,7 @@ void cWorld::TickClients(float a_Dt)
for (cClientHandleList::iterator itr = RemoveClients.begin(); itr != RemoveClients.end(); ++itr)
{
delete *itr;
- } // for itr - RemoveClients[]
+ } // for itr - RemoveClients[]
}
@@ -1088,7 +1200,7 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo
Vector3d explosion_pos = Vector3d(a_BlockX, a_BlockY, a_BlockZ);
cVector3iArray BlocksAffected;
m_ChunkMap->DoExplosionAt(a_ExplosionSize, a_BlockX, a_BlockY, a_BlockZ, BlocksAffected);
- BroadcastSoundEffect("random.explode", (int)floor(a_BlockX * 8), (int)floor(a_BlockY * 8), (int)floor(a_BlockZ * 8), 1.0f, 0.6f);
+ BroadcastSoundEffect("random.explode", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0f, 0.6f);
{
cCSLock Lock(m_CSPlayers);
for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
@@ -1129,6 +1241,15 @@ bool cWorld::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBloc
+bool cWorld::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback& a_Callback)
+{
+ return m_ChunkMap->DoWithBeaconAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
+}
+
+
+
+
+
bool cWorld::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback)
{
return m_ChunkMap->DoWithChestAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback);
@@ -2074,9 +2195,9 @@ void cWorld::BroadcastDisplayObjective(const AString & a_Objective, cScoreboard:
-void cWorld::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
+void cWorld::BroadcastSoundEffect(const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
{
- m_ChunkMap->BroadcastSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch, a_Exclude);
+ m_ChunkMap->BroadcastSoundEffect(a_SoundName, a_X, a_Y, a_Z, a_Volume, a_Pitch, a_Exclude);
}
@@ -2138,7 +2259,7 @@ void cWorld::BroadcastTimeUpdate(const cClientHandle * a_Exclude)
{
continue;
}
- ch->SendTimeUpdate(m_WorldAge, m_TimeOfDay);
+ ch->SendTimeUpdate(m_WorldAge, m_TimeOfDay, m_IsDaylightCycleEnabled);
}
}
@@ -2182,9 +2303,18 @@ void cWorld::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHa
-void cWorld::MarkChunkDirty (int a_ChunkX, int a_ChunkZ)
+void cWorld::MarkRedstoneDirty(int a_ChunkX, int a_ChunkZ)
+{
+ m_ChunkMap->MarkRedstoneDirty(a_ChunkX, a_ChunkZ);
+}
+
+
+
+
+
+void cWorld::MarkChunkDirty(int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty)
{
- m_ChunkMap->MarkChunkDirty (a_ChunkX, a_ChunkZ);
+ m_ChunkMap->MarkChunkDirty(a_ChunkX, a_ChunkZ, a_MarkRedstoneDirty);
}
@@ -2209,47 +2339,59 @@ void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
-void cWorld::SetChunkData(
- int a_ChunkX, int a_ChunkZ,
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- const cChunkDef::BiomeMap * a_BiomeMap,
- cEntityList & a_Entities,
- cBlockEntityList & a_BlockEntities,
- bool a_MarkDirty
-)
+void cWorld::QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData)
{
// Validate biomes, if needed:
- cChunkDef::BiomeMap BiomeMap;
- const cChunkDef::BiomeMap * Biomes = a_BiomeMap;
- if (a_BiomeMap == NULL)
+ if (!a_SetChunkData->AreBiomesValid())
{
// The biomes are not assigned, get them from the generator:
- Biomes = &BiomeMap;
- m_Generator.GenerateBiomes(a_ChunkX, a_ChunkZ, BiomeMap);
+ m_Generator.GenerateBiomes(a_SetChunkData->GetChunkX(), a_SetChunkData->GetChunkZ(), a_SetChunkData->GetBiomes());
+ a_SetChunkData->MarkBiomesValid();
}
- m_ChunkMap->SetChunkData(
- a_ChunkX, a_ChunkZ,
- a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight,
- a_HeightMap, *Biomes,
- a_BlockEntities,
- a_MarkDirty
- );
+ // Validate heightmap, if needed:
+ if (!a_SetChunkData->IsHeightMapValid())
+ {
+ a_SetChunkData->CalculateHeightMap();
+ }
+
+ // Store a copy of the data in the queue:
+ // TODO: If the queue is too large, wait for it to get processed. Not likely, though.
+ cCSLock Lock(m_CSSetChunkDataQueue);
+ m_SetChunkDataQueue.push_back(a_SetChunkData);
+}
+
+
+
+
+
+void cWorld::SetChunkData(cSetChunkData & a_SetChunkData)
+{
+ ASSERT(a_SetChunkData.AreBiomesValid());
+ ASSERT(a_SetChunkData.IsHeightMapValid());
+
+ m_ChunkMap->SetChunkData(a_SetChunkData);
// Initialize the entities (outside the m_ChunkMap's CS, to fix FS #347):
- for (cEntityList::iterator itr = a_Entities.begin(), end = a_Entities.end(); itr != end; ++itr)
+ cEntityList Entities;
+ std::swap(a_SetChunkData.GetEntities(), Entities);
+ for (cEntityList::iterator itr = Entities.begin(), end = Entities.end(); itr != end; ++itr)
{
(*itr)->Initialize(*this);
}
// If a client is requesting this chunk, send it to them:
- if (m_ChunkMap->HasChunkAnyClients(a_ChunkX, a_ChunkZ))
+ int ChunkX = a_SetChunkData.GetChunkX();
+ int ChunkZ = a_SetChunkData.GetChunkZ();
+ if (m_ChunkMap->HasChunkAnyClients(ChunkX, ChunkZ))
{
- m_ChunkSender.ChunkReady(a_ChunkX, a_ChunkZ);
+ m_ChunkSender.ChunkReady(ChunkX, ChunkZ);
+ }
+
+ // Save the chunk right after generating, so that we don't have to generate it again on next run
+ if (a_SetChunkData.ShouldMarkDirty())
+ {
+ m_Storage.QueueSaveChunk(ChunkX, 0, ChunkZ);
}
}
@@ -2344,17 +2486,21 @@ void cWorld::AddPlayer(cPlayer * a_Player)
-void cWorld::RemovePlayer(cPlayer * a_Player)
+void cWorld::RemovePlayer(cPlayer * a_Player, bool a_RemoveFromChunk)
{
-
- m_ChunkMap->RemoveEntity(a_Player);
+ if (a_RemoveFromChunk)
+ {
+ // To prevent iterator invalidations when an entity goes through a portal and calls this function whilst being ticked by cChunk
+ // we should not change cChunk's entity list if asked not to
+ m_ChunkMap->RemoveEntity(a_Player);
+ }
{
cCSLock Lock(m_CSPlayersToAdd);
m_PlayersToAdd.remove(a_Player);
}
{
cCSLock Lock(m_CSPlayers);
- LOGD("Removing player \"%s\" from world \"%s\".", a_Player->GetName().c_str(), m_WorldName.c_str());
+ LOGD("Removing player %s from world \"%s\"", a_Player->GetName().c_str(), m_WorldName.c_str());
m_Players.remove(a_Player);
}
@@ -2459,10 +2605,13 @@ cPlayer * cWorld::FindClosestPlayer(const Vector3d & a_Pos, float a_SightLimit,
if (Distance < ClosestDistance)
{
- if (a_CheckLineOfSight && !LineOfSight.Trace(a_Pos,(Pos - a_Pos),(int)(Pos - a_Pos).Length()))
+ if (a_CheckLineOfSight)
{
- ClosestDistance = Distance;
- ClosestPlayer = *itr;
+ if (!LineOfSight.Trace(a_Pos, (Pos - a_Pos), (int)(Pos - a_Pos).Length()))
+ {
+ ClosestDistance = Distance;
+ ClosestPlayer = *itr;
+ }
}
else
{
@@ -2847,20 +2996,11 @@ bool cWorld::HasEntity(int a_UniqueID)
-void cWorld::RemoveEntity(cEntity * a_Entity)
-{
- m_ChunkMap->RemoveEntity(a_Entity);
-}
-
-
-
-
-
/*
unsigned int cWorld::GetNumPlayers(void)
{
cCSLock Lock(m_CSPlayers);
- return m_Players.size();
+ return m_Players.size();
}
*/
@@ -2904,11 +3044,11 @@ void cWorld::TickQueuedBlocks(void)
{
// TODO: Handle the case when the chunk is already unloaded
m_ChunkMap->TickBlock(Block->X, Block->Y, Block->Z);
- delete Block; // We don't have to remove it from the vector, this will happen automatically on the next tick
+ delete Block; // We don't have to remove it from the vector, this will happen automatically on the next tick
}
else
{
- m_BlockTickQueue.push_back(Block); // Keep the block in the queue
+ m_BlockTickQueue.push_back(Block); // Keep the block in the queue
}
} // for itr - m_BlockTickQueueCopy[]
}
@@ -2964,21 +3104,31 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp
int cWorld::SpawnMobFinalize(cMonster * a_Monster)
{
+ // Invalid cMonster object. Bail out.
if (!a_Monster)
+ {
return -1;
+ }
+
+ // Give the mob full health.
a_Monster->SetHealth(a_Monster->GetMaxHealth());
+
+ // A plugin doesn't agree with the spawn. bail out.
if (cPluginManager::Get()->CallHookSpawningMonster(*this, *a_Monster))
{
delete a_Monster;
a_Monster = NULL;
return -1;
}
+
+ // Initialize the monster into the current world.
if (!a_Monster->Initialize(*this))
{
delete a_Monster;
a_Monster = NULL;
return -1;
}
+
BroadcastSpawnEntity(*a_Monster);
cPluginManager::Get()->CallHookSpawnedMonster(*this, *a_Monster);
@@ -2989,7 +3139,7 @@ int cWorld::SpawnMobFinalize(cMonster * a_Monster)
-int cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem & a_Item, const Vector3d * a_Speed)
+int cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed)
{
cProjectileEntity * Projectile = cProjectileEntity::Create(a_Kind, a_Creator, a_PosX, a_PosY, a_PosZ, a_Item, a_Speed);
if (Projectile == NULL)
@@ -3011,21 +3161,47 @@ int cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProje
void cWorld::TabCompleteUserName(const AString & a_Text, AStringVector & a_Results)
{
+ typedef std::pair<AString::size_type, AString> pair_t;
+ size_t LastSpace = a_Text.find_last_of(" "); // Find the position of the last space
+ AString LastWord = a_Text.substr(LastSpace + 1, a_Text.length()); // Find the last word
+
+ if (LastWord.empty())
+ {
+ return;
+ }
+
+ std::vector<pair_t> UsernamesByWeight;
+
cCSLock Lock(m_CSPlayers);
for (cPlayerList::iterator itr = m_Players.begin(), end = m_Players.end(); itr != end; ++itr)
{
- size_t LastSpace = a_Text.find_last_of(" "); // Find the position of the last space
-
- AString LastWord = a_Text.substr(LastSpace + 1, a_Text.length()); // Find the last word
AString PlayerName ((*itr)->GetName());
- size_t Found = PlayerName.find(LastWord); // Try to find last word in playername
+ AString::size_type Found = PlayerName.find(LastWord); // Try to find last word in playername
if (Found == AString::npos)
{
- continue; // No match
+ continue; // No match
}
- a_Results.push_back(PlayerName); // Match!
+ UsernamesByWeight.push_back(std::make_pair(Found, PlayerName)); // Match! Store it with the position of the match as a weight
+ }
+ Lock.Unlock();
+
+ std::sort(UsernamesByWeight.begin(), UsernamesByWeight.end()); // Sort lexicographically (by the first value, then second), so higher weights (usernames with match closer to start) come first (#1274)
+
+ /* TODO: Uncomment once migrated to C++11
+ std::transform(
+ UsernamesByWeight.begin(),
+ UsernamesByWeight.end(),
+ std::back_inserter(a_Results),
+ [](const pair_t & p) { return p.first; }
+ );
+ */
+
+ a_Results.reserve(UsernamesByWeight.size());
+ for (std::vector<pair_t>::const_iterator itr = UsernamesByWeight.begin(); itr != UsernamesByWeight.end(); ++itr)
+ {
+ a_Results.push_back(itr->second);
}
}
@@ -3044,17 +3220,17 @@ void cWorld::SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicke
cRedstoneSimulator * cWorld::InitializeRedstoneSimulator(cIniFile & a_IniFile)
{
- AString SimulatorName = a_IniFile.GetValueSet("Physics", "RedstoneSimulator", "");
+ AString SimulatorName = a_IniFile.GetValueSet("Physics", "RedstoneSimulator", "Incremental");
if (SimulatorName.empty())
{
- LOGWARNING("[Physics] RedstoneSimulator not present or empty in %s, using the default of \"incremental\".", GetIniFileName().c_str());
- SimulatorName = "incremental";
+ LOGWARNING("[Physics] RedstoneSimulator not present or empty in %s, using the default of \"Incremental\".", GetIniFileName().c_str());
+ SimulatorName = "Incremental";
}
cRedstoneSimulator * res = NULL;
- if (NoCaseCompare(SimulatorName, "incremental") == 0)
+ if (NoCaseCompare(SimulatorName, "Incremental") == 0)
{
res = new cIncrementalRedstoneSimulator(*this);
}
@@ -3078,7 +3254,7 @@ cFluidSimulator * cWorld::InitializeFluidSimulator(cIniFile & a_IniFile, const c
Printf(SimulatorNameKey, "%sSimulator", a_FluidName);
AString SimulatorSectionName;
Printf(SimulatorSectionName, "%sSimulator", a_FluidName);
- AString SimulatorName = a_IniFile.GetValueSet("Physics", SimulatorNameKey, "");
+ AString SimulatorName = a_IniFile.GetValueSet("Physics", SimulatorNameKey, "Vanilla");
if (SimulatorName.empty())
{
LOGWARNING("[Physics] %s not present or empty in %s, using the default of \"Vanilla\".", SimulatorNameKey.c_str(), GetIniFileName().c_str());
@@ -3153,6 +3329,7 @@ void cWorld::AddQueuedPlayers(void)
for (cPlayerList::iterator itr = PlayersToAdd.begin(), end = PlayersToAdd.end(); itr != end; ++itr)
{
ASSERT(std::find(m_Players.begin(), m_Players.end(), *itr) == m_Players.end()); // Is it already in the list? HOW?
+ LOGD("Adding player %s to world \"%s\".", (*itr)->GetName().c_str(), m_WorldName.c_str());
m_Players.push_back(*itr);
(*itr)->SetWorld(this);
@@ -3182,6 +3359,9 @@ void cWorld::AddQueuedPlayers(void)
if (Client != NULL)
{
Client->StreamChunks();
+ Client->SendPlayerMoveLook();
+ Client->SendHealth();
+ Client->SendWholeInventory(*(*itr)->GetWindow());
}
} // for itr - PlayersToAdd[]
}
@@ -3190,7 +3370,7 @@ void cWorld::AddQueuedPlayers(void)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWorld::cTaskSaveAllChunks:
void cWorld::cTaskSaveAllChunks::Run(cWorld & a_World)
@@ -3202,7 +3382,7 @@ void cWorld::cTaskSaveAllChunks::Run(cWorld & a_World)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWorld::cTaskUnloadUnusedChunks
void cWorld::cTaskUnloadUnusedChunks::Run(cWorld & a_World)
@@ -3214,7 +3394,7 @@ void cWorld::cTaskUnloadUnusedChunks::Run(cWorld & a_World)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWorld::cTaskSendBlockTo
cWorld::cTaskSendBlockToAllPlayers::cTaskSendBlockToAllPlayers(std::vector<Vector3i> & a_SendQueue) :
@@ -3257,7 +3437,7 @@ void cWorld::cTaskSendBlockToAllPlayers::Run(cWorld & a_World)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWorld::cChunkGeneratorCallbacks:
cWorld::cChunkGeneratorCallbacks::cChunkGeneratorCallbacks(cWorld & a_World) :
@@ -3274,17 +3454,14 @@ void cWorld::cChunkGeneratorCallbacks::OnChunkGenerated(cChunkDesc & a_ChunkDesc
cChunkDef::BlockNibbles BlockMetas;
a_ChunkDesc.CompressBlockMetas(BlockMetas);
- m_World->SetChunkData(
+ m_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(),
a_ChunkDesc.GetBlockTypes(), BlockMetas,
NULL, NULL, // We don't have lighting, chunk will be lighted when needed
&a_ChunkDesc.GetHeightMap(), &a_ChunkDesc.GetBiomeMap(),
a_ChunkDesc.GetEntities(), a_ChunkDesc.GetBlockEntities(),
true
- );
-
- // Save the chunk right after generating, so that we don't have to generate it again on next run
- m_World->GetStorage().QueueSaveChunk(a_ChunkDesc.GetChunkX(), 0, a_ChunkDesc.GetChunkZ());
+ )));
}
diff --git a/src/World.h b/src/World.h
index f903ff5be..578c9682b 100644
--- a/src/World.h
+++ b/src/World.h
@@ -41,6 +41,7 @@ class cEntity;
class cBlockEntity;
class cWorldGenerator; // The generator that actually generates the chunks for a single world
class cChunkGenerator; // The thread responsible for generating chunks
+class cBeaconEntity;
class cChestEntity;
class cDispenserEntity;
class cFlowerPotEntity;
@@ -49,11 +50,17 @@ class cNoteEntity;
class cMobHeadEntity;
class cCompositeChat;
class cCuboid;
+class cSetChunkData;
+
typedef std::list< cPlayer * > cPlayerList;
+typedef SharedPtr<cSetChunkData> cSetChunkDataPtr; // TODO: Change to unique_ptr once we go C++11
+typedef std::vector<cSetChunkDataPtr> cSetChunkDataPtrs;
+
typedef cItemCallback<cPlayer> cPlayerListCallback;
typedef cItemCallback<cEntity> cEntityCallback;
+typedef cItemCallback<cBeaconEntity> cBeaconCallback;
typedef cItemCallback<cChestEntity> cChestCallback;
typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
@@ -91,7 +98,7 @@ public:
class cTask
{
public:
- virtual ~cTask(){};
+ virtual ~cTask() {}
virtual void Run(cWorld & a_World) = 0;
} ;
@@ -138,9 +145,19 @@ public:
// tolua_begin
int GetTicksUntilWeatherChange(void) const { return m_WeatherInterval; }
-
+
+ /** Is the daylight cyclus enabled? */
+ virtual bool IsDaylightCycleEnabled(void) const { return m_IsDaylightCycleEnabled; }
+
+ /** Sets the daylight cyclus to true/false. */
+ virtual void SetDaylightCycleEnabled(bool a_IsDaylightCycleEnabled)
+ {
+ m_IsDaylightCycleEnabled = a_IsDaylightCycleEnabled;
+ BroadcastTimeUpdate();
+ }
+
virtual Int64 GetWorldAge (void) const override { return m_WorldAge; }
- virtual Int64 GetTimeOfDay(void) const override { return m_TimeOfDay; }
+ virtual Int64 GetTimeOfDay(void) const override { return m_TimeOfDay; }
void SetTicksUntilWeatherChange(int a_WeatherInterval)
{
@@ -151,6 +168,7 @@ public:
{
m_TimeOfDay = a_TimeOfDay;
m_TimeOfDaySecs = (double)a_TimeOfDay / 20.0;
+ UpdateSkyDarkness();
BroadcastTimeUpdate();
}
@@ -180,7 +198,7 @@ public:
virtual eDimension GetDimension(void) const { return m_Dimension; }
/** Returns the world height at the specified coords; waits for the chunk to get loaded / generated */
- int GetHeight(int a_BlockX, int a_BlockZ);
+ virtual int GetHeight(int a_BlockX, int a_BlockZ);
// tolua_end
@@ -217,15 +235,15 @@ public:
void BroadcastEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
- virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) override;
- void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); // tolua_export
+ virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) override; // tolua_export
+ void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); // tolua_export
void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL);
void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL);
void BroadcastScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
void BroadcastScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode);
void BroadcastDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display);
- void BroadcastSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // tolua_export a_Src coords are Block * 8
- void BroadcastSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL); // tolua_export
+ void BroadcastSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // tolua_export
+ void BroadcastSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data, const cClientHandle * a_Exclude = NULL); // tolua_export
void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastTeleportEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL);
@@ -241,28 +259,14 @@ public:
/** If there is a block entity at the specified coords, sends it to the client specified */
void SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client);
- void MarkChunkDirty (int a_ChunkX, int a_ChunkZ);
+ void MarkRedstoneDirty(int a_ChunkX, int a_ChunkZ);
+ void MarkChunkDirty (int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty = false);
void MarkChunkSaving(int a_ChunkX, int a_ChunkZ);
void MarkChunkSaved (int a_ChunkX, int a_ChunkZ);
- /** Sets the chunk data as either loaded from the storage or generated.
- a_BlockLight and a_BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
- a_BiomeMap is optional, if not present, biomes will be calculated by the generator
- a_HeightMap is optional, if not present, will be calculated.
- If a_MarkDirty is set, the chunk is set as dirty (used after generating)
- */
- void SetChunkData(
- int a_ChunkX, int a_ChunkZ,
- const BLOCKTYPE * a_BlockTypes,
- const NIBBLETYPE * a_BlockMeta,
- const NIBBLETYPE * a_BlockLight,
- const NIBBLETYPE * a_BlockSkyLight,
- const cChunkDef::HeightMap * a_HeightMap,
- const cChunkDef::BiomeMap * a_BiomeMap,
- cEntityList & a_Entities,
- cBlockEntityList & a_BlockEntities,
- bool a_MarkDirty
- );
+ /** Puts the chunk data into a queue to be set into the chunkmap in the tick thread.
+ If the chunk data doesn't contain valid biomes, the biomes are calculated before adding the data into the queue. */
+ void QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData);
void ChunkLighted(
int a_ChunkX, int a_ChunkZ,
@@ -290,8 +294,9 @@ public:
/** Removes the player from the world.
Removes the player from the addition queue, too, if appropriate.
- If the player has a ClientHandle, the ClientHandle is removed from all chunks in the world and will not be ticked by this world anymore. */
- void RemovePlayer(cPlayer * a_Player);
+ If the player has a ClientHandle, the ClientHandle is removed from all chunks in the world and will not be ticked by this world anymore.
+ @param a_RemoveFromChunk determines if the entity should be removed from its chunk as well. Should be false when ticking from cChunk. */
+ void RemovePlayer(cPlayer * a_Player, bool a_RemoveFromChunk);
/** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */
virtual bool ForEachPlayer(cPlayerListCallback & a_Callback) override; // >> EXPORTED IN MANUALBINDINGS <<
@@ -300,10 +305,10 @@ public:
bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
/** Finds a player from a partial or complete player name and calls the callback - case-insensitive */
- bool FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
+ bool FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
// TODO: This interface is dangerous - rewrite to DoWithClosestPlayer(pos, sight, action)
- cPlayer * FindClosestPlayer(const Vector3d & a_Pos, float a_SightLimit, bool a_CheckLineOfSight = true);
+ cPlayer * FindClosestPlayer(const Vector3d & a_Pos, float a_SightLimit, bool a_CheckLineOfSight = true);
void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player
@@ -313,9 +318,6 @@ public:
bool HasEntity(int a_UniqueID);
- /** Removes the entity, the entity ptr ownership is assumed taken by the caller */
- void RemoveEntity(cEntity * a_Entity);
-
/** Calls the callback for each entity in the entire world; returns true if all entities processed, false if the callback aborted by returning true */
bool ForEachEntity(cEntityCallback & a_Callback); // Exported in ManualBindings.cpp
@@ -364,10 +366,10 @@ public:
bool SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player = NULL); // Exported in ManualBindings.cpp
/** Sets the sign text, asking plugins for permission first. a_Player is the player who this change belongs to, may be NULL. Returns true if sign text changed. Same as SetSignLines() */
- bool UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player = NULL); // Exported in ManualBindings.cpp
+ bool UpdateSign(int a_X, int a_Y, int a_Z, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player = NULL); // Exported in ManualBindings.cpp
/** Sets the command block command. Returns true if command changed. */
- bool SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command); // tolua_export
+ bool SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command); // tolua_export
/** Is the trapdoor open? Returns false if there is no trapdoor at the specified coords. */
bool IsTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export
@@ -376,10 +378,10 @@ public:
bool SetTrapdoorOpen(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open); // tolua_export
/** Regenerate the given chunk: */
- void RegenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export
+ void RegenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export
/** Generates the given chunk, if not already generated */
- void GenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export
+ void GenerateChunk(int a_ChunkX, int a_ChunkZ); // tolua_export
/** Queues a chunk for lighting; a_Callback is called after the chunk is lighted */
void QueueLightChunk(int a_ChunkX, int a_ChunkZ, cChunkCoordCallback * a_Callback = NULL);
@@ -435,10 +437,10 @@ public:
// tolua_begin
// Vector3i variants:
- void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta ); }
- BLOCKTYPE GetBlock (const Vector3i & a_Pos ) { return GetBlock( a_Pos.x, a_Pos.y, a_Pos.z ); }
- NIBBLETYPE GetBlockMeta(const Vector3i & a_Pos ) { return GetBlockMeta( a_Pos.x, a_Pos.y, a_Pos.z ); }
- void SetBlockMeta(const Vector3i & a_Pos, NIBBLETYPE a_MetaData ) { SetBlockMeta( a_Pos.x, a_Pos.y, a_Pos.z, a_MetaData ); }
+ void FastSetBlock(const Vector3i & a_Pos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { FastSetBlock( a_Pos.x, a_Pos.y, a_Pos.z, a_BlockType, a_BlockMeta); }
+ BLOCKTYPE GetBlock (const Vector3i & a_Pos) { return GetBlock( a_Pos.x, a_Pos.y, a_Pos.z); }
+ NIBBLETYPE GetBlockMeta(const Vector3i & a_Pos) { return GetBlockMeta( a_Pos.x, a_Pos.y, a_Pos.z); }
+ void SetBlockMeta(const Vector3i & a_Pos, NIBBLETYPE a_MetaData) { SetBlockMeta( a_Pos.x, a_Pos.y, a_Pos.z, a_MetaData); }
// tolua_end
/** Writes the block area into the specified coords.
@@ -534,6 +536,9 @@ public:
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
virtual bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback) override; // Exported in ManualBindings.cpp
+ /** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
+ bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Exported in ManualBindings.cpp
+
/** Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found */
bool DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp
@@ -631,21 +636,22 @@ public:
bool ShouldUseChatPrefixes(void) const { return m_bUseChatPrefixes; }
void SetShouldUseChatPrefixes(bool a_Flag) { m_bUseChatPrefixes = a_Flag; }
+
+ bool ShouldBroadcastDeathMessages(void) const { return m_BroadcastDeathMessages; }
+ bool ShouldBroadcastAchievementMessages(void) const { return m_BroadcastAchievementMessages; }
+
+
+ AString GetNetherWorldName(void) const { return m_NetherWorldName; }
+ void SetNetherWorldName(const AString & a_Name) { m_NetherWorldName = a_Name; }
+
+ AString GetEndWorldName(void) const { return m_EndWorldName; }
+ void SetEndWorldName(const AString & a_Name) { m_EndWorldName = a_Name; }
+
+ AString GetLinkedOverworldName(void) const { return m_OverworldName; }
+ void SetLinkedOverworldName(const AString & a_Name) { m_OverworldName = a_Name; }
// tolua_end
- inline static void BlockToChunk( int a_X, int a_Y, int a_Z, int & a_ChunkX, int & a_ChunkY, int & a_ChunkZ )
- {
- // TODO: Use floor() instead of weird if statements
- // Also fix Y
- (void)a_Y; // not unused anymore
- a_ChunkX = a_X/cChunkDef::Width;
- if(a_X < 0 && a_X % cChunkDef::Width != 0) a_ChunkX--;
- a_ChunkY = 0;
- a_ChunkZ = a_Z/cChunkDef::Width;
- if(a_Z < 0 && a_Z % cChunkDef::Width != 0) a_ChunkZ--;
- }
-
/** Saves all chunks immediately. Dangerous interface, may deadlock, use QueueSaveAllChunks() instead */
void SaveAllChunks(void);
@@ -666,7 +672,7 @@ public:
void GetChunkStats(int & a_NumValid, int & a_NumDirty, int & a_NumInLightingQueue);
// Various queues length queries (cannot be const, they lock their CS):
- inline int GetGeneratorQueueLength (void) { return m_Generator.GetQueueLength(); } // tolua_export
+ inline int GetGeneratorQueueLength (void) { return m_Generator.GetQueueLength(); } // tolua_export
inline size_t GetLightingQueueLength (void) { return m_Lighting.GetQueueLength(); } // tolua_export
inline size_t GetStorageLoadQueueLength(void) { return m_Storage.GetLoadQueueLength(); } // tolua_export
inline size_t GetStorageSaveQueueLength(void) { return m_Storage.GetSaveQueueLength(); } // tolua_export
@@ -698,13 +704,13 @@ public:
void CastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ);
/** Sets the specified weather; resets weather interval; asks and notifies plugins of the change */
- void SetWeather (eWeather a_NewWeather);
+ void SetWeather(eWeather a_NewWeather);
/** Forces a weather change in the next game tick */
- void ChangeWeather (void);
+ void ChangeWeather(void);
/** Returns the current weather. Instead of comparing values directly to the weather constants, use IsWeatherXXX() functions, if possible */
- eWeather GetWeather (void) const { return m_Weather; };
+ eWeather GetWeather(void) const { return m_Weather; }
/** Returns true if the current weather is sun */
bool IsWeatherSunny(void) const { return (m_Weather == wSunny); }
@@ -719,14 +725,14 @@ public:
bool IsWeatherRain(void) const { return (m_Weather == wRain); }
/** Returns true if it is raining at the specified location. This takes into account biomes. */
- bool IsWeatherRainAt (int a_BlockX, int a_BlockZ)
+ bool IsWeatherRainAt(int a_BlockX, int a_BlockZ)
{
return (IsWeatherRain() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ)));
}
/** Returns true if the current weather is stormy */
bool IsWeatherStorm(void) const { return (m_Weather == wStorm); }
-
+
/** Returns true if the weather is stormy at the specified location. This takes into account biomes. */
bool IsWeatherStormAt(int a_BlockX, int a_BlockZ)
{
@@ -737,10 +743,11 @@ public:
bool IsWeatherWet(void) const { return !IsWeatherSunny(); }
/** Returns true if it is raining, stormy or snowing at the specified location. This takes into account biomes. */
- bool IsWeatherWetAt(int a_BlockX, int a_BlockZ)
+ virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ)
{
return (IsWeatherWet() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ)));
}
+
// tolua_end
cChunkGenerator & GetGenerator(void) { return m_Generator; }
@@ -762,7 +769,7 @@ public:
/** Creates a projectile of the specified type. Returns the projectile's EntityID if successful, <0 otherwise
Item parameter used currently for Fireworks to correctly set entity metadata based on item metadata
*/
- int CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem & a_Item, const Vector3d * a_Speed = NULL); // tolua_export
+ int CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem * a_Item, const Vector3d * a_Speed = NULL); // tolua_export
/** Returns a random number from the m_TickRand in range [0 .. a_Range]. To be used only in the tick thread! */
int GetTickRandomNumber(unsigned a_Range) { return (int)(m_TickRand.randInt(a_Range)); }
@@ -845,6 +852,12 @@ private:
AString m_WorldName;
+
+ /** The name of the world that a portal in this world should link to
+ Only has effect if this world is a nether or end world, as it is used by entities to see which world to teleport to when in a portal
+ */
+ AString m_OverworldName;
+
AString m_IniFileName;
/** Name of the storage schema used to load and save chunks */
@@ -863,6 +876,10 @@ private:
double m_SpawnY;
double m_SpawnZ;
+ bool m_BroadcastDeathMessages;
+ bool m_BroadcastAchievementMessages;
+
+ bool m_IsDaylightCycleEnabled;
double m_WorldAgeSecs; // World age, in seconds. Is only incremented, cannot be set by plugins.
double m_TimeOfDaySecs; // Time of day in seconds. Can be adjusted. Is wrapped to zero each day.
Int64 m_WorldAge; // World age in ticks, calculated off of m_WorldAgeSecs
@@ -870,7 +887,7 @@ private:
Int64 m_LastTimeUpdate; // The tick in which the last time update has been sent.
Int64 m_LastUnload; // The last WorldAge (in ticks) in which unloading was triggerred
Int64 m_LastSave; // The last WorldAge (in ticks) in which save-all was triggerred
- std::map<cMonster::eFamily,Int64> m_LastSpawnMonster; // The last WorldAge (in ticks) in which a monster was spawned (for each megatype of monster) // MG TODO : find a way to optimize without creating unmaintenability (if mob IDs are becoming unrowed)
+ std::map<cMonster::eFamily, Int64> m_LastSpawnMonster; // The last WorldAge (in ticks) in which a monster was spawned (for each megatype of monster) // MG TODO : find a way to optimize without creating unmaintenability (if mob IDs are becoming unrowed)
NIBBLETYPE m_SkyDarkness;
@@ -881,7 +898,7 @@ private:
bool m_VillagersShouldHarvestCrops;
std::vector<BlockTickQueueItem *> m_BlockTickQueue;
- std::vector<BlockTickQueueItem *> m_BlockTickQueueCopy; // Second is for safely removing the objects from the queue
+ std::vector<BlockTickQueueItem *> m_BlockTickQueueCopy; // Second is for safely removing the objects from the queue
cSimulatorManager * m_SimulatorManager;
cSandSimulator * m_SandSimulator;
@@ -929,6 +946,12 @@ private:
See the eShrapnelLevel enumeration for details
*/
eShrapnelLevel m_TNTShrapnelLevel;
+
+ /** Name of the nether world */
+ AString m_NetherWorldName;
+
+ /** Name of the end world */
+ AString m_EndWorldName;
cChunkGenerator m_Generator;
@@ -980,9 +1003,15 @@ private:
/** List of players that are scheduled for adding, waiting for the Tick thread to add them. */
cPlayerList m_PlayersToAdd;
+
+ /** CS protecting m_SetChunkDataQueue. */
+ cCriticalSection m_CSSetChunkDataQueue;
+
+ /** Queue for the chunk data to be set into m_ChunkMap by the tick thread. Protected by m_CSSetChunkDataQueue */
+ cSetChunkDataPtrs m_SetChunkDataQueue;
- cWorld(const AString & a_WorldName);
+ cWorld(const AString & a_WorldName, eDimension a_Dimension = dimOverworld, const AString & a_OverworldName = "");
virtual ~cWorld();
void Tick(float a_Dt, int a_LastTickDurationMSec);
@@ -1022,7 +1051,18 @@ private:
/** Adds the players queued in the m_PlayersToAdd queue into the m_Players list.
Assumes it is called from the Tick thread. */
void AddQueuedPlayers(void);
-}; // tolua_export
+
+ /** Sets generator values to dimension specific defaults, if those values do not exist */
+ void InitialiseGeneratorDefaults(cIniFile & a_IniFile);
+
+ /** Sets mob spawning values if nonexistant to their dimension specific defaults */
+ void InitialiseAndLoadMobSpawningValues(cIniFile & a_IniFile);
+
+ /** Sets the specified chunk data into the chunkmap. Called in the tick thread.
+ Modifies the a_SetChunkData - moves the entities contained in it into the chunk. */
+ void SetChunkData(cSetChunkData & a_SetChunkData);
+
+}; // tolua_export
diff --git a/src/WorldStorage/CMakeLists.txt b/src/WorldStorage/CMakeLists.txt
index 2844f7fe5..a00ff3b2f 100644
--- a/src/WorldStorage/CMakeLists.txt
+++ b/src/WorldStorage/CMakeLists.txt
@@ -4,11 +4,34 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ EnchantmentSerializer.cpp
+ FastNBT.cpp
+ FireworksSerializer.cpp
+ MapSerializer.cpp
+ NBTChunkSerializer.cpp
+ SchematicFileSerializer.cpp
+ ScoreboardSerializer.cpp
+ StatSerializer.cpp
+ WSSAnvil.cpp
+ WSSCompact.cpp
+ WorldStorage.cpp)
-add_library(WorldStorage ${SOURCE})
+SET (HDRS
+ EnchantmentSerializer.h
+ FastNBT.h
+ FireworksSerializer.h
+ MapSerializer.h
+ NBTChunkSerializer.h
+ SchematicFileSerializer.h
+ ScoreboardSerializer.h
+ StatSerializer.h
+ WSSAnvil.h
+ WSSCompact.h
+ WorldStorage.h)
-target_link_libraries(WorldStorage OSSupport)
+if(NOT MSVC)
+ add_library(WorldStorage ${SRCS} ${HDRS})
+
+ target_link_libraries(WorldStorage OSSupport)
+endif()
diff --git a/src/WorldStorage/FastNBT.cpp b/src/WorldStorage/FastNBT.cpp
index a047d67c7..c6294b99c 100644
--- a/src/WorldStorage/FastNBT.cpp
+++ b/src/WorldStorage/FastNBT.cpp
@@ -10,7 +10,7 @@
-// The number of NBT tags that are reserved when an NBT parsing is started.
+// The number of NBT tags that are reserved when an NBT parsing is started.
// You can override this by using a cmdline define
#ifndef NBT_RESERVE_SIZE
#define NBT_RESERVE_SIZE 200
@@ -25,7 +25,7 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cParsedNBT:
#define NEEDBYTES(N) \
@@ -69,7 +69,7 @@ bool cParsedNBT::Parse(void)
m_Pos = 1;
- RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
+ RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
RETURN_FALSE_IF_FALSE(ReadCompound());
return true;
@@ -329,7 +329,7 @@ int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cFastNBTWriter:
cFastNBTWriter::cFastNBTWriter(const AString & a_RootTagName) :
diff --git a/src/WorldStorage/FastNBT.h b/src/WorldStorage/FastNBT.h
index fe28005ac..4ef72e379 100644
--- a/src/WorldStorage/FastNBT.h
+++ b/src/WorldStorage/FastNBT.h
@@ -5,11 +5,11 @@
/*
The fast parser parses the data into a vector of cFastNBTTag structures. These structures describe the NBT tree,
-but themselves are allocated in a vector, thus minimizing reallocation.
+but themselves are allocated in a vector, thus minimizing reallocation.
The structures have a minimal constructor, setting all member "pointers" to "invalid".
The fast writer doesn't need a NBT tree structure built beforehand, it is commanded to open, append and close tags
-(just like XML); it keeps the internal tag stack and reports errors in usage.
+(just like XML); it keeps the internal tag stack and reports errors in usage.
It directly outputs a string containing the serialized NBT data.
*/
@@ -160,7 +160,7 @@ public:
/** Returns the direct child tag of the specified name, or -1 if no such tag. */
int FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLength = 0) const;
- /** Returns the child tag of the specified path (Name1\Name2\Name3...), or -1 if no such tag. */
+ /** Returns the child tag of the specified path (Name1/Name2/Name3...), or -1 if no such tag. */
int FindTagByPath(int a_Tag, const AString & a_Path) const;
eTagType GetType(int a_Tag) const { return m_Tags[(size_t)a_Tag].m_Type; }
@@ -173,7 +173,7 @@ public:
}
/** Returns the value stored in a Byte tag. Not valid for any other tag type. */
- inline unsigned char GetByte(int a_Tag) const
+ inline unsigned char GetByte(int a_Tag) const
{
ASSERT(m_Tags[(size_t)a_Tag].m_Type == TAG_Byte);
return (unsigned char)(m_Data[(size_t)m_Tags[(size_t)a_Tag].m_DataStart]);
diff --git a/src/WorldStorage/FireworksSerializer.cpp b/src/WorldStorage/FireworksSerializer.cpp
index 181cfde0d..ecb600483 100644
--- a/src/WorldStorage/FireworksSerializer.cpp
+++ b/src/WorldStorage/FireworksSerializer.cpp
@@ -72,7 +72,7 @@ void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNB
for (int explosiontag = a_NBT.GetFirstChild(a_TagIdx); explosiontag >= 0; explosiontag = a_NBT.GetNextSibling(explosiontag))
{
eTagType TagType = a_NBT.GetType(explosiontag);
- if (TagType == TAG_Byte) // Custon name tag
+ if (TagType == TAG_Byte) // Custon name tag
{
AString ExplosionName = a_NBT.GetName(explosiontag);
@@ -98,7 +98,7 @@ void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNB
// Divide by four as data length returned in bytes
size_t DataLength = a_NBT.GetDataLength(explosiontag);
// round to the next highest multiple of four
- DataLength -= DataLength % 4;
+ DataLength -= DataLength % 4;
if (DataLength == 0)
{
continue;
@@ -114,7 +114,7 @@ void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNB
{
size_t DataLength = a_NBT.GetDataLength(explosiontag) / 4;
// round to the next highest multiple of four
- DataLength -= DataLength % 4;
+ DataLength -= DataLength % 4;
if (DataLength == 0)
{
continue;
@@ -135,7 +135,7 @@ void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNB
for (int fireworkstag = a_NBT.GetFirstChild(a_TagIdx); fireworkstag >= 0; fireworkstag = a_NBT.GetNextSibling(fireworkstag))
{
eTagType TagType = a_NBT.GetType(fireworkstag);
- if (TagType == TAG_Byte) // Custon name tag
+ if (TagType == TAG_Byte) // Custon name tag
{
if (a_NBT.GetName(fireworkstag) == "Flight")
{
diff --git a/src/WorldStorage/MapSerializer.h b/src/WorldStorage/MapSerializer.h
index eb7678a08..4fa40f6f9 100644
--- a/src/WorldStorage/MapSerializer.h
+++ b/src/WorldStorage/MapSerializer.h
@@ -52,10 +52,9 @@ private:
/** Utility class used to serialize item ID counts.
- *
- * In order to perform bounds checking (while loading),
- * the last registered ID of each item is serialized to an NBT file.
- */
+In order to perform bounds checking (while loading),
+the last registered ID of each item is serialized to an NBT file.
+*/
class cIDCountSerializer
{
public:
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index 317ace795..e435a1b1f 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -10,6 +10,7 @@
#include "../StringCompression.h"
#include "FastNBT.h"
+#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/DispenserEntity.h"
@@ -29,6 +30,7 @@
#include "../Entities/Minecart.h"
#include "../Entities/Pickup.h"
#include "../Entities/ArrowEntity.h"
+#include "../Entities/SplashPotionEntity.h"
#include "../Entities/TNTEntity.h"
#include "../Entities/ExpOrb.h"
#include "../Entities/HangingEntity.h"
@@ -175,10 +177,27 @@ void cNBTChunkSerializer::AddBasicTileEntity(cBlockEntity * a_Entity, const char
-void cNBTChunkSerializer::AddChestEntity(cChestEntity * a_Entity)
+void cNBTChunkSerializer::AddBeaconEntity(cBeaconEntity * a_Entity)
{
m_Writer.BeginCompound("");
- AddBasicTileEntity(a_Entity, "Chest");
+ AddBasicTileEntity(a_Entity, "Beacon");
+ m_Writer.AddInt("Levels", a_Entity->GetBeaconLevel());
+ m_Writer.AddInt("Primary", (int)a_Entity->GetPrimaryEffect());
+ m_Writer.AddInt("Secondary", (int)a_Entity->GetSecondaryEffect());
+ m_Writer.BeginList("Items", TAG_Compound);
+ AddItemGrid(a_Entity->GetContents());
+ m_Writer.EndList();
+ m_Writer.EndCompound();
+}
+
+
+
+
+
+void cNBTChunkSerializer::AddChestEntity(cChestEntity * a_Entity, BLOCKTYPE a_ChestType)
+{
+ m_Writer.BeginCompound("");
+ AddBasicTileEntity(a_Entity, (a_ChestType == E_BLOCK_CHEST) ? "Chest" : "TrappedChest");
m_Writer.BeginList("Items", TAG_Compound);
AddItemGrid(a_Entity->GetContents());
m_Writer.EndList();
@@ -278,7 +297,7 @@ void cNBTChunkSerializer::AddCommandBlockEntity(cCommandBlockEntity * a_CmdBlock
m_Writer.AddString("Command", a_CmdBlock->GetCommand());
m_Writer.AddInt ("SuccessCount", a_CmdBlock->GetResult());
m_Writer.AddString("LastOutput", a_CmdBlock->GetLastOutput());
- m_Writer.AddByte ("TrackOutput", 1); // TODO 2014-01-18 xdot: Figure out what TrackOutput is and save it.
+ m_Writer.AddByte ("TrackOutput", 1); // TODO 2014-01-18 xdot: Figure out what TrackOutput is and save it.
m_Writer.EndCompound();
}
@@ -550,10 +569,18 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster)
}
case cMonster::mtWolf:
{
- m_Writer.AddString("Owner", ((const cWolf *)a_Monster)->GetOwner());
- m_Writer.AddByte("Sitting", (((const cWolf *)a_Monster)->IsSitting() ? 1 : 0));
- m_Writer.AddByte("Angry", (((const cWolf *)a_Monster)->IsAngry() ? 1 : 0));
- m_Writer.AddInt("CollarColor", ((const cWolf *)a_Monster)->GetCollarColor());
+ const cWolf & Wolf = *((cWolf *)a_Monster);
+ if (!Wolf.GetOwnerName().empty())
+ {
+ m_Writer.AddString("Owner", Wolf.GetOwnerName());
+ }
+ if (!Wolf.GetOwnerUUID().empty())
+ {
+ m_Writer.AddString("OwnerUUID", Wolf.GetOwnerUUID());
+ }
+ m_Writer.AddByte("Sitting", Wolf.IsSitting() ? 1 : 0);
+ m_Writer.AddByte("Angry", Wolf.IsAngry() ? 1 : 0);
+ m_Writer.AddInt("CollarColor", Wolf.GetCollarColor());
break;
}
case cMonster::mtZombie:
@@ -604,6 +631,17 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
m_Writer.AddDouble("damage", Arrow->GetDamageCoeff());
break;
}
+ case cProjectileEntity::pkSplashPotion:
+ {
+ cSplashPotionEntity * Potion = (cSplashPotionEntity *)a_Projectile;
+
+ m_Writer.AddInt("EffectType", (Int16)Potion->GetEntityEffectType());
+ m_Writer.AddInt("EffectDuration", (Int16)Potion->GetEntityEffect().GetDuration());
+ m_Writer.AddShort("EffectIntensity", Potion->GetEntityEffect().GetIntensity());
+ m_Writer.AddDouble("EffectDistanceModifier", Potion->GetEntityEffect().GetDistanceModifier());
+ m_Writer.AddInt("PotionName", Potion->GetPotionColor());
+ break;
+ }
case cProjectileEntity::pkGhastFireball:
{
m_Writer.AddInt("ExplosionPower", 1);
@@ -619,7 +657,7 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
{
ASSERT(!"Unsaved projectile entity!");
}
- } // switch (ProjectileKind)
+ } // switch (ProjectileKind)
if (!a_Projectile->GetCreatorName().empty())
{
@@ -813,19 +851,22 @@ void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity)
// Add tile-entity into NBT:
switch (a_Entity->GetBlockType())
{
- case E_BLOCK_CHEST: AddChestEntity ((cChestEntity *) a_Entity); break;
- case E_BLOCK_DISPENSER: AddDispenserEntity ((cDispenserEntity *) a_Entity); break;
- case E_BLOCK_DROPPER: AddDropperEntity ((cDropperEntity *) a_Entity); break;
- case E_BLOCK_ENDER_CHEST: /* No need to be saved */ break;
- case E_BLOCK_FLOWER_POT: AddFlowerPotEntity ((cFlowerPotEntity *) a_Entity); break;
- case E_BLOCK_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break;
- case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break;
- case E_BLOCK_SIGN_POST:
- case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break;
- case E_BLOCK_HEAD: AddMobHeadEntity ((cMobHeadEntity *) a_Entity); break;
- case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break;
- case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break;
- case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity((cCommandBlockEntity *) a_Entity); break;
+ case E_BLOCK_BEACON: AddBeaconEntity ((cBeaconEntity *) a_Entity); break;
+ case E_BLOCK_CHEST: AddChestEntity ((cChestEntity *) a_Entity, a_Entity->GetBlockType()); break;
+ case E_BLOCK_COMMAND_BLOCK: AddCommandBlockEntity((cCommandBlockEntity *)a_Entity); break;
+ case E_BLOCK_DISPENSER: AddDispenserEntity ((cDispenserEntity *) a_Entity); break;
+ case E_BLOCK_DROPPER: AddDropperEntity ((cDropperEntity *) a_Entity); break;
+ case E_BLOCK_ENDER_CHEST: /* No data to be saved */ break;
+ case E_BLOCK_FLOWER_POT: AddFlowerPotEntity ((cFlowerPotEntity *) a_Entity); break;
+ case E_BLOCK_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break;
+ case E_BLOCK_HEAD: AddMobHeadEntity ((cMobHeadEntity *) a_Entity); break;
+ case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break;
+ case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break;
+ case E_BLOCK_LIT_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break;
+ case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break;
+ case E_BLOCK_SIGN_POST: AddSignEntity ((cSignEntity *) a_Entity); break;
+ case E_BLOCK_TRAPPED_CHEST: AddChestEntity ((cChestEntity *) a_Entity, a_Entity->GetBlockType()); break;
+ case E_BLOCK_WALLSIGN: AddSignEntity ((cSignEntity *) a_Entity); break;
default:
{
diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h
index 112afc27e..4c229a65c 100644
--- a/src/WorldStorage/NBTChunkSerializer.h
+++ b/src/WorldStorage/NBTChunkSerializer.h
@@ -20,6 +20,7 @@ class cFastNBTWriter;
class cEntity;
class cBlockEntity;
class cBoat;
+class cBeaconEntity;
class cChestEntity;
class cCommandBlockEntity;
class cDispenserEntity;
@@ -46,6 +47,7 @@ class cTNTEntity;
class cExpOrb;
class cHangingEntity;
class cItemFrame;
+class cEntityEffect;
@@ -92,7 +94,8 @@ protected:
// Block entities:
void AddBasicTileEntity(cBlockEntity * a_Entity, const char * a_EntityTypeID);
- void AddChestEntity (cChestEntity * a_Entity);
+ void AddBeaconEntity (cBeaconEntity * a_Entity);
+ void AddChestEntity (cChestEntity * a_Entity, BLOCKTYPE a_ChestType);
void AddDispenserEntity(cDispenserEntity * a_Entity);
void AddDropperEntity (cDropperEntity * a_Entity);
void AddFurnaceEntity (cFurnaceEntity * a_Furnace);
diff --git a/src/WorldStorage/SchematicFileSerializer.cpp b/src/WorldStorage/SchematicFileSerializer.cpp
index 1cf99efd9..64f4cb00d 100644
--- a/src/WorldStorage/SchematicFileSerializer.cpp
+++ b/src/WorldStorage/SchematicFileSerializer.cpp
@@ -44,7 +44,7 @@ public:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cSchematicFileSerializer:
bool cSchematicFileSerializer::LoadFromSchematicFile(cBlockArea & a_BlockArea, const AString & a_FileName)
diff --git a/src/WorldStorage/ScoreboardSerializer.cpp b/src/WorldStorage/ScoreboardSerializer.cpp
index 6c885bb45..da8236e0d 100644
--- a/src/WorldStorage/ScoreboardSerializer.cpp
+++ b/src/WorldStorage/ScoreboardSerializer.cpp
@@ -117,7 +117,7 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer)
a_Writer.EndCompound();
}
- a_Writer.EndList(); // Objectives
+ a_Writer.EndList(); // Objectives
a_Writer.BeginList("PlayerScores", TAG_Compound);
@@ -138,7 +138,7 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer)
}
}
- a_Writer.EndList(); // PlayerScores
+ a_Writer.EndList(); // PlayerScores
a_Writer.BeginList("Teams", TAG_Compound);
@@ -169,7 +169,7 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer)
a_Writer.EndCompound();
}
- a_Writer.EndList(); // Teams
+ a_Writer.EndList(); // Teams
a_Writer.BeginCompound("DisplaySlots");
@@ -182,9 +182,9 @@ void cScoreboardSerializer::SaveScoreboardToNBT(cFastNBTWriter & a_Writer)
Objective = m_ScoreBoard->GetObjectiveIn(cScoreboard::dsName);
a_Writer.AddString("slot_2", (Objective == NULL) ? "" : Objective->GetName());
- a_Writer.EndCompound(); // DisplaySlots
+ a_Writer.EndCompound(); // DisplaySlots
- a_Writer.EndCompound(); // Data
+ a_Writer.EndCompound(); // Data
}
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index f13c4d4d2..a9c9ae4b5 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -14,7 +14,10 @@
#include "../Item.h"
#include "../ItemGrid.h"
#include "../StringCompression.h"
+#include "../SetChunkData.h"
+#include "../Root.h"
+#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/DispenserEntity.h"
@@ -36,6 +39,7 @@
#include "../Entities/Minecart.h"
#include "../Entities/Pickup.h"
#include "../Entities/ArrowEntity.h"
+#include "../Entities/SplashPotionEntity.h"
#include "../Entities/ThrownEggEntity.h"
#include "../Entities/ThrownEnderPearlEntity.h"
#include "../Entities/ThrownSnowballEntity.h"
@@ -46,6 +50,8 @@
#include "../Entities/HangingEntity.h"
#include "../Entities/ItemFrame.h"
+#include "../Protocol/MojangAPI.h"
+
@@ -55,7 +61,7 @@ thus making skylight visible in Minutor's Lighting mode
*/
// #define DEBUG_SKYLIGHT
-/** Maximum number of MCA files that are cached in memory.
+/** Maximum number of MCA files that are cached in memory.
Since only the header is actually in the memory, this number can be high, but still, each file means an OS FS handle.
*/
#define MAX_MCA_FILES 32
@@ -68,7 +74,7 @@ Since only the header is actually in the memory, this number can be high, but st
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWSSAnvil:
cWSSAnvil::cWSSAnvil(cWorld * a_World, int a_CompressionFactor) :
@@ -390,15 +396,15 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
} // for y
//*/
- m_World->SetChunkData(
+ m_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
- BlockTypes, MetaData,
+ BlockTypes, MetaData,
IsLightValid ? BlockLight : NULL,
IsLightValid ? SkyLight : NULL,
NULL, Biomes,
Entities, BlockEntities,
false
- );
+ )));
return true;
}
@@ -448,7 +454,7 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_
const char * BlockLight = (const char *)(Serializer.m_BlockSkyLight);
#else
const char * BlockLight = (const char *)(Serializer.m_BlockLight);
- #endif
+ #endif
const char * BlockSkyLight = (const char *)(Serializer.m_BlockSkyLight);
for (int Y = 0; Y < 16; Y++)
{
@@ -462,7 +468,7 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_
}
a_Writer.EndList(); // "Sections"
- // Store the information that the lighting is valid.
+ // Store the information that the lighting is valid.
// For compatibility reason, the default is "invalid" (missing) - this means older data is re-lighted upon loading.
if (Serializer.IsLightValid())
{
@@ -580,9 +586,13 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
{
continue;
}
- if (strncmp(a_NBT.GetData(sID), "Chest", a_NBT.GetDataLength(sID)) == 0)
+ if (strncmp(a_NBT.GetData(sID), "Beacon", a_NBT.GetDataLength(sID)) == 0)
+ {
+ LoadBeaconFromNBT(a_BlockEntities, a_NBT, Child);
+ }
+ else if (strncmp(a_NBT.GetData(sID), "Chest", a_NBT.GetDataLength(sID)) == 0)
{
- LoadChestFromNBT(a_BlockEntities, a_NBT, Child);
+ LoadChestFromNBT(a_BlockEntities, a_NBT, Child, E_BLOCK_CHEST);
}
else if (strncmp(a_NBT.GetData(sID), "Control", a_NBT.GetDataLength(sID)) == 0)
{
@@ -624,6 +634,10 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
{
LoadDispenserFromNBT(a_BlockEntities, a_NBT, Child);
}
+ else if (strncmp(a_NBT.GetData(sID), "TrappedChest", a_NBT.GetDataLength(sID)) == 0)
+ {
+ LoadChestFromNBT(a_BlockEntities, a_NBT, Child, E_BLOCK_TRAPPED_CHEST);
+ }
// TODO: Other block entities
} // for Child - tag children
}
@@ -740,7 +754,50 @@ void cWSSAnvil::LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a
-void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+void cWSSAnvil::LoadBeaconFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
+ int x, y, z;
+ if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ {
+ return;
+ }
+
+ std::auto_ptr<cBeaconEntity> Beacon(new cBeaconEntity(x, y, z, m_World));
+
+ int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Levels");
+ if (CurrentLine >= 0)
+ {
+ Beacon->SetBeaconLevel((char)a_NBT.GetInt(CurrentLine));
+ }
+
+ CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Primary");
+ if (CurrentLine >= 0)
+ {
+ Beacon->SetPrimaryEffect((cEntityEffect::eType)a_NBT.GetInt(CurrentLine));
+ }
+
+ CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Secondary");
+ if (CurrentLine >= 0)
+ {
+ Beacon->SetSecondaryEffect((cEntityEffect::eType)a_NBT.GetInt(CurrentLine));
+ }
+
+ // We are better than mojang, we load/save the beacon inventory!
+ int Items = a_NBT.FindChildByName(a_TagIdx, "Items");
+ if ((Items >= 0) && (a_NBT.GetType(Items) == TAG_List))
+ {
+ LoadItemGridFromNBT(Beacon->GetContents(), a_NBT, Items);
+ }
+
+ a_BlockEntities.push_back(Beacon.release());
+}
+
+
+
+
+
+void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_ChestType)
{
ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
int x, y, z;
@@ -753,7 +810,7 @@ void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cPars
{
return; // Make it an empty chest - the chunk loader will provide an empty cChestEntity for this
}
- std::auto_ptr<cChestEntity> Chest(new cChestEntity(x, y, z, m_World));
+ std::auto_ptr<cChestEntity> Chest(new cChestEntity(x, y, z, m_World, a_ChestType));
LoadItemGridFromNBT(Chest->GetContents(), a_NBT, Items);
a_BlockEntities.push_back(Chest.release());
}
@@ -1152,6 +1209,10 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
{
LoadArrowFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
}
+ else if (strncmp(a_IDTag, "SplashPotion", a_IDTagLength) == 0)
+ {
+ LoadSplashPotionFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
+ }
else if (strncmp(a_IDTag, "Snowball", a_IDTagLength) == 0)
{
LoadSnowballFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
@@ -1347,7 +1408,7 @@ void cWSSAnvil::LoadFallingBlockFromNBT(cEntityList & a_Entities, const cParsedN
void cWSSAnvil::LoadMinecartRFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
- std::auto_ptr<cRideableMinecart> Minecart(new cRideableMinecart(0, 0, 0, cItem(), 1)); // TODO: Load the block and the height
+ std::auto_ptr<cRideableMinecart> Minecart(new cRideableMinecart(0, 0, 0, cItem(), 1)); // TODO: Load the block and the height
if (!LoadEntityBaseFromNBT(*Minecart.get(), a_NBT, a_TagIdx))
{
return;
@@ -1456,7 +1517,7 @@ void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a
return;
}
- std::auto_ptr<cPickup> Pickup(new cPickup(0, 0, 0, Item, false)); // Pickup delay doesn't matter, just say false
+ std::auto_ptr<cPickup> Pickup(new cPickup(0, 0, 0, Item, false)); // Pickup delay doesn't matter, just say false
if (!LoadEntityBaseFromNBT(*Pickup.get(), a_NBT, a_TagIdx))
{
return;
@@ -1658,6 +1719,29 @@ void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
+void cWSSAnvil::LoadSplashPotionFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ std::auto_ptr<cSplashPotionEntity> SplashPotion(new cSplashPotionEntity(NULL, 0, 0, 0, Vector3d(0, 0, 0), cItem()));
+ if (!LoadProjectileBaseFromNBT(*SplashPotion.get(), a_NBT, a_TagIdx))
+ {
+ return;
+ }
+
+ int EffectDuration = a_NBT.FindChildByName(a_TagIdx, "EffectDuration");
+ int EffectIntensity = a_NBT.FindChildByName(a_TagIdx, "EffectIntensity");
+ int EffectDistanceModifier = a_NBT.FindChildByName(a_TagIdx, "EffectDistanceModifier");
+
+ SplashPotion->SetEntityEffectType((cEntityEffect::eType) a_NBT.FindChildByName(a_TagIdx, "EffectType"));
+ SplashPotion->SetEntityEffect(cEntityEffect(EffectDuration, EffectIntensity, EffectDistanceModifier));
+ SplashPotion->SetPotionColor(a_NBT.FindChildByName(a_TagIdx, "PotionName"));
+
+ // Store the new splash potion in the entities list:
+ a_Entities.push_back(SplashPotion.release());
+}
+
+
+
+
void cWSSAnvil::LoadSnowballFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
@@ -2082,10 +2166,11 @@ void cWSSAnvil::LoadPigFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NB
void cWSSAnvil::LoadSheepFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
int ColorIdx = a_NBT.FindChildByName(a_TagIdx, "Color");
-
- if (ColorIdx < 0) { return; }
-
- int Color = (int)a_NBT.GetByte(ColorIdx);
+ int Color = -1;
+ if (ColorIdx > 0)
+ {
+ Color = (int)a_NBT.GetByte(ColorIdx);
+ }
std::auto_ptr<cSheep> Monster(new cSheep(Color));
if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx))
@@ -2098,6 +2183,12 @@ void cWSSAnvil::LoadSheepFromNBT(cEntityList & a_Entities, const cParsedNBT & a_
return;
}
+ int ShearedIdx = a_NBT.FindChildByName(a_TagIdx, "Sheared");
+ if (ShearedIdx > 0)
+ {
+ Monster->SetSheared(a_NBT.GetByte(ShearedIdx) != 0);
+ }
+
a_Entities.push_back(Monster.release());
}
@@ -2323,16 +2414,9 @@ void cWSSAnvil::LoadWolfFromNBT(cEntityList & a_Entities, const cParsedNBT & a_N
{
return;
}
- int OwnerIdx = a_NBT.FindChildByName(a_TagIdx, "Owner");
- if (OwnerIdx > 0)
- {
- AString OwnerName = a_NBT.GetString(OwnerIdx);
- if (OwnerName != "")
- {
- Monster->SetOwner(OwnerName);
- Monster->SetIsTame(true);
- }
- }
+
+ LoadWolfOwner(*Monster.get(), a_NBT, a_TagIdx);
+
int SittingIdx = a_NBT.FindChildByName(a_TagIdx, "Sitting");
if (SittingIdx > 0)
{
@@ -2404,6 +2488,64 @@ void cWSSAnvil::LoadPigZombieFromNBT(cEntityList & a_Entities, const cParsedNBT
+void cWSSAnvil::LoadWolfOwner(cWolf & a_Wolf, const cParsedNBT & a_NBT, int a_TagIdx)
+{
+ // Load the owner information. OwnerUUID or Owner may be specified, possibly both:
+ AString OwnerUUID, OwnerName;
+ int OwnerUUIDIdx = a_NBT.FindChildByName(a_TagIdx, "OwnerUUID");
+ if (OwnerUUIDIdx > 0)
+ {
+ OwnerUUID = a_NBT.GetString(OwnerUUIDIdx);
+ }
+ int OwnerIdx = a_NBT.FindChildByName(a_TagIdx, "Owner");
+ if (OwnerIdx > 0)
+ {
+ OwnerName = a_NBT.GetString(OwnerIdx);
+ }
+ if (OwnerName.empty() && OwnerUUID.empty())
+ {
+ // There is no owner, bail out:
+ return;
+ }
+
+ // Convert name to UUID, if needed:
+ if (OwnerUUID.empty())
+ {
+ // This wolf has only playername stored (pre-1.7.6), look up the UUID
+ // The lookup is blocking, but we're running in a separate thread, so it's ok
+ OwnerUUID = cRoot::Get()->GetMojangAPI().GetUUIDFromPlayerName(OwnerName);
+ if (OwnerUUID.empty())
+ {
+ // Not a known player, un-tame the wolf by bailing out
+ return;
+ }
+ }
+ else
+ {
+ // Normalize the UUID:
+ OwnerUUID = cMojangAPI::MakeUUIDShort(OwnerUUID);
+ }
+
+ // Convert UUID to name, if needed:
+ if (OwnerName.empty())
+ {
+ // The lookup is blocking, but we're running in a separate thread, so it's ok
+ OwnerName = cRoot::Get()->GetMojangAPI().GetPlayerNameFromUUID(OwnerUUID);
+ if (OwnerName.empty())
+ {
+ // Not a known player, un-tame the wolf by bailing out
+ return;
+ }
+ }
+
+ a_Wolf.SetOwner(OwnerName, OwnerUUID);
+ a_Wolf.SetIsTame(true);
+}
+
+
+
+
+
bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
{
double Pos[3];
@@ -2435,10 +2577,7 @@ bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_N
// Load health:
int Health = a_NBT.FindChildByName(a_TagIdx, "Health");
- if (Health > 0)
- {
- a_Entity.SetHealth(a_NBT.GetShort(Health));
- }
+ a_Entity.SetHealth(Health > 0 ? a_NBT.GetShort(Health) : a_Entity.GetMaxHealth());
return true;
}
@@ -2459,8 +2598,14 @@ bool cWSSAnvil::LoadMonsterBaseFromNBT(cMonster & a_Monster, const cParsedNBT &
a_Monster.SetDropChanceChestplate(DropChance[2]);
a_Monster.SetDropChanceLeggings(DropChance[3]);
a_Monster.SetDropChanceBoots(DropChance[4]);
- bool CanPickUpLoot = (a_NBT.GetByte(a_NBT.FindChildByName(a_TagIdx, "CanPickUpLoot")) == 1);
- a_Monster.SetCanPickUpLoot(CanPickUpLoot);
+
+ int LootTag = a_NBT.FindChildByName(a_TagIdx, "CanPickUpLoot");
+ if (LootTag > 0)
+ {
+ bool CanPickUpLoot = (a_NBT.GetByte(LootTag) == 1);
+ a_Monster.SetCanPickUpLoot(CanPickUpLoot);
+ }
+
return true;
}
@@ -2553,7 +2698,7 @@ bool cWSSAnvil::GetBlockEntityNBTPos(const cParsedNBT & a_NBT, int a_TagIdx, int
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWSSAnvil::cMCAFile:
cWSSAnvil::cMCAFile::cMCAFile(const AString & a_FileName, int a_RegionX, int a_RegionZ) :
diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h
index 7542a828a..a41268f4c 100644
--- a/src/WorldStorage/WSSAnvil.h
+++ b/src/WorldStorage/WSSAnvil.h
@@ -21,6 +21,7 @@ class cItemGrid;
class cProjectileEntity;
class cHangingEntity;
+class cWolf;
@@ -133,7 +134,8 @@ protected:
*/
void LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a_NBT, int a_ItemsTagIdx, int s_SlotOffset = 0);
- void LoadChestFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadBeaconFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadChestFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_ChestType);
void LoadDispenserFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadDropperFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadFlowerPotFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
@@ -153,7 +155,7 @@ protected:
void LoadPickupFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadTNTFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadExpOrbFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadHangingFromNBT (cHangingEntity & a_Hanging,const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadHangingFromNBT (cHangingEntity & a_Hanging, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadItemFrameFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadMinecartRFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
@@ -163,6 +165,7 @@ protected:
void LoadMinecartHFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadArrowFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ void LoadSplashPotionFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadSnowballFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadEggFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadFireballFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
@@ -199,6 +202,9 @@ protected:
void LoadZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
void LoadPigZombieFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
+ /** Loads the wolf's owner information from the NBT into the specified wolf entity. */
+ void LoadWolfOwner(cWolf & a_Wolf, const cParsedNBT & a_NBT, int a_TagIdx);
+
/// Loads entity common data from the NBT compound; returns true if successful
bool LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx);
diff --git a/src/WorldStorage/WSSCompact.cpp b/src/WorldStorage/WSSCompact.cpp
index a853f6ec9..58f9e3cab 100644
--- a/src/WorldStorage/WSSCompact.cpp
+++ b/src/WorldStorage/WSSCompact.cpp
@@ -9,6 +9,7 @@
#include "zlib/zlib.h"
#include "json/json.h"
#include "../StringCompression.h"
+#include "../BlockEntities/BeaconEntity.h"
#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../BlockEntities/DispenserEntity.h"
@@ -18,6 +19,7 @@
#include "../BlockEntities/MobHeadEntity.h"
#include "../BlockEntities/NoteEntity.h"
#include "../BlockEntities/SignEntity.h"
+#include "../SetChunkData.h"
@@ -48,7 +50,7 @@ const int MAX_DIRTY_CHUNKS = 16;
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cJsonChunkSerializer:
cJsonChunkSerializer::cJsonChunkSerializer(void) :
@@ -74,6 +76,7 @@ void cJsonChunkSerializer::BlockEntity(cBlockEntity * a_BlockEntity)
const char * SaveInto = NULL;
switch (a_BlockEntity->GetBlockType())
{
+ case E_BLOCK_BEACON: SaveInto = "Beacons"; break;
case E_BLOCK_CHEST: SaveInto = "Chests"; break;
case E_BLOCK_DISPENSER: SaveInto = "Dispensers"; break;
case E_BLOCK_DROPPER: SaveInto = "Droppers"; break;
@@ -120,7 +123,7 @@ void cJsonChunkSerializer::LightIsValid(bool a_IsLightValid)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWSSCompact:
cWSSCompact::~cWSSCompact()
@@ -196,7 +199,7 @@ cWSSCompact::cPAKFile * cWSSCompact::LoadPAKFile(const cChunkCoords & a_Chunk)
// Load it anew:
AString FileName;
- Printf(FileName, "%s/X%i_Z%i.pak", m_World->GetName().c_str(), LayerX, LayerZ );
+ Printf(FileName, "%s/X%i_Z%i.pak", m_World->GetName().c_str(), LayerX, LayerZ);
cPAKFile * f = new cPAKFile(FileName, LayerX, LayerZ, m_CompressionFactor);
if (f == NULL)
{
@@ -267,16 +270,34 @@ bool cWSSCompact::EraseChunkData(const cChunkCoords & a_Chunk)
void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities, cWorld * a_World)
{
+ // Load beacon:
+ Json::Value AllBeacons = a_Value.get("Beacons", Json::nullValue);
+ if (!AllBeacons.empty())
+ {
+ for (Json::Value::iterator itr = AllBeacons.begin(); itr != AllBeacons.end(); ++itr)
+ {
+ std::auto_ptr<cBeaconEntity> BeaconEntity(new cBeaconEntity(0, 0, 0, a_World));
+ if (!BeaconEntity->LoadFromJson(*itr))
+ {
+ LOGWARNING("ERROR READING BEACON FROM JSON!");
+ }
+ else
+ {
+ a_BlockEntities.push_back(BeaconEntity.release());
+ }
+ } // for itr - AllBeacons[]
+ }
+
// Load chests:
Json::Value AllChests = a_Value.get("Chests", Json::nullValue);
if (!AllChests.empty())
{
- for (Json::Value::iterator itr = AllChests.begin(); itr != AllChests.end(); ++itr )
+ for (Json::Value::iterator itr = AllChests.begin(); itr != AllChests.end(); ++itr)
{
- std::auto_ptr<cChestEntity> ChestEntity(new cChestEntity(0, 0, 0, a_World));
+ std::auto_ptr<cChestEntity> ChestEntity(new cChestEntity(0, 0, 0, a_World, E_BLOCK_CHEST));
if (!ChestEntity->LoadFromJson(*itr))
{
- LOGWARNING("ERROR READING CHEST FROM JSON!" );
+ LOGWARNING("ERROR READING CHEST FROM JSON!");
}
else
{
@@ -292,7 +313,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En
std::auto_ptr<cDispenserEntity> DispenserEntity(new cDispenserEntity(0, 0, 0, a_World));
if (!DispenserEntity->LoadFromJson(*itr))
{
- LOGWARNING("ERROR READING DISPENSER FROM JSON!" );
+ LOGWARNING("ERROR READING DISPENSER FROM JSON!");
}
else
{
@@ -307,7 +328,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En
std::auto_ptr<cFlowerPotEntity> FlowerPotEntity(new cFlowerPotEntity(0, 0, 0, a_World));
if (!FlowerPotEntity->LoadFromJson(*itr))
{
- LOGWARNING("ERROR READING FLOWERPOT FROM JSON!" );
+ LOGWARNING("ERROR READING FLOWERPOT FROM JSON!");
}
else
{
@@ -323,7 +344,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En
std::auto_ptr<cFurnaceEntity> FurnaceEntity(new cFurnaceEntity(0, 0, 0, E_BLOCK_FURNACE, 0, a_World));
if (!FurnaceEntity->LoadFromJson(*itr))
{
- LOGWARNING("ERROR READING FURNACE FROM JSON!" );
+ LOGWARNING("ERROR READING FURNACE FROM JSON!");
}
else
{
@@ -353,7 +374,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En
std::auto_ptr<cNoteEntity> NoteEntity(new cNoteEntity(0, 0, 0, a_World));
if (!NoteEntity->LoadFromJson(*itr))
{
- LOGWARNING("ERROR READING NOTE BLOCK FROM JSON!" );
+ LOGWARNING("ERROR READING NOTE BLOCK FROM JSON!");
}
else
{
@@ -368,7 +389,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En
std::auto_ptr<cJukeboxEntity> JukeboxEntity(new cJukeboxEntity(0, 0, 0, a_World));
if (!JukeboxEntity->LoadFromJson(*itr))
{
- LOGWARNING("ERROR READING JUKEBOX FROM JSON!" );
+ LOGWARNING("ERROR READING JUKEBOX FROM JSON!");
}
else
{
@@ -383,7 +404,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En
std::auto_ptr<cCommandBlockEntity> CommandBlockEntity(new cCommandBlockEntity(0, 0, 0, a_World));
if (!CommandBlockEntity->LoadFromJson(*itr))
{
- LOGWARNING("ERROR READING COMMAND BLOCK FROM JSON!" );
+ LOGWARNING("ERROR READING COMMAND BLOCK FROM JSON!");
}
else
{
@@ -398,7 +419,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En
std::auto_ptr<cMobHeadEntity> MobHeadEntity(new cMobHeadEntity(0, 0, 0, a_World));
if (!MobHeadEntity->LoadFromJson(*itr))
{
- LOGWARNING("ERROR READING MOB HEAD FROM JSON!" );
+ LOGWARNING("ERROR READING MOB HEAD FROM JSON!");
}
else
{
@@ -411,7 +432,7 @@ void cWSSCompact::LoadEntitiesFromJson(Json::Value & a_Value, cEntityList & a_En
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWSSCompact::cPAKFile
#define READ(Var) \
@@ -427,8 +448,8 @@ cWSSCompact::cPAKFile::cPAKFile(const AString & a_FileName, int a_LayerX, int a_
m_LayerX(a_LayerX),
m_LayerZ(a_LayerZ),
m_NumDirty(0),
- m_ChunkVersion( CHUNK_VERSION ), // Init with latest version
- m_PakVersion( PAK_VERSION )
+ m_ChunkVersion( CHUNK_VERSION), // Init with latest version
+ m_PakVersion( PAK_VERSION)
{
cFile f;
if (!f.Open(m_FileName, cFile::fmRead))
@@ -445,18 +466,24 @@ cWSSCompact::cPAKFile::cPAKFile(const AString & a_FileName, int a_LayerX, int a_
}
READ(m_ChunkVersion);
- switch( m_ChunkVersion )
+ switch (m_ChunkVersion)
{
- case 1:
- m_ChunkSize.Set(16, 128, 16);
- break;
- case 2:
- case 3:
- m_ChunkSize.Set(16, 256, 16);
- break;
- default:
- LOGERROR("File \"%s\" is in an unknown chunk format (%d)", m_FileName.c_str(), m_ChunkVersion);
- return;
+ case 1:
+ {
+ m_ChunkSize.Set(16, 128, 16);
+ break;
+ }
+ case 2:
+ case 3:
+ {
+ m_ChunkSize.Set(16, 256, 16);
+ break;
+ }
+ default:
+ {
+ LOGERROR("File \"%s\" is in an unknown chunk format (%d)", m_FileName.c_str(), m_ChunkVersion);
+ return;
+ }
};
short NumChunks = 0;
@@ -486,12 +513,12 @@ cWSSCompact::cPAKFile::cPAKFile(const AString & a_FileName, int a_LayerX, int a_
return;
}
- if( m_ChunkVersion == 1 ) // Convert chunks to version 2
+ if (m_ChunkVersion == 1) // Convert chunks to version 2
{
UpdateChunk1To2();
}
#if AXIS_ORDER == AXIS_ORDER_XZY
- if( m_ChunkVersion == 2 ) // Convert chunks to version 3
+ if (m_ChunkVersion == 2) // Convert chunks to version 3
{
UpdateChunk2To3();
}
@@ -574,9 +601,9 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
{
sChunkHeader * Header = *itr;
- if( ChunksConverted % 32 == 0 )
+ if (ChunksConverted % 32 == 0)
{
- LOGINFO("Updating \"%s\" version 1 to version 2: " SIZE_T_FMT " %%", m_FileName.c_str(), (ChunksConverted * 100) / m_ChunkHeaders.size() );
+ LOGINFO("Updating \"%s\" version 1 to version 2: " SIZE_T_FMT " %%", m_FileName.c_str(), (ChunksConverted * 100) / m_ChunkHeaders.size());
}
ChunksConverted++;
@@ -586,7 +613,7 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
Offset += Header->m_CompressedSize;
// Crude data integrity check:
- int ExpectedSize = (16*128*16)*2 + (16*128*16)/2; // For version 1
+ int ExpectedSize = (16*128*16)*2 + (16*128*16)/2; // For version 1
if (UncompressedSize < ExpectedSize)
{
LOGWARNING("Chunk [%d, %d] has too short decompressed data (%d bytes out of %d needed), erasing",
@@ -603,7 +630,7 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
int errorcode = UncompressString(Data.data(), Data.size(), UncompressedData, (size_t)UncompressedSize);
if (errorcode != Z_OK)
{
- LOGERROR("Error %d decompressing data for chunk [%d, %d]",
+ LOGERROR("Error %d decompressing data for chunk [%d, %d]",
errorcode,
Header->m_ChunkX, Header->m_ChunkZ
);
@@ -627,9 +654,9 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
char ConvertedData[cChunkDef::BlockDataSize];
int Index = 0;
unsigned int InChunkOffset = 0;
- for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z )
+ for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z)
{
- for( int y = 0; y < 128; ++y )
+ for (int y = 0; y < 128; ++y)
{
ConvertedData[Index++] = UncompressedData[y + z * 128 + x * 128 * 16 + InChunkOffset];
}
@@ -638,9 +665,9 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
Index += 128;
}
InChunkOffset += (16 * 128 * 16);
- for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) // Metadata
+ for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) // Metadata
{
- for( int y = 0; y < 64; ++y )
+ for (int y = 0; y < 64; ++y)
{
ConvertedData[Index++] = UncompressedData[y + z * 64 + x * 64 * 16 + InChunkOffset];
}
@@ -648,9 +675,9 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
Index += 64;
}
InChunkOffset += (16 * 128 * 16) / 2;
- for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) // Block light
+ for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) // Block light
{
- for( int y = 0; y < 64; ++y )
+ for (int y = 0; y < 64; ++y)
{
ConvertedData[Index++] = UncompressedData[y + z * 64 + x * 64 * 16 + InChunkOffset];
}
@@ -658,9 +685,9 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
Index += 64;
}
InChunkOffset += (16*128*16)/2;
- for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) // Sky light
+ for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) // Sky light
{
- for( int y = 0; y < 64; ++y )
+ for (int y = 0; y < 64; ++y)
{
ConvertedData[Index++] = UncompressedData[y + z * 64 + x * 64 * 16 + InChunkOffset];
}
@@ -674,7 +701,7 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
// Add JSON data afterwards
if (UncompressedData.size() > InChunkOffset)
{
- Converted.append( UncompressedData.begin() + InChunkOffset, UncompressedData.end() );
+ Converted.append( UncompressedData.begin() + InChunkOffset, UncompressedData.end());
}
// Re-compress data
@@ -683,7 +710,7 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
int errorcode = CompressString(Converted.data(), Converted.size(), CompressedData, m_CompressionFactor);
if (errorcode != Z_OK)
{
- LOGERROR("Error %d compressing data for chunk [%d, %d]",
+ LOGERROR("Error %d compressing data for chunk [%d, %d]",
errorcode,
Header->m_ChunkX, Header->m_ChunkZ
);
@@ -702,7 +729,7 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
m_ChunkVersion = 2;
SynchronizeFile();
- LOGINFO("Updated \"%s\" version 1 to version 2", m_FileName.c_str() );
+ LOGINFO("Updated \"%s\" version 1 to version 2", m_FileName.c_str());
}
@@ -718,9 +745,9 @@ void cWSSCompact::cPAKFile::UpdateChunk2To3()
{
sChunkHeader * Header = *itr;
- if( ChunksConverted % 32 == 0 )
+ if (ChunksConverted % 32 == 0)
{
- LOGINFO("Updating \"%s\" version 2 to version 3: " SIZE_T_FMT " %%", m_FileName.c_str(), (ChunksConverted * 100) / m_ChunkHeaders.size() );
+ LOGINFO("Updating \"%s\" version 2 to version 3: " SIZE_T_FMT " %%", m_FileName.c_str(), (ChunksConverted * 100) / m_ChunkHeaders.size());
}
ChunksConverted++;
@@ -747,7 +774,7 @@ void cWSSCompact::cPAKFile::UpdateChunk2To3()
int errorcode = UncompressString(Data.data(), Data.size(), UncompressedData, (size_t)UncompressedSize);
if (errorcode != Z_OK)
{
- LOGERROR("Error %d decompressing data for chunk [%d, %d]",
+ LOGERROR("Error %d decompressing data for chunk [%d, %d]",
errorcode,
Header->m_ChunkX, Header->m_ChunkZ
);
@@ -771,10 +798,10 @@ void cWSSCompact::cPAKFile::UpdateChunk2To3()
// Cannot use cChunk::MakeIndex because it might change again?????????
// For compatibility, use what we know is current
- #define MAKE_3_INDEX( x, y, z ) ( x + (z * 16) + (y * 16 * 16) )
+ #define MAKE_3_INDEX( x, y, z) ( x + (z * 16) + (y * 16 * 16))
unsigned int InChunkOffset = 0;
- for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) for( int y = 0; y < 256; ++y ) // YZX Loop order is important, in 1.1 Y was first then Z then X
+ for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) for (int y = 0; y < 256; ++y) // YZX Loop order is important, in 1.1 Y was first then Z then X
{
ConvertedData[ MAKE_3_INDEX(x, y, z) ] = UncompressedData[InChunkOffset];
++InChunkOffset;
@@ -782,25 +809,25 @@ void cWSSCompact::cPAKFile::UpdateChunk2To3()
unsigned int index2 = 0;
- for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) for( int y = 0; y < 256; ++y )
+ for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) for (int y = 0; y < 256; ++y)
{
- ConvertedData[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4) ) & 0x0f ) << ((x&1)*4);
+ ConvertedData[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4)) & 0x0f) << ((x&1)*4);
++index2;
}
InChunkOffset += index2 / 2;
index2 = 0;
- for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) for( int y = 0; y < 256; ++y )
+ for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) for (int y = 0; y < 256; ++y)
{
- ConvertedData[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4) ) & 0x0f ) << ((x&1)*4);
+ ConvertedData[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4)) & 0x0f) << ((x&1)*4);
++index2;
}
InChunkOffset += index2 / 2;
index2 = 0;
- for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) for( int y = 0; y < 256; ++y )
+ for (int x = 0; x < 16; ++x) for (int z = 0; z < 16; ++z) for (int y = 0; y < 256; ++y)
{
- ConvertedData[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4) ) & 0x0f ) << ((x&1)*4);
+ ConvertedData[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4)) & 0x0f) << ((x&1)*4);
++index2;
}
InChunkOffset += index2 / 2;
@@ -810,7 +837,7 @@ void cWSSCompact::cPAKFile::UpdateChunk2To3()
// Add JSON data afterwards
if (UncompressedData.size() > InChunkOffset)
{
- Converted.append( UncompressedData.begin() + InChunkOffset, UncompressedData.end() );
+ Converted.append( UncompressedData.begin() + InChunkOffset, UncompressedData.end());
}
// Re-compress data
@@ -819,7 +846,7 @@ void cWSSCompact::cPAKFile::UpdateChunk2To3()
int errorcode = CompressString(Converted.data(), Converted.size(), CompressedData, m_CompressionFactor);
if (errorcode != Z_OK)
{
- LOGERROR("Error %d compressing data for chunk [%d, %d]",
+ LOGERROR("Error %d compressing data for chunk [%d, %d]",
errorcode,
Header->m_ChunkX, Header->m_ChunkZ
);
@@ -838,7 +865,7 @@ void cWSSCompact::cPAKFile::UpdateChunk2To3()
m_ChunkVersion = 3;
SynchronizeFile();
- LOGINFO("Updated \"%s\" version 2 to version 3", m_FileName.c_str() );
+ LOGINFO("Updated \"%s\" version 2 to version 3", m_FileName.c_str());
}
@@ -863,7 +890,7 @@ bool cWSSCompact::LoadChunkFromData(const cChunkCoords & a_Chunk, int a_Uncompre
int errorcode = UncompressString(a_Data.data(), a_Data.size(), UncompressedData, (size_t)a_UncompressedSize);
if (errorcode != Z_OK)
{
- LOGERROR("Error %d decompressing data for chunk [%d, %d]",
+ LOGERROR("Error %d decompressing data for chunk [%d, %d]",
errorcode,
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ
);
@@ -887,7 +914,7 @@ bool cWSSCompact::LoadChunkFromData(const cChunkCoords & a_Chunk, int a_Uncompre
{
Json::Value root; // will contain the root value after parsing.
Json::Reader reader;
- if ( !reader.parse( UncompressedData.data() + cChunkDef::BlockDataSize, root, false ) )
+ if (!reader.parse( UncompressedData.data() + cChunkDef::BlockDataSize, root, false))
{
LOGERROR("Failed to parse trailing JSON in chunk [%d, %d]!",
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ
@@ -905,7 +932,7 @@ bool cWSSCompact::LoadChunkFromData(const cChunkCoords & a_Chunk, int a_Uncompre
NIBBLETYPE * BlockLight = (NIBBLETYPE *)(BlockData + LightOffset);
NIBBLETYPE * SkyLight = (NIBBLETYPE *)(BlockData + SkyLightOffset);
- a_World->SetChunkData(
+ a_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
BlockData, MetaData,
IsLightValid ? BlockLight : NULL,
@@ -913,7 +940,7 @@ bool cWSSCompact::LoadChunkFromData(const cChunkCoords & a_Chunk, int a_Uncompre
NULL, NULL,
Entities, BlockEntities,
false
- );
+ )));
return true;
}
@@ -970,7 +997,7 @@ bool cWSSCompact::cPAKFile::SaveChunkToData(const cChunkCoords & a_Chunk, cWorld
// Compress the data:
AString CompressedData;
int errorcode = CompressString(Data.data(), Data.size(), CompressedData, m_CompressionFactor);
- if ( errorcode != Z_OK )
+ if (errorcode != Z_OK)
{
LOGERROR("Error %i compressing data for chunk [%d, %d, %d]", errorcode, a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ);
return false;
diff --git a/src/WorldStorage/WSSCompact.h b/src/WorldStorage/WSSCompact.h
index b148005f6..83e9cb49f 100644
--- a/src/WorldStorage/WSSCompact.h
+++ b/src/WorldStorage/WSSCompact.h
@@ -105,15 +105,15 @@ protected:
int m_NumDirty; // Number of chunks that were written into m_DataContents but not into the file
- Vector3i m_ChunkSize; // Is related to m_ChunkVersion
+ Vector3i m_ChunkSize; // Is related to m_ChunkVersion
char m_ChunkVersion;
char m_PakVersion;
bool SaveChunkToData(const cChunkCoords & a_Chunk, cWorld * a_World); // Saves the chunk to m_DataContents, updates headers and m_NumDirty
void SynchronizeFile(void); // Writes m_DataContents along with the headers to file, resets m_NumDirty
- void UpdateChunk1To2(void); // Height from 128 to 256
- void UpdateChunk2To3(void); // Axis order from YZX to XZY
+ void UpdateChunk1To2(void); // Height from 128 to 256
+ void UpdateChunk2To3(void); // Axis order from YZX to XZY
} ;
typedef std::list<cPAKFile *> cPAKFiles;
diff --git a/src/WorldStorage/WorldStorage.cpp b/src/WorldStorage/WorldStorage.cpp
index d3f35384b..707e8f929 100644
--- a/src/WorldStorage/WorldStorage.cpp
+++ b/src/WorldStorage/WorldStorage.cpp
@@ -35,7 +35,7 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// cWorldStorage:
cWorldStorage::cWorldStorage(void) :
@@ -61,7 +61,7 @@ cWorldStorage::~cWorldStorage()
-bool cWorldStorage::Start(cWorld * a_World, const AString & a_StorageSchemaName, int a_StorageCompressionFactor )
+bool cWorldStorage::Start(cWorld * a_World, const AString & a_StorageSchemaName, int a_StorageCompressionFactor)
{
m_World = a_World;
m_StorageSchemaName = a_StorageSchemaName;
@@ -96,7 +96,7 @@ void cWorldStorage::WaitForFinish(void)
// Wait for the thread to finish:
m_ShouldTerminate = true;
- m_Event.Set(); // Wake up the thread if waiting
+ m_Event.Set(); // Wake up the thread if waiting
super::Wait();
LOG("World storage thread finished");
}
@@ -163,7 +163,7 @@ void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
- m_LoadQueue.Remove(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ,true));
+ m_LoadQueue.Remove(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, true));
}
@@ -182,8 +182,8 @@ void cWorldStorage::UnqueueSave(const cChunkCoords & a_Chunk)
void cWorldStorage::InitSchemas(int a_StorageCompressionFactor)
{
// The first schema added is considered the default
- m_Schemas.push_back(new cWSSAnvil (m_World,a_StorageCompressionFactor));
- m_Schemas.push_back(new cWSSCompact (m_World,a_StorageCompressionFactor));
+ m_Schemas.push_back(new cWSSAnvil (m_World, a_StorageCompressionFactor));
+ m_Schemas.push_back(new cWSSCompact (m_World, a_StorageCompressionFactor));
m_Schemas.push_back(new cWSSForgetful(m_World));
// Add new schemas here
@@ -202,7 +202,7 @@ void cWorldStorage::InitSchemas(int a_StorageCompressionFactor)
} // for itr - m_Schemas[]
// Unknown schema selected, let the admin know:
- LOGWARNING("Unknown storage schema name \"%s\". Using default (\"%s\"). Available schemas:",
+ LOGWARNING("Unknown storage schema name \"%s\". Using default (\"%s\"). Available schemas:",
m_StorageSchemaName.c_str(), m_SaveSchema->GetName().c_str()
);
for (cWSSchemaList::iterator itr = m_Schemas.begin(); itr != m_Schemas.end(); ++itr)
diff --git a/src/WorldStorage/WorldStorage.h b/src/WorldStorage/WorldStorage.h
index 1204b4310..dd07ecb64 100644
--- a/src/WorldStorage/WorldStorage.h
+++ b/src/WorldStorage/WorldStorage.h
@@ -93,23 +93,26 @@ protected:
sChunkLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate) : m_ChunkX(a_ChunkX), m_ChunkY(a_ChunkY), m_ChunkZ(a_ChunkZ), m_Generate(a_Generate) {}
- bool operator==(const sChunkLoad other) const
+ bool operator ==(const sChunkLoad other) const
{
- return this->m_ChunkX == other.m_ChunkX &&
- this->m_ChunkY == other.m_ChunkY &&
- this->m_ChunkZ == other.m_ChunkZ;
+ return (
+ (this->m_ChunkX == other.m_ChunkX) &&
+ (this->m_ChunkY == other.m_ChunkY) &&
+ (this->m_ChunkZ == other.m_ChunkZ)
+ );
}
} ;
- struct FuncTable {
- static void Delete(sChunkLoad) {};
- static void Combine(sChunkLoad& a_orig, const sChunkLoad a_new)
+ struct FuncTable
+ {
+ static void Delete(sChunkLoad) {}
+ static void Combine(sChunkLoad & a_orig, const sChunkLoad a_new)
{
a_orig.m_Generate |= a_new.m_Generate;
- };
+ }
};
- typedef cQueue<sChunkLoad,FuncTable> sChunkLoadQueue;
+ typedef cQueue<sChunkLoad, FuncTable> sChunkLoadQueue;
cWorld * m_World;
AString m_StorageSchemaName;
diff --git a/src/XMLParser.h b/src/XMLParser.h
index f492d1a5d..e39405529 100644
--- a/src/XMLParser.h
+++ b/src/XMLParser.h
@@ -55,13 +55,13 @@ protected:
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// The following template has been modified from code available at
// http://www.codeproject.com/Articles/1847/C-Wrappers-for-the-Expat-XML-Parser
// It uses templates to remove the virtual function call penalty (both size and speed) for each callback
/* Usage:
-1, Declare a subclass:
+1, Declare a subclass:
class CMyParser : public CExpatImpl<CMyParser>
2, Declare handlers that you want in that subclass:
void CMyParser::OnEndElement(const XML_Char * iTagName);
@@ -318,7 +318,7 @@ protected:
void EnableEndDoctypeDeclHandler (bool fEnable = true)
{
assert (m_p != NULL);
- XML_SetEndDoctypeDeclHandler (m_p,
+ XML_SetEndDoctypeDeclHandler (m_p,
fEnable ? EndDoctypeDeclHandler : NULL);
}
@@ -336,7 +336,7 @@ public:
// @cmember Get last error
- enum XML_Error GetErrorCode ()
+ enum XML_Error GetErrorCode ()
{
assert (m_p != NULL);
return XML_GetErrorCode (m_p);
@@ -344,7 +344,7 @@ public:
// @cmember Get the current byte index
- long GetCurrentByteIndex ()
+ long GetCurrentByteIndex ()
{
assert (m_p != NULL);
return XML_GetCurrentByteIndex (m_p);
@@ -352,7 +352,7 @@ public:
// @cmember Get the current line number
- int GetCurrentLineNumber ()
+ int GetCurrentLineNumber ()
{
assert (m_p != NULL);
return XML_GetCurrentLineNumber (m_p);
@@ -360,7 +360,7 @@ public:
// @cmember Get the current column number
- int GetCurrentColumnNumber ()
+ int GetCurrentColumnNumber ()
{
assert (m_p != NULL);
return XML_GetCurrentColumnNumber (m_p);
@@ -368,7 +368,7 @@ public:
// @cmember Get the current byte count
- int GetCurrentByteCount ()
+ int GetCurrentByteCount ()
{
assert (m_p != NULL);
return XML_GetCurrentByteCount (m_p);
@@ -384,7 +384,7 @@ public:
// @cmember Get last error string
- const XML_LChar *GetErrorString ()
+ const XML_LChar *GetErrorString ()
{
return XML_ErrorString (GetErrorCode ());
}
@@ -411,7 +411,7 @@ public:
// @cmember Get last error string
- static const XML_LChar *GetErrorString (enum XML_Error nError)
+ static const XML_LChar *GetErrorString (enum XML_Error nError)
{
return XML_ErrorString (nError);
}
@@ -443,7 +443,7 @@ public:
// @cmember Processing instruction handler
- void OnProcessingInstruction (const XML_Char *pszTarget,
+ void OnProcessingInstruction (const XML_Char *pszTarget,
const XML_Char *pszData)
{
return;
@@ -495,7 +495,7 @@ public:
// @cmember Start namespace declaration handler
- void OnStartNamespaceDecl (const XML_Char *pszPrefix,
+ void OnStartNamespaceDecl (const XML_Char *pszPrefix,
const XML_Char *pszURI)
{
return;
@@ -518,7 +518,7 @@ public:
// @cmember Start DOCTYPE declaration handler
- void OnStartDoctypeDecl (const XML_Char *pszDoctypeName,
+ void OnStartDoctypeDecl (const XML_Char *pszDoctypeName,
const XML_Char *pszSysID, const XML_Char *pszPubID,
bool fHasInternalSubset)
{
@@ -607,7 +607,7 @@ protected:
// @cmember Default wrapper
- static void __cdecl DefaultHandler (void *pUserData,
+ static void __cdecl DefaultHandler (void *pUserData,
const XML_Char *pszData, int nLength)
{
_T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
@@ -616,12 +616,12 @@ protected:
// @cmember External entity ref wrapper
- static int __cdecl ExternalEntityRefHandler (void *pUserData,
- const XML_Char *pszContext, const XML_Char *pszBase,
+ static int __cdecl ExternalEntityRefHandler (void *pUserData,
+ const XML_Char *pszContext, const XML_Char *pszBase,
const XML_Char *pszSystemID, const XML_Char *pszPublicID)
{
_T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
- return pThis ->OnExternalEntityRef (pszContext,
+ return pThis ->OnExternalEntityRef (pszContext,
pszBase, pszSystemID, pszPublicID) ? 1 : 0;
}
@@ -660,12 +660,12 @@ protected:
// @cmember Start Doctype declaration wrapper
static void __cdecl StartDoctypeDeclHandler (
- void *pUserData, const XML_Char *pszDoctypeName, const XML_Char *pszSysID,
+ void *pUserData, const XML_Char *pszDoctypeName, const XML_Char *pszSysID,
const XML_Char *pszPubID, int nHasInternalSubset
)
{
_T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
- pThis ->OnStartDoctypeDecl (pszDoctypeName, pszSysID,
+ pThis ->OnStartDoctypeDecl (pszDoctypeName, pszSysID,
pszPubID, nHasInternalSubset != 0);
}
diff --git a/src/main.cpp b/src/main.cpp
index 6925d9ff1..86ecd4000 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -3,17 +3,17 @@
#include "Root.h"
-#include <exception> //std::exception
-#include <csignal> //std::signal
-#include <stdlib.h> //exit()
+#include <exception>
+#include <csignal>
+#include <stdlib.h>
#ifdef _MSC_VER
#include <dbghelp.h>
#endif // _MSC_VER
-// Here, we have some ALL CAPS variables, to give the impression that this is deeeep, gritty programming :P
-bool g_TERMINATE_EVENT_RAISED = false; // If something has told the server to stop; checked periodically in cRoot
-bool g_SERVER_TERMINATED = false; // Set to true when the server terminates, so our CTRL handler can then tell Windows to close the console
+
+bool cRoot::m_TerminateEventRaised = false; // If something has told the server to stop; checked periodically in cRoot
+static bool g_ServerTerminated = false; // Set to true when the server terminates, so our CTRL handler can then tell the OS to close the console
@@ -49,10 +49,10 @@ bool g_ShouldLogCommOut;
-void NonCtrlHandler(int a_Signal)
+void NonCtrlHandler(int a_Signal)
{
LOGD("Terminate event raised from std::signal");
- g_TERMINATE_EVENT_RAISED = true;
+ cRoot::m_TerminateEventRaised = true;
switch (a_Signal)
{
@@ -76,7 +76,7 @@ void NonCtrlHandler(int a_Signal)
case SIGINT:
case SIGTERM:
{
- std::signal(a_Signal, SIG_IGN); // Server is shutting down, wait for it...
+ std::signal(a_Signal, SIG_IGN); // Server is shutting down, wait for it...
break;
}
default: break;
@@ -88,7 +88,7 @@ void NonCtrlHandler(int a_Signal)
#if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// Windows 32-bit stuff: when the server crashes, create a "dump file" containing the callstack of each thread and some variables; let the user send us that crash file for analysis
typedef BOOL (WINAPI *pMiniDumpWriteDump)(
@@ -155,12 +155,12 @@ LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_Except
// Handle CTRL events in windows, including console window close
BOOL CtrlHandler(DWORD fdwCtrlType)
{
- g_TERMINATE_EVENT_RAISED = true;
+ cRoot::m_TerminateEventRaised = true;
LOGD("Terminate event raised from the Windows CtrlHandler");
- if (fdwCtrlType == CTRL_CLOSE_EVENT) // Console window closed via 'x' button, Windows will try to close immediately, therefore...
+ if (fdwCtrlType == CTRL_CLOSE_EVENT) // Console window closed via 'x' button, Windows will try to close immediately, therefore...
{
- while (!g_SERVER_TERMINATED) { cSleep::MilliSleep(100); } // Delay as much as possible to try to get the server to shut down cleanly
+ while (!g_ServerTerminated) { cSleep::MilliSleep(100); } // Delay as much as possible to try to get the server to shut down cleanly
}
return TRUE;
@@ -171,10 +171,10 @@ BOOL CtrlHandler(DWORD fdwCtrlType)
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
// main:
-int main( int argc, char **argv )
+int main( int argc, char **argv)
{
UNUSED(argc);
UNUSED(argv);
@@ -218,7 +218,7 @@ int main( int argc, char **argv )
#endif
#if defined(_DEBUG) && defined(_MSC_VER)
- _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
+ _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
// _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output)
// Only useful when the leak is in the same sequence all the time
@@ -233,7 +233,7 @@ int main( int argc, char **argv )
std::signal(SIGABRT, NonCtrlHandler);
#ifdef SIGABRT_COMPAT
std::signal(SIGABRT_COMPAT, NonCtrlHandler);
- #endif // SIGABRT_COMPAT
+ #endif // SIGABRT_COMPAT
#endif
// DEBUG: test the dumpfile creation:
@@ -273,19 +273,21 @@ int main( int argc, char **argv )
}
} // for i - argv[]
+ cLogger::InitiateMultithreading();
+
#if !defined(ANDROID_NDK)
try
#endif
{
- cRoot Root;
+ cRoot Root;
Root.Start();
}
#if !defined(ANDROID_NDK)
- catch( std::exception& e )
+ catch (std::exception & e)
{
- LOGERROR("Standard exception: %s", e.what() );
+ LOGERROR("Standard exception: %s", e.what());
}
- catch( ... )
+ catch (...)
{
LOGERROR("Unknown exception!");
}
@@ -296,7 +298,7 @@ int main( int argc, char **argv )
DeinitLeakFinder();
#endif
- g_SERVER_TERMINATED = true;
+ g_ServerTerminated = true;
return EXIT_SUCCESS;
}