Repository: skyblueyoshi/TerraCraft Branch: master Commit: dabeb2789995 Files: 3382 Total size: 2.7 MB Directory structure: gitextract_ll5d4bnt/ ├── DebugHelper.lua ├── DebugHelperConfig.lua ├── LICENSE ├── README.md ├── advancements/ │ ├── AdvancementTriggers.lua │ ├── ancient_ingot.json │ ├── ancient_wear.json │ ├── blaze_rod.json │ ├── bow.json │ ├── bread.json │ ├── brew.json │ ├── bronze.json │ ├── cake.json │ ├── crafting_table.json │ ├── crison_eye.json │ ├── crison_eye_killed.json │ ├── crossbow.json │ ├── diamond.json │ ├── diamond_ingot.json │ ├── diamond_wear.json │ ├── dungeon_eater.json │ ├── dungeon_eater_killed.json │ ├── enchant.json │ ├── ender_chest.json │ ├── ender_pearl.json │ ├── farm.json │ ├── flesh_ingot.json │ ├── flesh_wear.json │ ├── furnace.json │ ├── ghast.json │ ├── ghost.json │ ├── ghost_crystal.json │ ├── go_bone_dungeon.json │ ├── go_dark_dungeon.json │ ├── go_deep_snow.json │ ├── go_desert_dungeon.json │ ├── go_ghost_house.json │ ├── go_ice_dungeon.json │ ├── go_lava_dungeon.json │ ├── gold.json │ ├── gold_wear.json │ ├── guardian.json │ ├── gun.json │ ├── hunter.json │ ├── ice_element_ball.json │ ├── inventory.json │ ├── iron.json │ ├── knight_ingot.json │ ├── knight_wear.json │ ├── lava.json │ ├── leather.json │ ├── magic_gold_wear.json │ ├── magic_limit.json │ ├── mine.json │ ├── mine_bronze.json │ ├── mine_copper.json │ ├── mine_diamond.json │ ├── mine_gold.json │ ├── mine_iron.json │ ├── mine_netherite.json │ ├── mine_up.json │ ├── mirror.json │ ├── nether.json │ ├── nether_destroyer.json │ ├── nether_destroyer_killed.json │ ├── netherite.json │ ├── netherite_full_wear.json │ ├── portal.json │ ├── pumpkin_helmet.json │ ├── recipe_book.json │ ├── redstone.json │ ├── redstone_wire.json │ ├── repair.json │ ├── rocket_boost.json │ ├── snow_guard.json │ ├── snow_queen.json │ ├── snow_queen_killed.json │ ├── staff.json │ ├── star_wear.json │ ├── steel.json │ ├── stone.json │ ├── strange_len.json │ ├── super_diamond_sword.json │ ├── super_diamond_wear.json │ ├── sword.json │ └── wood.json ├── api.lua ├── apis/ │ ├── Account.lua │ ├── AccountUtils.lua │ ├── Advancement.lua │ ├── AdvancementUtils.lua │ ├── Attack.lua │ ├── BiomeData.lua │ ├── BiomeUtils.lua │ ├── BlockData.lua │ ├── BlockEntity.lua │ ├── BlockUtils.lua │ ├── Buff.lua │ ├── ClientBoundPacketWriter.lua │ ├── ClientState.lua │ ├── ClientStateManager.lua │ ├── Container.lua │ ├── DataWatcher.lua │ ├── DeathReason.lua │ ├── Defense.lua │ ├── Direction.lua │ ├── Effect.lua │ ├── EffectUtils.lua │ ├── Enchantment.lua │ ├── EnchantmentData.lua │ ├── EnchantmentUtils.lua │ ├── Entity.lua │ ├── EntityIndex.lua │ ├── GameMode.lua │ ├── GlobalBlock.lua │ ├── GlobalNpc.lua │ ├── GlobalPlayer.lua │ ├── GuiContainer.lua │ ├── Hitbox.lua │ ├── Inventory.lua │ ├── Item.lua │ ├── ItemRegistry.lua │ ├── ItemStack.lua │ ├── ItemType.lua │ ├── ItemUtils.lua │ ├── JoinData.lua │ ├── LangUtils.lua │ ├── LightingUtils.lua │ ├── MapPos.lua │ ├── MapUtils.lua │ ├── MiscUtils.lua │ ├── Mod.lua │ ├── ModBlock.lua │ ├── ModBlockEntity.lua │ ├── ModItem.lua │ ├── ModNpc.lua │ ├── ModProjectile.lua │ ├── ModTextureData.lua │ ├── ModTextureUtils.lua │ ├── Npc.lua │ ├── NpcType.lua │ ├── NpcUtils.lua │ ├── OreDataGroup.lua │ ├── ParameterClick.lua │ ├── ParameterDestroy.lua │ ├── ParameterPlace.lua │ ├── ParameterStrike.lua │ ├── Player.lua │ ├── PlayerUtils.lua │ ├── Point.lua │ ├── Projectile.lua │ ├── ProjectileUtils.lua │ ├── Recipe.lua │ ├── RecipeConfig.lua │ ├── RecipeSearchAction.lua │ ├── RecipeUtils.lua │ ├── Rectangle.lua │ ├── Reg.lua │ ├── ServerBoundPacketWriter.lua │ ├── Shape.lua │ ├── Skeleton.lua │ ├── Skin.lua │ ├── SkinUtils.lua │ ├── Slot.lua │ ├── SlotCommandQueue.lua │ ├── SmartMode.lua │ ├── SoundUtils.lua │ ├── SpriteEx.lua │ ├── Type.lua │ ├── Utils.lua │ ├── WorldData.lua │ ├── WorldDataUtils.lua │ ├── WorldGenArea.lua │ ├── WorldGenChunkBuffer.lua │ ├── WorldGenCode.lua │ ├── WorldGenNoise.lua │ └── engine_api/ │ ├── AnimationEvent.lua │ ├── Animator2D.lua │ ├── AnimatorData2D.lua │ ├── App.lua │ ├── Array.lua │ ├── AssetBundle.lua │ ├── AssetManager.lua │ ├── AtlasInfos.lua │ ├── AtlasLoader.lua │ ├── Audio.lua │ ├── ByteStream.lua │ ├── Bytes.lua │ ├── CameraComponentWrapper.lua │ ├── CameraProjection.lua │ ├── CanvasComponentWrapper.lua │ ├── CanvasDisplayMode.lua │ ├── ClipCollection2D.lua │ ├── Color.lua │ ├── ComponentID.lua │ ├── ComponentWrapper.lua │ ├── DateTime.lua │ ├── FadingState.lua │ ├── File.lua │ ├── FileTimeType.lua │ ├── FontManager.lua │ ├── FontSprite.lua │ ├── GameObject.lua │ ├── GameWindow.lua │ ├── GlobalHook.lua │ ├── GraphicsDevice.lua │ ├── HotKeyCombination.lua │ ├── Hotfix.lua │ ├── Image.lua │ ├── ImageInfo.lua │ ├── Input.lua │ ├── IntegratedClient.lua │ ├── IntegratedEnv.lua │ ├── Joint2D.lua │ ├── JointBody2D.lua │ ├── JointCollection2D.lua │ ├── Joystick.lua │ ├── JoystickDevice.lua │ ├── JsonUtil.lua │ ├── KeyTrigger.lua │ ├── Keyboard.lua │ ├── Keys.lua │ ├── ListenerID.lua │ ├── Log.lua │ ├── MathHelper.lua │ ├── Matrix.lua │ ├── MeshFilterComponentWrapper.lua │ ├── MeshRendererComponentWrapper.lua │ ├── Mouse.lua │ ├── NetMode.lua │ ├── ObbDouble.lua │ ├── Path.lua │ ├── Quaternion.lua │ ├── Random.lua │ ├── Rect.lua │ ├── RectFloat.lua │ ├── RectFloatEx.lua │ ├── Registry.lua │ ├── Rigidbody.lua │ ├── Schedule.lua │ ├── ScheduleID.lua │ ├── SerializableType.lua │ ├── Size.lua │ ├── SliderDirection.lua │ ├── Sprite.lua │ ├── SpriteExData.lua │ ├── TextAlignment.lua │ ├── TextBuffer.lua │ ├── TextEditLineType.lua │ ├── TextHorizontalOverflow.lua │ ├── TextStyle.lua │ ├── TextVerticalOverflow.lua │ ├── Texture.lua │ ├── TextureLocation.lua │ ├── TextureManager.lua │ ├── TexturePacker.lua │ ├── Time.lua │ ├── TimeDiff.lua │ ├── Touch.lua │ ├── Transform.lua │ ├── Transform2D.lua │ ├── TransformComponentWrapper.lua │ ├── UIButton.lua │ ├── UICanvas.lua │ ├── UIImage.lua │ ├── UIInputField.lua │ ├── UIJoystick.lua │ ├── UINode.lua │ ├── UINodeDrawLayer.lua │ ├── UIPanel.lua │ ├── UIScrollView.lua │ ├── UISerializable.lua │ ├── UISlices9.lua │ ├── UISlider.lua │ ├── UISprite.lua │ ├── UISpriteStyle.lua │ ├── UISwitch.lua │ ├── UIText.lua │ ├── UITexturePool.lua │ ├── Vector2.lua │ ├── Vector3.lua │ ├── Vector4.lua │ ├── cls.lua │ └── utf8string.lua ├── atlas_config.json ├── biome_types/ │ ├── Nether.json │ ├── Radiation.json │ ├── Space.json │ ├── Surface.json │ ├── TwilightForest.json │ └── Underground.json ├── biomes/ │ ├── nethers/ │ │ └── nether.json │ ├── surfaces/ │ │ ├── badland.json │ │ ├── desert.json │ │ ├── flesh.json │ │ ├── forest.json │ │ ├── jungle.json │ │ ├── mushroom_fields.json │ │ ├── ocean.json │ │ ├── snow_land.json │ │ ├── soft_snow_land.json │ │ ├── super_volcano.json │ │ ├── tainted_land.json │ │ └── volcano.json │ └── undergrounds/ │ ├── andesite_cave.json │ ├── blue_cave.json │ ├── blue_mushroom_cave.json │ ├── deep_ice_cave.json │ ├── deep_magma_cave.json │ ├── desert_cave.json │ ├── diorite_cave.json │ ├── flesh_cave.json │ ├── granite_cave.json │ ├── ice_cave.json │ ├── jungle_cave.json │ ├── lava_cave.json │ ├── magma_cave.json │ ├── mud_cave.json │ ├── mushroom_cave.json │ ├── normal_cave.json │ ├── stone_cave.json │ ├── tainted_cave.json │ └── waste_cave.json ├── block_entity_ai/ │ ├── BrewingEntity.json │ ├── BrewingEntity.lua │ ├── Chest30Entity.json │ ├── Chest30Entity.lua │ ├── IChestEntity.lua │ ├── IShooterEntity.lua │ ├── Shooter9Entity.json │ ├── Shooter9Entity.lua │ ├── SmeltEntity.json │ └── SmeltEntity.lua ├── block_presets/ │ ├── Anvil.json │ ├── Anvil.lua │ ├── Bed.json │ ├── Brewing.json │ ├── BurnerTower.json │ ├── Button.json │ ├── Cake.json │ ├── Cobweb.json │ ├── Cobweb.lua │ ├── CraftingTable.json │ ├── CraftingTable.lua │ ├── Crop.json │ ├── CrystalTower.json │ ├── DaylightTrigger.json │ ├── DoorClosed.json │ ├── DoorOpened.json │ ├── Enchantment.json │ ├── EnchantmentTable.lua │ ├── EndRod.json │ ├── EnderStorage.json │ ├── EnderStorage.lua │ ├── Facing.json │ ├── Farmland.json │ ├── Furnace.json │ ├── Furnace.lua │ ├── Grass.json │ ├── GrowGrass.json │ ├── HeartCrystal.json │ ├── HeartCrystal.lua │ ├── IceSmelt.json │ ├── InsideStorage.json │ ├── Kelp.json │ ├── MagmaBlock.json │ ├── MagmaBlock.lua │ ├── Melon.json │ ├── MelonStem.json │ ├── MoonlightTrigger.json │ ├── NetherAltar.json │ ├── NetherAltar.lua │ ├── Painting.json │ ├── PortalDoor.json │ ├── Pot.json │ ├── Pumpkin.json │ ├── RandomDisplay.json │ ├── RedstoneLamp.json │ ├── RedstonePlate.json │ ├── RedstonePlate.lua │ ├── RedstoneTorch.json │ ├── Sapling.json │ ├── Shooter.json │ ├── SnowQueenBall.json │ ├── SnowQueenBall.lua │ ├── SoulSand.json │ ├── SoulSand.lua │ ├── Sponge.json │ ├── Stalactite.json │ ├── Storage.json │ ├── Sugarcane.json │ ├── TNT.json │ ├── Torch.json │ ├── TrapStorage.json │ ├── Vine.json │ └── WetSponge.json ├── blocks/ │ ├── furnitures/ │ │ ├── beds/ │ │ │ ├── wooden_bed_black.json │ │ │ ├── wooden_bed_blue.json │ │ │ ├── wooden_bed_brown.json │ │ │ ├── wooden_bed_cyan.json │ │ │ ├── wooden_bed_gray.json │ │ │ ├── wooden_bed_green.json │ │ │ ├── wooden_bed_light_blue.json │ │ │ ├── wooden_bed_light_gray.json │ │ │ ├── wooden_bed_lime.json │ │ │ ├── wooden_bed_magenta.json │ │ │ ├── wooden_bed_orange.json │ │ │ ├── wooden_bed_pink.json │ │ │ ├── wooden_bed_purple.json │ │ │ ├── wooden_bed_red.json │ │ │ ├── wooden_bed_white.json │ │ │ └── wooden_bed_yellow.json │ │ ├── benches/ │ │ │ ├── bench_acacia.json │ │ │ ├── bench_birch.json │ │ │ ├── bench_dark_oak.json │ │ │ ├── bench_jungle.json │ │ │ ├── bench_nether.json │ │ │ ├── bench_oak.json │ │ │ ├── bench_palm.json │ │ │ ├── bench_spruce.json │ │ │ ├── bench_tainted.json │ │ │ └── bench_volcano.json │ │ ├── bookcases/ │ │ │ ├── bookcase_acacia.json │ │ │ ├── bookcase_birch.json │ │ │ ├── bookcase_dark_oak.json │ │ │ ├── bookcase_jungle.json │ │ │ ├── bookcase_nether.json │ │ │ ├── bookcase_oak.json │ │ │ ├── bookcase_palm.json │ │ │ ├── bookcase_spruce.json │ │ │ ├── bookcase_tainted.json │ │ │ └── bookcase_volcano.json │ │ ├── bosses/ │ │ │ ├── nether_altar.json │ │ │ └── snow_glass_ball.json │ │ ├── cabinet/ │ │ │ ├── cabinet_acacia.json │ │ │ ├── cabinet_birch.json │ │ │ ├── cabinet_dark_oak.json │ │ │ ├── cabinet_jungle.json │ │ │ ├── cabinet_nether.json │ │ │ ├── cabinet_oak.json │ │ │ ├── cabinet_palm.json │ │ │ ├── cabinet_spruce.json │ │ │ ├── cabinet_tainted.json │ │ │ └── cabinet_volcano.json │ │ ├── chairs/ │ │ │ ├── chair_acacia.json │ │ │ ├── chair_birch.json │ │ │ ├── chair_dark_oak.json │ │ │ ├── chair_jungle.json │ │ │ ├── chair_nether.json │ │ │ ├── chair_oak.json │ │ │ ├── chair_palm.json │ │ │ ├── chair_spruce.json │ │ │ ├── chair_tainted.json │ │ │ └── chair_volcano.json │ │ ├── chests/ │ │ │ ├── barrel.json │ │ │ ├── chest.json │ │ │ ├── ender_chest.json │ │ │ ├── nether_chest.json │ │ │ ├── shulker_box.json │ │ │ ├── stone_chest.json │ │ │ └── trapped_chest.json │ │ ├── doors/ │ │ │ ├── door_nether.json │ │ │ ├── door_nether_open.json │ │ │ ├── iron_door.json │ │ │ ├── iron_door_open.json │ │ │ ├── wooden_door_acacia.json │ │ │ ├── wooden_door_acacia_open.json │ │ │ ├── wooden_door_birch.json │ │ │ ├── wooden_door_birch_open.json │ │ │ ├── wooden_door_dark_oak.json │ │ │ ├── wooden_door_dark_oak_open.json │ │ │ ├── wooden_door_jungle.json │ │ │ ├── wooden_door_jungle_open.json │ │ │ ├── wooden_door_oak.json │ │ │ ├── wooden_door_oak_open.json │ │ │ ├── wooden_door_palm.json │ │ │ ├── wooden_door_palm_open.json │ │ │ ├── wooden_door_spruce.json │ │ │ ├── wooden_door_spruce_open.json │ │ │ ├── wooden_door_tainted.json │ │ │ ├── wooden_door_tainted_open.json │ │ │ ├── wooden_door_volcano.json │ │ │ └── wooden_door_volcano_open.json │ │ ├── farms/ │ │ │ ├── carrot.json │ │ │ ├── melon_stem.json │ │ │ ├── nether_wart.json │ │ │ ├── potato.json │ │ │ ├── pumpkin.json │ │ │ ├── pumpkin_carved.json │ │ │ ├── pumpkin_stem.json │ │ │ ├── sugar_cane.json │ │ │ ├── watermelon.json │ │ │ └── wheat.json │ │ ├── flowers/ │ │ │ ├── allium.json │ │ │ ├── azure_bluet.json │ │ │ ├── blue_orchid.json │ │ │ ├── dandelion.json │ │ │ ├── fern.json │ │ │ ├── lilac.json │ │ │ ├── orange_tulip.json │ │ │ ├── peony.json │ │ │ ├── pink_tulip.json │ │ │ ├── poppy.json │ │ │ ├── red_tulip.json │ │ │ ├── rose_bush.json │ │ │ ├── sunflower.json │ │ │ └── white_tulip.json │ │ ├── grasses/ │ │ │ ├── blood_grass.json │ │ │ ├── eyeball_grass.json │ │ │ ├── grass.json │ │ │ ├── large_eyeball_grass.json │ │ │ └── tainted_grass.json │ │ ├── lightings/ │ │ │ ├── candle.json │ │ │ ├── candle_holder.json │ │ │ ├── chandeliers.json │ │ │ ├── fire_lamp.json │ │ │ ├── jack_o_lantern.json │ │ │ ├── lantern.json │ │ │ └── nether_lamp.json │ │ ├── misc/ │ │ │ ├── anvil.json │ │ │ ├── book.json │ │ │ ├── brewing_stand.json │ │ │ ├── cake.json │ │ │ ├── campfire.json │ │ │ ├── cauldron.json │ │ │ ├── cobweb.json │ │ │ ├── crafting_table.json │ │ │ ├── enchantment_table.json │ │ │ ├── flower_pot.json │ │ │ ├── flower_pot_large.json │ │ │ ├── furnace.json │ │ │ ├── health_crystal.json │ │ │ ├── jukebox.json │ │ │ ├── pot.json │ │ │ ├── potion.json │ │ │ ├── sign.json │ │ │ ├── skull.json │ │ │ └── thorn.json │ │ ├── mushrooms/ │ │ │ ├── brown_mushroom.json │ │ │ ├── glowing_mushroom.json │ │ │ ├── large_brown_mushroom.json │ │ │ ├── large_poison_mushroom.json │ │ │ ├── large_red_mushroom.json │ │ │ ├── poison_mushroom.json │ │ │ └── red_mushroom.json │ │ ├── paintings/ │ │ │ ├── painting.json │ │ │ ├── painting_2x2.json │ │ │ ├── painting_2x4.json │ │ │ ├── painting_4x2.json │ │ │ ├── painting_4x4.json │ │ │ ├── painting_8x4.json │ │ │ ├── painting_8x6.json │ │ │ └── painting_8x8.json │ │ ├── plants/ │ │ │ └── bush.json │ │ ├── redstones/ │ │ │ ├── daylight_sensor.json │ │ │ ├── daylight_sensor_inverted.json │ │ │ ├── dispenser.json │ │ │ ├── lever.json │ │ │ ├── pressure_plates/ │ │ │ │ ├── pressure_plate_golden.json │ │ │ │ ├── pressure_plate_iron.json │ │ │ │ ├── pressure_plate_stone.json │ │ │ │ └── pressure_plate_wooden.json │ │ │ ├── redstone_lamp.json │ │ │ ├── stone_button.json │ │ │ └── wooden_button.json │ │ ├── rocks/ │ │ │ ├── rock.json │ │ │ └── rock_waste.json │ │ ├── saplings/ │ │ │ ├── sapling_acacia.json │ │ │ ├── sapling_bare_oak.json │ │ │ ├── sapling_birch.json │ │ │ ├── sapling_cactus.json │ │ │ ├── sapling_dark_oak.json │ │ │ ├── sapling_jungle.json │ │ │ ├── sapling_oak.json │ │ │ ├── sapling_palm.json │ │ │ ├── sapling_spruce.json │ │ │ ├── sapling_tainted.json │ │ │ └── sapling_volcano.json │ │ ├── seas/ │ │ │ ├── coral.json │ │ │ ├── kelp.json │ │ │ ├── sea_grass.json │ │ │ └── sea_shell.json │ │ ├── small_trees/ │ │ │ ├── small_tree_desert.json │ │ │ ├── small_tree_normal.json │ │ │ ├── small_tree_snowy.json │ │ │ ├── small_tree_tainted.json │ │ │ └── small_tree_waste.json │ │ ├── stabs/ │ │ │ ├── stab_hanging_tainted.json │ │ │ └── stab_tainted.json │ │ ├── stalactites/ │ │ │ ├── stalactite_andesite.json │ │ │ ├── stalactite_desert.json │ │ │ ├── stalactite_diorite.json │ │ │ ├── stalactite_granite.json │ │ │ ├── stalactite_hanging_andesite.json │ │ │ ├── stalactite_hanging_desert.json │ │ │ ├── stalactite_hanging_diorite.json │ │ │ ├── stalactite_hanging_granite.json │ │ │ ├── stalactite_hanging_ice.json │ │ │ ├── stalactite_hanging_small_andesite.json │ │ │ ├── stalactite_hanging_small_desert.json │ │ │ ├── stalactite_hanging_small_diorite.json │ │ │ ├── stalactite_hanging_small_granite.json │ │ │ ├── stalactite_hanging_small_ice.json │ │ │ ├── stalactite_hanging_small_stone.json │ │ │ ├── stalactite_hanging_small_tainted.json │ │ │ ├── stalactite_hanging_small_waste.json │ │ │ ├── stalactite_hanging_stone.json │ │ │ ├── stalactite_hanging_tainted.json │ │ │ ├── stalactite_hanging_waste.json │ │ │ ├── stalactite_ice.json │ │ │ ├── stalactite_small_andesite.json │ │ │ ├── stalactite_small_desert.json │ │ │ ├── stalactite_small_diorite.json │ │ │ ├── stalactite_small_granite.json │ │ │ ├── stalactite_small_ice.json │ │ │ ├── stalactite_small_stone.json │ │ │ ├── stalactite_small_tainted.json │ │ │ ├── stalactite_small_waste.json │ │ │ ├── stalactite_stone.json │ │ │ ├── stalactite_tainted.json │ │ │ └── stalactite_waste.json │ │ ├── stone_decoses/ │ │ │ ├── stone_decos_ice.json │ │ │ ├── stone_decos_mossy.json │ │ │ ├── stone_decos_normal.json │ │ │ ├── stone_decos_tainted.json │ │ │ └── stone_decos_waste.json │ │ ├── stone_pillars/ │ │ │ ├── stone_pillar_desert.json │ │ │ ├── stone_pillar_ice.json │ │ │ ├── stone_pillar_normal.json │ │ │ └── stone_pillar_tainted.json │ │ ├── tables/ │ │ │ ├── table_acacia.json │ │ │ ├── table_birch.json │ │ │ ├── table_dark_oak.json │ │ │ ├── table_jungle.json │ │ │ ├── table_nether.json │ │ │ ├── table_oak.json │ │ │ ├── table_palm.json │ │ │ ├── table_spruce.json │ │ │ ├── table_tainted.json │ │ │ └── table_volcano.json │ │ ├── tentacles/ │ │ │ ├── flesh_tentacle.json │ │ │ └── flesh_tentacle_hanging.json │ │ ├── torches/ │ │ │ ├── blue_torch.json │ │ │ ├── end_rod.json │ │ │ ├── green_torch.json │ │ │ ├── red_torch.json │ │ │ ├── redstone_torch.json │ │ │ ├── torch.json │ │ │ ├── white_torch.json │ │ │ └── yellow_torch.json │ │ └── vines/ │ │ ├── eyeball_vine.json │ │ ├── tainted_vine.json │ │ └── vine.json │ └── tiles/ │ ├── andesites/ │ │ ├── andesite.json │ │ └── andesite_polished.json │ ├── auroras/ │ │ ├── aurora_block.json │ │ └── aurora_pillar.json │ ├── diorites/ │ │ ├── diorite.json │ │ └── diorite_polished.json │ ├── ends/ │ │ ├── end_stone.json │ │ └── end_stone_brick.json │ ├── fences/ │ │ ├── cobblestone_fence.json │ │ ├── fence_acacia.json │ │ ├── fence_birch.json │ │ ├── fence_dark_oak.json │ │ ├── fence_jungle.json │ │ ├── fence_nether.json │ │ ├── fence_oak.json │ │ ├── fence_palm.json │ │ ├── fence_spruce.json │ │ ├── fence_tainted.json │ │ ├── fence_volcano.json │ │ ├── iron_bar.json │ │ └── mossy_cobblestone_fence.json │ ├── fleshes/ │ │ ├── flesh_dirt.json │ │ ├── flesh_gut.json │ │ └── flesh_stone.json │ ├── glasses/ │ │ ├── glass.json │ │ ├── stained_glass_black.json │ │ ├── stained_glass_blue.json │ │ ├── stained_glass_brown.json │ │ ├── stained_glass_cyan.json │ │ ├── stained_glass_gray.json │ │ ├── stained_glass_green.json │ │ ├── stained_glass_light_blue.json │ │ ├── stained_glass_light_gray.json │ │ ├── stained_glass_lime.json │ │ ├── stained_glass_magenta.json │ │ ├── stained_glass_orange.json │ │ ├── stained_glass_pink.json │ │ ├── stained_glass_purple.json │ │ ├── stained_glass_red.json │ │ ├── stained_glass_white.json │ │ └── stained_glass_yellow.json │ ├── granites/ │ │ ├── granite.json │ │ └── granite_polished.json │ ├── ices/ │ │ ├── blue_ice.json │ │ ├── ice.json │ │ ├── ice_brick.json │ │ ├── ice_cobblestone.json │ │ ├── ice_packed.json │ │ └── ice_thin.json │ ├── misc/ │ │ ├── bedrock.json │ │ ├── bone_block.json │ │ ├── brick.json │ │ ├── clay.json │ │ ├── coarse_dirt.json │ │ ├── dirt.json │ │ ├── dirt.mdp │ │ ├── dirt2.mdp │ │ ├── dried_kelp_block.json │ │ ├── farmland.json │ │ ├── gravel.json │ │ ├── hay_bale.json │ │ ├── obsidian.json │ │ ├── slime_block.json │ │ └── tnt.json │ ├── mushrooms/ │ │ ├── brown_mushroom_block.json │ │ ├── mushroom_stem.json │ │ ├── mycelium.json │ │ └── red_mushroom_block.json │ ├── nethers/ │ │ ├── glowstone.json │ │ ├── nether_brick.json │ │ ├── netherrack.json │ │ ├── red_nether_brick.json │ │ └── soul_sand.json │ ├── ore_blocks/ │ │ ├── block_coal.json │ │ ├── block_diamond.json │ │ ├── block_emerald.json │ │ ├── block_gold.json │ │ ├── block_iron.json │ │ ├── block_lapis.json │ │ ├── block_netherite.json │ │ ├── block_quartz.json │ │ └── block_redstone.json │ ├── ores/ │ │ ├── ore_ancient_debris.json │ │ ├── ore_coal.json │ │ ├── ore_copper.json │ │ ├── ore_diamond.json │ │ ├── ore_emerald.json │ │ ├── ore_gold.json │ │ ├── ore_iron.json │ │ ├── ore_lapis.json │ │ ├── ore_lead.json │ │ ├── ore_nether_quartz.json │ │ ├── ore_redstone.json │ │ ├── ore_silver.json │ │ └── ore_tin.json │ ├── planks/ │ │ ├── plank_acacia.json │ │ ├── plank_birch.json │ │ ├── plank_dark_oak.json │ │ ├── plank_jungle.json │ │ ├── plank_oak.json │ │ ├── plank_palm.json │ │ ├── plank_spruce.json │ │ ├── plank_tainted.json │ │ └── plank_volcano.json │ ├── platforms/ │ │ ├── platform_acacia.json │ │ ├── platform_birch.json │ │ ├── platform_dark_oak.json │ │ ├── platform_end_stone.json │ │ ├── platform_jungle.json │ │ ├── platform_nether_brick.json │ │ ├── platform_oak.json │ │ ├── platform_palm.json │ │ ├── platform_prismarine.json │ │ ├── platform_prismarine_dark.json │ │ ├── platform_purpur.json │ │ ├── platform_quartz.json │ │ ├── platform_red_sand_stone.json │ │ ├── platform_sandstone.json │ │ ├── platform_spruce.json │ │ ├── platform_stone_brick.json │ │ ├── platform_tainted.json │ │ └── platform_volcano.json │ ├── prismarines/ │ │ ├── prismarine.json │ │ ├── prismarine_brick.json │ │ ├── prismarine_dark.json │ │ ├── prismarine_mud.json │ │ └── sea_lantern.json │ ├── purpurs/ │ │ └── purpur_block.json │ ├── red_sands/ │ │ ├── red_sand.json │ │ ├── red_sand_carved.json │ │ ├── red_sand_smooth.json │ │ └── red_sand_stone.json │ ├── sands/ │ │ ├── sand.json │ │ ├── sandstone.json │ │ ├── sandstone_carved.json │ │ └── sandstone_smooth.json │ ├── snows/ │ │ ├── snow.json │ │ └── snow_brick.json │ ├── sponges/ │ │ ├── sponge.json │ │ └── wet_sponge.json │ ├── stones/ │ │ ├── cobblestone.json │ │ ├── cobblestone_mossy.json │ │ ├── stone.json │ │ ├── stone_brick.json │ │ ├── stone_brick_carved.json │ │ ├── stone_brick_cracked.json │ │ └── stone_brick_mossy.json │ ├── tainted/ │ │ ├── tainted_dirt.json │ │ └── tainted_stone.json │ ├── terracottas/ │ │ ├── terracotta_black.json │ │ ├── terracotta_blue.json │ │ ├── terracotta_brown.json │ │ ├── terracotta_cyan.json │ │ ├── terracotta_gray.json │ │ ├── terracotta_green.json │ │ ├── terracotta_light_blue.json │ │ ├── terracotta_light_gray.json │ │ ├── terracotta_lime.json │ │ ├── terracotta_magenta.json │ │ ├── terracotta_orange.json │ │ ├── terracotta_pink.json │ │ ├── terracotta_purple.json │ │ ├── terracotta_red.json │ │ ├── terracotta_white.json │ │ └── terracotta_yellow.json │ ├── test/ │ │ ├── blue_mushroom.json │ │ ├── blue_mushroom_dirt.json │ │ ├── blue_mushroom_stem.json │ │ ├── ice_cobblestone_hard.json │ │ ├── large_blue_mushroom.json │ │ ├── lava_block_pile.json │ │ ├── pile_cobblestone.json │ │ ├── snow_soft.json │ │ ├── volcano_burn_stone.json │ │ └── volcano_cobblestone.json │ ├── volcanos/ │ │ ├── magma_block.json │ │ ├── volcano_dirt.json │ │ └── volcano_stone.json │ ├── woods/ │ │ ├── wood_acacia.json │ │ ├── wood_birch.json │ │ ├── wood_dark_oak.json │ │ ├── wood_jungle.json │ │ ├── wood_oak.json │ │ ├── wood_palm.json │ │ ├── wood_spruce.json │ │ ├── wood_stripped_acacia.json │ │ ├── wood_stripped_birch.json │ │ ├── wood_stripped_dark_oak.json │ │ ├── wood_stripped_jungle.json │ │ ├── wood_stripped_oak.json │ │ ├── wood_stripped_palm.json │ │ ├── wood_stripped_spruce.json │ │ ├── wood_stripped_tainted.json │ │ ├── wood_stripped_volcano.json │ │ ├── wood_tainted.json │ │ └── wood_volcano.json │ └── wools/ │ ├── wool_black.json │ ├── wool_blue.json │ ├── wool_brown.json │ ├── wool_cyan.json │ ├── wool_gray.json │ ├── wool_green.json │ ├── wool_light_blue.json │ ├── wool_light_gray.json │ ├── wool_lime.json │ ├── wool_magenta.json │ ├── wool_orange.json │ ├── wool_pink.json │ ├── wool_purple.json │ ├── wool_red.json │ ├── wool_white.json │ └── wool_yellow.json ├── bone2d/ │ ├── ItemJointHelper.lua │ ├── NpcHumanAnimator.lua │ ├── NpcHumanBoneInfo.lua │ ├── NpcHumanClips.lua │ ├── NpcHumanJoints.lua │ ├── NpcHumanJointsTall.lua │ ├── PlayerAnimator.lua │ ├── PlayerBoneInfo.lua │ ├── PlayerClips.lua │ └── PlayerJoints.lua ├── buffs/ │ ├── BaseBuffProxy.lua │ ├── BuffBlindness.lua │ ├── BuffFire.lua │ ├── BuffGlowing.lua │ ├── BuffHappiness.lua │ ├── BuffHealthBoost.lua │ ├── BuffHunger.lua │ ├── BuffHurt.lua │ ├── BuffInvisibility.lua │ ├── BuffJumpBoost.lua │ ├── BuffLevitation.lua │ ├── BuffMiningFatigue.lua │ ├── BuffPoison.lua │ ├── BuffProxies.lua │ ├── BuffRegeneration.lua │ ├── BuffResistance.lua │ ├── BuffSadness.lua │ ├── BuffSlowFalling.lua │ ├── BuffSlowMining.lua │ ├── BuffSlowness.lua │ ├── BuffSpeed.lua │ ├── BuffStrength.lua │ ├── BuffVision.lua │ ├── BuffWeak.lua │ ├── BuffWither.lua │ ├── absorption.json │ ├── blindness.json │ ├── fire.json │ ├── fire_defense.json │ ├── glowing.json │ ├── happiness.json │ ├── health_boost.json │ ├── health_cold.json │ ├── hunger.json │ ├── hurt.json │ ├── invisibility.json │ ├── jump_boost.json │ ├── levitation.json │ ├── luck.json │ ├── mining_fatique.json │ ├── nausea.json │ ├── poison.json │ ├── regeneration.json │ ├── resistance.json │ ├── sadness.json │ ├── slow_falling.json │ ├── slow_mining.json │ ├── slowness.json │ ├── speed.json │ ├── strength.json │ ├── vision.json │ ├── water_breathing.json │ ├── weak.json │ └── wither.json ├── buildings/ │ ├── aurora_palace/ │ │ └── aurora_palace.json │ ├── by_house/ │ │ └── by_house.json │ ├── desert_house/ │ │ └── desert_house.json │ ├── end_outpost/ │ │ └── end_outpost.json │ ├── forest_house/ │ │ └── forest_house.json │ ├── fossils/ │ │ └── fossils.json │ ├── heart/ │ │ └── heart.json │ ├── jungle_temple/ │ │ └── jungle_temple.json │ ├── mineshaft/ │ │ └── mineshaft.json │ ├── mini_house/ │ │ └── mini_house.json │ ├── monument_ocean/ │ │ └── monument_ocean.json │ ├── nether_fortress/ │ │ └── nether_fortress.json │ ├── pyramid/ │ │ └── pyramid.json │ ├── under_dark_oak_cabin/ │ │ └── under_dark_oak_cabin.json │ ├── under_desert_cabin/ │ │ └── under_desert_cabin.json │ ├── under_jungle_cabin/ │ │ └── under_jungle_cabin.json │ ├── under_oak_cabin/ │ │ └── under_oak_cabin.json │ ├── under_spruce_cabin/ │ │ └── under_spruce_cabin.json │ ├── under_stone_cabin/ │ │ └── under_stone_cabin.json │ └── under_tainted_cabin/ │ └── under_tainted_cabin.json ├── client/ │ ├── CameraInGame.lua │ ├── ControlAimMode.lua │ ├── InputControl.lua │ ├── MenuJoinInfo.lua │ ├── ModClient.lua │ ├── ModMusicSceneProxy.lua │ ├── MusicCopyright.lua │ ├── MusicPool.lua │ ├── MusicScene.lua │ ├── MusicSceneProxy.lua │ └── MusicSystem.lua ├── constants/ │ └── Constants.lua ├── contents/ │ ├── IGNORE_THIS_FOLDER.txt │ └── commands/ │ ├── admin.json │ ├── admin.lua │ ├── autosave-off.json │ ├── autosave-on.json │ ├── autosaveoff.lua │ ├── autosaveon.lua │ ├── banip.json │ ├── banip.lua │ ├── blacklist.json │ ├── blacklist.lua │ ├── blueyoshiiscool.json │ ├── buff.json │ ├── buff.lua │ ├── buffp.json │ ├── byiscool.lua │ ├── clear.json │ ├── clear.lua │ ├── clearp.json │ ├── day.json │ ├── day.lua │ ├── dayf.json │ ├── dayf.lua │ ├── daylock.json │ ├── daylock.lua │ ├── dayspeed.json │ ├── dayspeed.lua │ ├── dayunlock.json │ ├── dayunlock.lua │ ├── effect.json │ ├── effect.lua │ ├── enchant.json │ ├── enchant.lua │ ├── ex.json │ ├── ex.lua │ ├── exp.json │ ├── gamemode.json │ ├── gamemodep.json │ ├── gamemodep.lua │ ├── gamemodew.json │ ├── gamemodew.lua │ ├── give.json │ ├── give.lua │ ├── givep.json │ ├── home.json │ ├── home.lua │ ├── kick.json │ ├── kick.lua │ ├── kickall.json │ ├── kickall.lua │ ├── kill.json │ ├── kill.lua │ ├── killp.json │ ├── master.json │ ├── master.lua │ ├── me.json │ ├── me.lua │ ├── msg.json │ ├── msg.lua │ ├── noadmin.json │ ├── noadmin.lua │ ├── nobanip.json │ ├── nobanip.lua │ ├── nomaster.json │ ├── nomaster.lua │ ├── npc.json │ ├── npc.lua │ ├── players.json │ ├── players.lua │ ├── port.json │ ├── port.lua │ ├── pvp-off.json │ ├── pvp-on.json │ ├── pvpoff.lua │ ├── pvpon.lua │ ├── safeblow-off.json │ ├── safeblow-on.json │ ├── safeblowoff.lua │ ├── safeblowon.lua │ ├── save.json │ ├── save.lua │ ├── say.json │ ├── say.lua │ ├── spawn.json │ ├── spawn.lua │ ├── state.json │ ├── stopwea.json │ ├── stopwea.lua │ ├── tp.json │ ├── tp.lua │ ├── tpp.json │ ├── wea.json │ └── wea.lua ├── data/ │ ├── backgrounds.json │ ├── block_config.json │ ├── item_config.json │ ├── sound_config.json │ └── sounds.json ├── effect_ai/ │ ├── Explosion.json │ ├── GlowingFlow.json │ ├── Gore.json │ └── Smoke.json ├── effects/ │ ├── arrow_paticular.json │ ├── chasting_word.json │ ├── chip.json │ ├── chip_fast.json │ ├── circle.json │ ├── ender_flash.json │ ├── exp_paticular.json │ ├── explosion.json │ ├── fallen_flame_star.json │ ├── fire.json │ ├── fire_flame.json │ ├── fire_flame_long.json │ ├── fire_smoke.json │ ├── flame_star.json │ ├── flash.json │ ├── flash2.json │ ├── flow_particular.json │ ├── gores/ │ │ ├── gore_angry_skeleton.json │ │ ├── gore_arrow_zombie.json │ │ ├── gore_bald_zombie.json │ │ ├── gore_bat.json │ │ ├── gore_black_rabbit.json │ │ ├── gore_black_skeleton.json │ │ ├── gore_blood_bat.json │ │ ├── gore_blood_eye.json │ │ ├── gore_blood_skeleton.json │ │ ├── gore_bone_lee.json │ │ ├── gore_bone_officer.json │ │ ├── gore_bone_sniper.json │ │ ├── gore_boney_skeleton.json │ │ ├── gore_brown_mushroom_cow.json │ │ ├── gore_brown_rabbit.json │ │ ├── gore_chicken.json │ │ ├── gore_cow.json │ │ ├── gore_creeper.json │ │ ├── gore_cursed_skull.json │ │ ├── gore_dark_mage.json │ │ ├── gore_dead_mage.json │ │ ├── gore_doge_zombie.json │ │ ├── gore_dolphin.json │ │ ├── gore_drowned.json │ │ ├── gore_dungeon_creeper.json │ │ ├── gore_dungeon_knight.json │ │ ├── gore_eagle.json │ │ ├── gore_enderman.json │ │ ├── gore_evil.json │ │ ├── gore_evoker.json │ │ ├── gore_eye_guard.json │ │ ├── gore_eye_guard_laser.json │ │ ├── gore_flower_creeper.json │ │ ├── gore_fly_eye.json │ │ ├── gore_fly_mouth.json │ │ ├── gore_fly_skeleton.json │ │ ├── gore_giant_cursed_skull.json │ │ ├── gore_grass_walker.json │ │ ├── gore_grim_reaper.json │ │ ├── gore_husk.json │ │ ├── gore_ice_sprite_girl.json │ │ ├── gore_iron_zombie.json │ │ ├── gore_jungle_bat.json │ │ ├── gore_large_bat.json │ │ ├── gore_large_jungle_bat.json │ │ ├── gore_large_spider.json │ │ ├── gore_lava_snake_body.json │ │ ├── gore_lava_snake_head.json │ │ ├── gore_lava_snake_tail.json │ │ ├── gore_mad_skeleton.json │ │ ├── gore_mad_skeleton_armed.json │ │ ├── gore_mad_skeleton_tall.json │ │ ├── gore_mad_skeleton_tall_armed.json │ │ ├── gore_mad_skeleton_tall_helmet_armed.json │ │ ├── gore_magma_birdo.json │ │ ├── gore_man_eater.json │ │ ├── gore_mummy.json │ │ ├── gore_paimon.json │ │ ├── gore_phantom.json │ │ ├── gore_pig.json │ │ ├── gore_ragged_mage.json │ │ ├── gore_red_mage.json │ │ ├── gore_red_mushroom_cow.json │ │ ├── gore_red_phantom.json │ │ ├── gore_rock_man.json │ │ ├── gore_sheep.json │ │ ├── gore_shulker.json │ │ ├── gore_skeleton_assaulter.json │ │ ├── gore_skeleton_blue_armed.json │ │ ├── gore_skeleton_blue_armed_masked.json │ │ ├── gore_skeleton_blue_knight.json │ │ ├── gore_skeleton_fire_armed.json │ │ ├── gore_skeleton_fire_armed_swordsman.json │ │ ├── gore_skeleton_guard.json │ │ ├── gore_skeleton_kid.json │ │ ├── gore_skull.json │ │ ├── gore_small_hell_eater.json │ │ ├── gore_snow_guner.json │ │ ├── gore_spider.json │ │ ├── gore_squid.json │ │ ├── gore_tainted_creeper.json │ │ ├── gore_tainted_skeleton.json │ │ ├── gore_turtle.json │ │ ├── gore_undead_miner.json │ │ ├── gore_vampire_miner.json │ │ ├── gore_villager_zombie.json │ │ ├── gore_waste_mummy.json │ │ ├── gore_white_rabbit.json │ │ ├── gore_wither_skeleton.json │ │ ├── gore_worm_body.json │ │ ├── gore_worm_head.json │ │ ├── gore_worm_tail.json │ │ ├── gore_yellow_rabbit.json │ │ ├── gore_zombie.json │ │ └── gore_zombie_pigman.json │ ├── heal.json │ ├── laser_flash.json │ ├── liquid_paticular.json │ ├── poison.json │ ├── pot_break.json │ ├── redstone_smoke.json │ ├── smoke.json │ ├── star.json │ └── white_smoke.json ├── enchantments/ │ ├── BaseEnchantmentProxy.lua │ ├── EnchantmentAquaAffinity.lua │ ├── EnchantmentBlastProtection.lua │ ├── EnchantmentDepthStrider.lua │ ├── EnchantmentFeatherFalling.lua │ ├── EnchantmentFireProtection.lua │ ├── EnchantmentFrostWalker.lua │ ├── EnchantmentKnockBack.lua │ ├── EnchantmentPhyton.lua │ ├── EnchantmentProjectileProtection.lua │ ├── EnchantmentProtection.lua │ ├── EnchantmentProxies.lua │ ├── EnchantmentRespiration.lua │ ├── EnchantmentSharpness.lua │ ├── EnchantmentThorns.lua │ ├── aqua_affinity.json │ ├── bane_of_arthropods.json │ ├── blast_protection.json │ ├── curse_of_binding.json │ ├── curse_of_vanishing.json │ ├── depth_strider.json │ ├── efficiency.json │ ├── feather_falling.json │ ├── fire_aspect.json │ ├── fire_protection.json │ ├── flame.json │ ├── fortune.json │ ├── frost_walker.json │ ├── infinity.json │ ├── knockback.json │ ├── looting.json │ ├── luck_of_the_sea.json │ ├── lure.json │ ├── multishot.json │ ├── phyton.json │ ├── piercing.json │ ├── power.json │ ├── projectile_protection.json │ ├── protection.json │ ├── punch.json │ ├── quick_charge.json │ ├── respiration.json │ ├── sharpness.json │ ├── silk_touch.json │ ├── smite.json │ ├── thorns.json │ └── unbreaking.json ├── game_debug.json ├── init.lua ├── item_ai/ │ ├── Axe.json │ ├── Axe.lua │ ├── BaseAccessory.lua │ ├── BaseRangedWeapon.lua │ ├── BaseTool.lua │ ├── BlueTalisman.json │ ├── BlueTalisman.lua │ ├── BossCaller.json │ ├── BossCaller.lua │ ├── Bow.json │ ├── Bow.lua │ ├── CrisonEye.json │ ├── CrisonEye.lua │ ├── DungeonEater.json │ ├── DungeonEater.lua │ ├── EnderMirror.json │ ├── EnderMirror.lua │ ├── Food.json │ ├── Food.lua │ ├── Gun.json │ ├── Gun.lua │ ├── InfBow.json │ ├── InfBow.lua │ ├── Ingot.json │ ├── Ingot.lua │ ├── LavaNecklace.json │ ├── LavaNecklace.lua │ ├── LavaSword.json │ ├── LavaSword.lua │ ├── LightingTalisman.json │ ├── LightingTalisman.lua │ ├── Pickaxe.json │ ├── Pickaxe.lua │ ├── Potion.json │ ├── Potion.lua │ ├── RedTalisman.json │ ├── RedTalisman.lua │ ├── RocketBoost.json │ ├── RocketBoost.lua │ ├── Staff.json │ ├── Staff.lua │ ├── Sword.json │ ├── Sword.lua │ ├── Torch.json │ ├── Torch.lua │ ├── cross_bow.json │ ├── cross_bow.lua │ ├── dirt.json │ ├── dirt.lua │ ├── drill.json │ ├── drill.lua │ ├── fire_gun.json │ ├── fishing_rod.json │ ├── fishing_rod.lua │ ├── laser_gun.json │ ├── magic_sword.json │ ├── rocket_launcher.json │ ├── saw.json │ ├── swordA.json │ └── swordA.lua ├── items/ │ ├── accessory/ │ │ ├── blue_talisman.json │ │ ├── gold_talisman.json │ │ ├── heart_talisman.json │ │ ├── lava_necklace.json │ │ ├── lighting_talisman.json │ │ └── rocket_boost.json │ ├── armors/ │ │ ├── ancient/ │ │ │ ├── ancient_chestplate.json │ │ │ ├── ancient_helmet.json │ │ │ └── ancient_leggings.json │ │ ├── bronze/ │ │ │ ├── bronze_chestplate.json │ │ │ ├── bronze_helmet.json │ │ │ └── bronze_leggings.json │ │ ├── copper/ │ │ │ ├── copper_chestplate.json │ │ │ ├── copper_helmet.json │ │ │ └── copper_leggings.json │ │ ├── diamond/ │ │ │ ├── diamond_chestplate.json │ │ │ ├── diamond_helmet.json │ │ │ └── diamond_leggings.json │ │ ├── fine_tin/ │ │ │ ├── fine_tin_chestplate.json │ │ │ ├── fine_tin_helmet.json │ │ │ └── fine_tin_leggings.json │ │ ├── flesh/ │ │ │ ├── flesh_chestplate.json │ │ │ ├── flesh_helmet.json │ │ │ └── flesh_leggings.json │ │ ├── gold/ │ │ │ ├── golden_chestplate.json │ │ │ ├── golden_helmet.json │ │ │ └── golden_leggings.json │ │ ├── iron/ │ │ │ ├── iron_chestplate.json │ │ │ ├── iron_helmet.json │ │ │ └── iron_leggings.json │ │ ├── knight/ │ │ │ ├── knight_chestplate.json │ │ │ ├── knight_helmet.json │ │ │ └── knight_leggings.json │ │ ├── lava/ │ │ │ ├── lava_chestplate.json │ │ │ ├── lava_helmet.json │ │ │ └── lava_leggings.json │ │ ├── lead/ │ │ │ ├── lead_chestplate.json │ │ │ ├── lead_helmet.json │ │ │ └── lead_leggings.json │ │ ├── leather/ │ │ │ ├── leather_chestplate.json │ │ │ ├── leather_helmet.json │ │ │ └── leather_leggings.json │ │ ├── magic_gold/ │ │ │ ├── magic_gold_chestplate.json │ │ │ ├── magic_gold_helmet.json │ │ │ └── magic_gold_leggings.json │ │ ├── magic_shadow/ │ │ │ ├── magic_shadow_chestplate.json │ │ │ ├── magic_shadow_helmet.json │ │ │ └── magic_shadow_leggings.json │ │ ├── magic_silver/ │ │ │ ├── magic_silver_chestplate.json │ │ │ ├── magic_silver_helmet.json │ │ │ └── magic_silver_leggings.json │ │ ├── nether/ │ │ │ ├── nether_chestplate.json │ │ │ ├── nether_helmet.json │ │ │ └── nether_leggings.json │ │ ├── pumpkin/ │ │ │ └── pumpkin_helmet.json │ │ ├── shadow/ │ │ │ ├── shadow_chestplate.json │ │ │ ├── shadow_helmet.json │ │ │ └── shadow_leggings.json │ │ ├── silver/ │ │ │ ├── silver_chestplate.json │ │ │ ├── silver_helmet.json │ │ │ └── silver_leggings.json │ │ ├── star/ │ │ │ ├── star_chestplate.json │ │ │ ├── star_helmet.json │ │ │ └── star_leggings.json │ │ ├── steel/ │ │ │ ├── steel_chestplate.json │ │ │ ├── steel_helmet.json │ │ │ └── steel_leggings.json │ │ ├── super_diamond/ │ │ │ ├── super_diamond_chestplate.json │ │ │ ├── super_diamond_helmet.json │ │ │ └── super_diamond_leggings.json │ │ └── tin/ │ │ ├── tin_chestplate.json │ │ ├── tin_helmet.json │ │ └── tin_leggings.json │ ├── arrows/ │ │ ├── blood_arrow.json │ │ ├── blue_arrow.json │ │ ├── ice_arrow.json │ │ ├── lighting_arrow.json │ │ ├── star_arrow.json │ │ ├── sword_arrow.json │ │ └── wooden_arrow.json │ ├── axes/ │ │ ├── bronze_axe.json │ │ ├── copper_axe.json │ │ ├── diamond_axe.json │ │ ├── golden_axe.json │ │ ├── grass_axe.json │ │ ├── iron_axe.json │ │ ├── lead_axe.json │ │ ├── nether_axe.json │ │ ├── silver_axe.json │ │ ├── steel_axe.json │ │ ├── stone_axe.json │ │ ├── tin_axe.json │ │ └── wooden_axe.json │ ├── bombs/ │ │ ├── bomb.json │ │ ├── glow_bomb.json │ │ └── grenade.json │ ├── boomerangs/ │ │ ├── boomerang.json │ │ ├── fire_boomerang.json │ │ └── wooden_boomerang.json │ ├── bows/ │ │ ├── blood_bow.json │ │ ├── blue_shot_bow.json │ │ ├── blue_stone_bow.json │ │ ├── chast_bow.json │ │ ├── cross_bow.json │ │ ├── curse_bow.json │ │ ├── ice_bow.json │ │ ├── lighting_bow.json │ │ ├── shot_bow.json │ │ ├── super_cross_bow.json │ │ ├── super_fire_shot_bow.json │ │ ├── super_spike_shot_bow.json │ │ └── wooden_bow.json │ ├── buckets/ │ │ ├── bucket_empty.json │ │ ├── bucket_lava.json │ │ ├── bucket_milk.json │ │ └── bucket_water.json │ ├── bullets/ │ │ ├── fire_bullet.json │ │ ├── iron_bullet.json │ │ └── silver_bullet.json │ ├── dyes/ │ │ ├── dye_black.json │ │ ├── dye_blue.json │ │ ├── dye_brown.json │ │ ├── dye_cyan.json │ │ ├── dye_gray.json │ │ ├── dye_green.json │ │ ├── dye_light_blue.json │ │ ├── dye_light_gray.json │ │ ├── dye_lime.json │ │ ├── dye_magenta.json │ │ ├── dye_orange.json │ │ ├── dye_pink.json │ │ ├── dye_purple.json │ │ ├── dye_red.json │ │ ├── dye_white.json │ │ └── dye_yellow.json │ ├── foods/ │ │ ├── apple.json │ │ ├── baked_potato.json │ │ ├── beetroot.json │ │ ├── bread.json │ │ ├── cake_piece.json │ │ ├── carrot.json │ │ ├── chorus_fruit.json │ │ ├── cooked_chicken.json │ │ ├── cooked_cod.json │ │ ├── cooked_mutton.json │ │ ├── cooked_porkchop.json │ │ ├── cooked_rabbit.json │ │ ├── cooked_salmon.json │ │ ├── cookie.json │ │ ├── golden_apple.json │ │ ├── golden_carrot.json │ │ ├── melon_slice.json │ │ ├── mushroom_stew.json │ │ ├── potato.json │ │ ├── pufferfish.json │ │ ├── pumpkin_pie.json │ │ ├── raw_beef.json │ │ ├── raw_chicken.json │ │ ├── raw_cod.json │ │ ├── raw_mutton.json │ │ ├── raw_porkchop.json │ │ ├── raw_rabbit.json │ │ ├── raw_salmon.json │ │ └── steak.json │ ├── guns/ │ │ ├── fire_gun.json │ │ ├── fire_shooter.json │ │ ├── handgun.json │ │ ├── rifle.json │ │ ├── rocket_launcher.json │ │ ├── shotgun.json │ │ └── sniper.json │ ├── hoes/ │ │ ├── stone_hoe.json │ │ └── wooden_hoe.json │ ├── ingots/ │ │ ├── aluminum_ingot.json │ │ ├── antimony_ingot.json │ │ ├── beryllium_ingot.json │ │ ├── bismuth_ingot.json │ │ ├── bronze_ingot.json │ │ ├── chromium_ingot.json │ │ ├── cobalt_ingot.json │ │ ├── copper_ingot.json │ │ ├── gallium_ingot.json │ │ ├── gold_ingot.json │ │ ├── indium_ingot.json │ │ ├── iridium_ingot.json │ │ ├── iron_ingot.json │ │ ├── lead_ingot.json │ │ ├── lithium_ingot.json │ │ ├── magnesium_ingot.json │ │ ├── manganese_ingot.json │ │ ├── molybdenum_ingot.json │ │ ├── netherite_ingot.json │ │ ├── nickel_ingot.json │ │ ├── niobium_ingot.json │ │ ├── osmium_ingot.json │ │ ├── palladium_ingot.json │ │ ├── platinum_ingot.json │ │ ├── redstone_ingot.json │ │ ├── rhenium_ingot.json │ │ ├── silver_ingot.json │ │ ├── sodium_ingot.json │ │ ├── steel_ingot.json │ │ ├── tantalum_ingot.json │ │ ├── tin_ingot.json │ │ ├── titanium_ingot.json │ │ ├── vanadium_ingot.json │ │ ├── vibranium_ingot.json │ │ ├── wolfram_ingot.json │ │ ├── yttrium_ingot.json │ │ └── zinc_ingot.json │ ├── loots/ │ │ ├── guardian.json │ │ ├── nether_destroyer_loot.json │ │ └── snow_queen_loot.json │ ├── magic/ │ │ ├── bone_gun.json │ │ ├── dark_staff.json │ │ ├── fire_book.json │ │ ├── mini_laser_gun.json │ │ ├── mini_rocket_launcher.json │ │ ├── soul_laserer.json │ │ ├── super_shark.json │ │ ├── super_shark_ghost.json │ │ ├── sword_fish.json │ │ ├── sword_fish_gun.json │ │ └── water_book.json │ ├── misc/ │ │ ├── blaze_powder.json │ │ ├── blaze_rod.json │ │ ├── bone.json │ │ ├── bone_meal.json │ │ ├── book.json │ │ ├── bowl.json │ │ ├── charcoal.json │ │ ├── clay.json │ │ ├── coal.json │ │ ├── cocoa_bean.json │ │ ├── diamond.json │ │ ├── dried_kelp.json │ │ ├── egg.json │ │ ├── emerald.json │ │ ├── enchanted_book.json │ │ ├── ender_eye.json │ │ ├── ender_pearl.json │ │ ├── feather.json │ │ ├── fermented_spider_eye.json │ │ ├── fire_charge.json │ │ ├── firework_rocket.json │ │ ├── fishing_rod.json │ │ ├── flint.json │ │ ├── ghast_tear.json │ │ ├── glistering_melon_slice.json │ │ ├── glow_ball.json │ │ ├── glowstone_dust.json │ │ ├── gray_feather.json │ │ ├── gunpowder.json │ │ ├── heart_of_sea.json │ │ ├── ink_sac.json │ │ ├── kelp.json │ │ ├── lapis_lazuli.json │ │ ├── leather.json │ │ ├── lighter.json │ │ ├── magma_cream.json │ │ ├── mana_piece.json │ │ ├── map_paper.json │ │ ├── nautilus_shell.json │ │ ├── nether_brick.json │ │ ├── nether_star.json │ │ ├── nether_wart.json │ │ ├── netherite_scrap.json │ │ ├── paper.json │ │ ├── phantom_membrane.json │ │ ├── popped_chorus_fruits.json │ │ ├── prismarine_crystals.json │ │ ├── prismarine_shard.json │ │ ├── quartz.json │ │ ├── rabbit_foot.json │ │ ├── rabbit_hide.json │ │ ├── red_brick.json │ │ ├── redstone.json │ │ ├── rocket.json │ │ ├── rotten_flesh.json │ │ ├── scute.json │ │ ├── shears.json │ │ ├── shulker_shell.json │ │ ├── slimeball.json │ │ ├── snowball.json │ │ ├── spider_eye.json │ │ ├── stick.json │ │ ├── string.json │ │ ├── sugar_cane.json │ │ ├── suger.json │ │ ├── totem_of_undying.json │ │ ├── vine.json │ │ ├── wheat.json │ │ └── wire_cutter.json │ ├── misc2/ │ │ ├── ancient_ingot.json │ │ ├── ancient_sample.json │ │ ├── blood.json │ │ ├── blue_crystal.json │ │ ├── dark_shadow_ingot.json │ │ ├── dark_shadow_part.json │ │ ├── diamond_ingot.json │ │ ├── ender_mirror.json │ │ ├── evil_part.json │ │ ├── flesh_ingot.json │ │ ├── flesh_machine_part.json │ │ ├── flesh_part.json │ │ ├── ghost.json │ │ ├── ghost_crystal.json │ │ ├── ghost_element.json │ │ ├── ice_element.json │ │ ├── ice_element_ball.json │ │ ├── knight_ingot.json │ │ ├── machine_part.json │ │ ├── magic_cell.json │ │ ├── magic_cell_group.json │ │ ├── magic_crystal.json │ │ ├── magic_silver_ingot.json │ │ ├── magma_gold_ingot.json │ │ ├── nether_destroyer.json │ │ ├── pure_red_stone.json │ │ ├── red_crystal.json │ │ ├── red_gold_ingot.json │ │ ├── soul_element.json │ │ ├── star_ingot.json │ │ ├── strange_eye.json │ │ ├── strange_len.json │ │ ├── tower_core.json │ │ ├── white_crystal.json │ │ └── yellow_crystal.json │ ├── nuggets/ │ │ ├── gold_nugget.json │ │ └── iron_nugget.json │ ├── pickaxes/ │ │ ├── bronze_pickaxe.json │ │ ├── copper_pickaxe.json │ │ ├── diamond_pickaxe.json │ │ ├── golden_pickaxe.json │ │ ├── grass_pickaxe.json │ │ ├── iron_pickaxe.json │ │ ├── lead_pickaxe.json │ │ ├── nether_pickaxe.json │ │ ├── silver_pickaxe.json │ │ ├── steel_pickaxe.json │ │ ├── stone_pickaxe.json │ │ ├── tin_pickaxe.json │ │ └── wooden_pickaxe.json │ ├── potions/ │ │ ├── glass_bottle.json │ │ ├── potion_awkward.json │ │ ├── potion_fire_resistance.json │ │ ├── potion_fire_resistance_long.json │ │ ├── potion_glowing.json │ │ ├── potion_glowing_long.json │ │ ├── potion_harming.json │ │ ├── potion_harming_super.json │ │ ├── potion_healing.json │ │ ├── potion_healing_super.json │ │ ├── potion_invisibility.json │ │ ├── potion_invisibility_long.json │ │ ├── potion_leaping.json │ │ ├── potion_leaping_long.json │ │ ├── potion_night_vision.json │ │ ├── potion_night_vision_long.json │ │ ├── potion_poison.json │ │ ├── potion_poison_long.json │ │ ├── potion_regeneration.json │ │ ├── potion_regeneration_long.json │ │ ├── potion_slow_falling.json │ │ ├── potion_slow_falling_long.json │ │ ├── potion_slowness.json │ │ ├── potion_slowness_long.json │ │ ├── potion_strength.json │ │ ├── potion_strength_long.json │ │ ├── potion_swiftness.json │ │ ├── potion_swiftness_long.json │ │ ├── potion_water.json │ │ ├── potion_water_breathing.json │ │ ├── potion_water_breathing_long.json │ │ ├── potion_weakness.json │ │ └── potion_weakness_long.json │ ├── seeds/ │ │ ├── melon_seed.json │ │ ├── pumpkin_seed.json │ │ └── seed.json │ ├── staffs/ │ │ ├── amethyst_staff.json │ │ ├── fire_staff.json │ │ ├── frosen_staff.json │ │ ├── ice_staff.json │ │ ├── lighting_staff.json │ │ ├── shadow_staff.json │ │ ├── soul_staff.json │ │ └── water_staff.json │ ├── swords/ │ │ ├── air_sword.json │ │ ├── bronze_sword.json │ │ ├── copper_sword.json │ │ ├── diamond_sword.json │ │ ├── ghost_sword.json │ │ ├── golden_sword.json │ │ ├── grass_sword.json │ │ ├── iron_sword.json │ │ ├── lava_sword.json │ │ ├── lead_sword.json │ │ ├── nether_sword.json │ │ ├── silver_sword.json │ │ ├── steel_sword.json │ │ ├── stone_sword.json │ │ ├── super_air_sword.json │ │ ├── super_bronze_sword.json │ │ ├── super_copper_sword.json │ │ ├── super_diamond_sword.json │ │ ├── super_golden_sword.json │ │ ├── super_iron_sword.json │ │ ├── super_lead_sword.json │ │ ├── super_nether_sword.json │ │ ├── super_silver_sword.json │ │ ├── super_steel_sword.json │ │ ├── super_tin_sword.json │ │ ├── tin_sword.json │ │ └── wooden_sword.json │ └── wires/ │ ├── blue_wire.json │ ├── green_wire.json │ ├── red_wire.json │ └── yellow_wire.json ├── languages/ │ ├── Locale.lua │ ├── LocaleHelper.lua │ ├── chinese.json │ └── english.json ├── liquids/ │ ├── lava.json │ └── water.json ├── mod_textures/ │ ├── ModTextures.lua │ ├── blade.json │ ├── candle_fire.json │ ├── candle_fire_blue.json │ ├── crack.json │ ├── electric_direction.json │ ├── fire.json │ ├── flesh_grass.json │ ├── fly_book.json │ ├── grass.json │ ├── mycelium_grass.json │ ├── tainted_grass.json │ ├── torch_fire.json │ ├── torch_fire_blue.json │ ├── torch_fire_green.json │ ├── torch_fire_red.json │ ├── torch_fire_white.json │ ├── torch_fire_yellow.json │ └── torch_redstone.json ├── network/ │ ├── ClientBoundResponse.lua │ ├── ModNetworkProxyHandler.lua │ ├── NetworkProxy.lua │ ├── RPC_ID.lua │ └── TCNetworkProxyHandler.lua ├── npc_ai/ │ ├── AngrySkeleton.json │ ├── AngrySkeleton.lua │ ├── Animal.json │ ├── Animal.lua │ ├── Archer.json │ ├── Archer.lua │ ├── BallMagic.json │ ├── BallMagic.lua │ ├── BaseSnake.lua │ ├── BaseSnakeBody.lua │ ├── Bat.json │ ├── Bat.lua │ ├── BlackSkeleton.json │ ├── BlackSkeleton.lua │ ├── Blaze.json │ ├── Blaze.lua │ ├── BlockSlime.json │ ├── BlockSlime.lua │ ├── BloodSkeleton.json │ ├── BloodSkeleton.lua │ ├── BloodyEye.json │ ├── BloodyEye.lua │ ├── BoneArcher.json │ ├── BoneArcher.lua │ ├── BoneLee.json │ ├── BoneLee.lua │ ├── BoneOfficer.json │ ├── BoneOfficer.lua │ ├── BoneSniper.json │ ├── BoneSniper.lua │ ├── BoneySkeleton.json │ ├── BoneySkeleton.lua │ ├── BouncySlime.json │ ├── BouncySlime.lua │ ├── Butterfly.json │ ├── Butterfly.lua │ ├── Cat.json │ ├── Cat.lua │ ├── Chicken.json │ ├── Chicken.lua │ ├── Creeper.json │ ├── Creeper.lua │ ├── CrisonEye.json │ ├── CrisonEye.lua │ ├── CrystalMonster.json │ ├── CrystalMonster.lua │ ├── CursedSkull.json │ ├── CursedSkull.lua │ ├── DarkMage.json │ ├── DarkMage.lua │ ├── DeadMage.json │ ├── DeadMage.lua │ ├── Dolphin.json │ ├── Dolphin.lua │ ├── DungeonCreeper.json │ ├── DungeonCreeper.lua │ ├── DungeonEater.lua │ ├── DungeonEaterBody.lua │ ├── DungeonEater_Body.json │ ├── DungeonEater_Head.json │ ├── DungeonKnight.json │ ├── DungeonKnight.lua │ ├── DungeonSkeleton.json │ ├── DungeonSkeleton.lua │ ├── DungeonSoul.json │ ├── DungeonSoul.lua │ ├── Eagle.json │ ├── Eagle.lua │ ├── Ender_Dragon.json │ ├── Enderman.json │ ├── Enderman.lua │ ├── Evil.json │ ├── Evil.lua │ ├── Evoker.json │ ├── Evoker.lua │ ├── EyeGuard.json │ ├── EyeGuard.lua │ ├── EyeGuardLaser.json │ ├── EyeGuardLaser.lua │ ├── Fighter.json │ ├── Fighter.lua │ ├── FireHellEater.json │ ├── FireHellEater.lua │ ├── FlameSoul.json │ ├── FlameSoul.lua │ ├── FlyEye.json │ ├── FlyEye.lua │ ├── FlySkeleton.json │ ├── FlySkeleton.lua │ ├── Ghast.json │ ├── Ghast.lua │ ├── GhostGunner.json │ ├── GhostGunner.lua │ ├── GhostSoul.json │ ├── GhostSoul.lua │ ├── GiantCursedSkull.json │ ├── GiantCursedSkull.lua │ ├── GrimReaper.json │ ├── GrimReaper.lua │ ├── Guardian.json │ ├── Guardian.lua │ ├── HellDestroyer.lua │ ├── HellDestroyer_Head.json │ ├── HellEater.json │ ├── HellEater.lua │ ├── HumanFighter.json │ ├── HumanFighter.lua │ ├── IceElf.json │ ├── IceElf.lua │ ├── JungleSnake.lua │ ├── JungleSnake_Head.json │ ├── LargeBat.json │ ├── LargeBat.lua │ ├── LargeSpider.json │ ├── LargeSpider.lua │ ├── MagmaBirdo.json │ ├── MagmaBirdo.lua │ ├── MagmaElf.json │ ├── MagmaElf.lua │ ├── MagmaSlime.json │ ├── MagmaSlime.lua │ ├── ManEater.json │ ├── ManEater.lua │ ├── Meteor.json │ ├── Meteor.lua │ ├── MiniGhast.json │ ├── MiniGhast.lua │ ├── Paimon.json │ ├── Paimon.lua │ ├── Phantom.json │ ├── Phantom.lua │ ├── Pufferfish.json │ ├── Pufferfish.lua │ ├── RaggedMage.json │ ├── RaggedMage.lua │ ├── RedMage.json │ ├── RedMage.lua │ ├── RedPhantom.json │ ├── RedPhantom.lua │ ├── RockMan.json │ ├── RockMan.lua │ ├── RollingFireBall.json │ ├── RollingFireBall.lua │ ├── Sheep.json │ ├── Shulker.json │ ├── Shulker.lua │ ├── SkeletonAssaulter.json │ ├── SkeletonAssaulter.lua │ ├── SkeletonGuard.json │ ├── SkeletonGuard.lua │ ├── Slime.json │ ├── Slime.lua │ ├── Snake_Body.json │ ├── Snake_Head.json │ ├── SnowGuardian.json │ ├── SnowGuardian.lua │ ├── SnowGuardianArcher.json │ ├── SnowGuardianArcher.lua │ ├── SnowQueen.json │ ├── SnowQueen.lua │ ├── Squid.json │ ├── Squid.lua │ ├── SwordHumanFighter.lua │ ├── TaintedSlime.json │ ├── TaintedSlime.lua │ ├── UndeadMiner.json │ ├── UndeadMiner.lua │ ├── Villager.json │ ├── WasteGhost.json │ ├── WasteGhost.lua │ ├── WitherSkeleton.json │ ├── WitherSkeleton.lua │ ├── Wolf.json │ ├── Wolf.lua │ ├── Zombie.json │ ├── Zombie.lua │ ├── Zpig.json │ └── Zpig.lua ├── npc_ai_global/ │ ├── GNpc.lua │ └── GlobalNpc.json ├── npcs/ │ ├── angry_skeleton.json │ ├── arrow_zombie.json │ ├── bald_zombie.json │ ├── bat.json │ ├── black_rabbit.json │ ├── black_skeleton.json │ ├── blaze.json │ ├── block_slime.json │ ├── blood_bat.json │ ├── blood_eye.json │ ├── blood_skeleton.json │ ├── blood_slime.json │ ├── blue_slime.json │ ├── bone_lee.json │ ├── bone_officer.json │ ├── bone_sniper.json │ ├── boney_skeleton.json │ ├── bouncy_slime.json │ ├── brown_mushroom_cow.json │ ├── brown_rabbit.json │ ├── cat.json │ ├── chicken.json │ ├── cow.json │ ├── creeper.json │ ├── crison_eye.json │ ├── crystal_monster.json │ ├── cursed_skull.json │ ├── dark_mage.json │ ├── dead_mage.json │ ├── desert_slime.json │ ├── doge_zombie.json │ ├── dolphin.json │ ├── dragon_skull.json │ ├── drowned.json │ ├── dungeon_creeper.json │ ├── dungeon_eater_body.json │ ├── dungeon_eater_head.json │ ├── dungeon_eater_tail.json │ ├── dungeon_knight.json │ ├── dungeon_slime.json │ ├── dungeon_soul.json │ ├── eagle.json │ ├── ender_dragon.json │ ├── enderman.json │ ├── evil.json │ ├── evoker.json │ ├── eye_guard.json │ ├── eye_guard_laser.json │ ├── flame_soul.json │ ├── flower_creeper.json │ ├── fly_eye.json │ ├── fly_mouth.json │ ├── fly_skeleton.json │ ├── ghast.json │ ├── ghost_gunner.json │ ├── ghost_soul.json │ ├── giant_cursed_skull.json │ ├── green_slime.json │ ├── grim_reaper.json │ ├── guardian.json │ ├── husk.json │ ├── ice_elf.json │ ├── ice_slime.json │ ├── iron_zombie.json │ ├── jungle_bat.json │ ├── large_bat.json │ ├── large_black_slime.json │ ├── large_block_slime.json │ ├── large_desert_slime.json │ ├── large_green_slime.json │ ├── large_ice_slime.json │ ├── large_jungle_bat.json │ ├── large_spider.json │ ├── large_tainted_slime.json │ ├── large_waste_block_slime.json │ ├── large_waste_slime.json │ ├── light_blue_butterfly.json │ ├── mad_skeleton.json │ ├── mad_skeleton_armed.json │ ├── mad_skeleton_tall.json │ ├── mad_skeleton_tall_armed.json │ ├── mad_skeleton_tall_helmet_armed.json │ ├── magma_birdo.json │ ├── magma_elf.json │ ├── magma_slime.json │ ├── man_eater.json │ ├── meteor.json │ ├── mini_ghast.json │ ├── mummy.json │ ├── phantom.json │ ├── pig.json │ ├── pufferfish.json │ ├── purple_slime.json │ ├── ragged_mage.json │ ├── red_butterfly.json │ ├── red_mage.json │ ├── red_mushroom_cow.json │ ├── red_phantom.json │ ├── rock_man.json │ ├── rolling_fire_ball.json │ ├── sheep.json │ ├── shulker.json │ ├── skeleton.json │ ├── skeleton_assaulter.json │ ├── skeleton_blue_armed.json │ ├── skeleton_blue_armed_masked.json │ ├── skeleton_blue_knight.json │ ├── skeleton_fire_armed.json │ ├── skeleton_fire_armed_swordsman.json │ ├── skeleton_guard.json │ ├── small_fire_hell_eater.json │ ├── small_hell_eater.json │ ├── snow_guardian.json │ ├── snow_guardian_archer.json │ ├── snow_queen.json │ ├── snow_slime.json │ ├── spider.json │ ├── squid.json │ ├── tainted_creeper.json │ ├── tainted_skeleton.json │ ├── tainted_slime.json │ ├── turtle.json │ ├── undead_miner.json │ ├── vampire_miner.json │ ├── villager_zombie.json │ ├── vine_man_eater_body.json │ ├── vine_man_eater_head.json │ ├── vine_man_eater_tail.json │ ├── waste_block_slime.json │ ├── waste_ghost.json │ ├── waste_mummy.json │ ├── white_rabbit.json │ ├── wither_skeleton.json │ ├── wolf.json │ ├── worm_body.json │ ├── worm_head.json │ ├── worm_tail.json │ ├── yellow_butterfly.json │ ├── yellow_rabbit.json │ ├── yellow_slime.json │ ├── zombie.json │ └── zombie_pigman.json ├── package.json ├── player/ │ ├── GPlayer.lua │ ├── GlobalPlayer.json │ └── PlayerConstants.lua ├── projectile_ai/ │ ├── AirBullet.json │ ├── AirBullet.lua │ ├── AirWave.json │ ├── AirWave.lua │ ├── AmethystMagic.json │ ├── AmethystMagic.lua │ ├── Arrow.json │ ├── Arrow.lua │ ├── BlackHole.json │ ├── BlackHole.lua │ ├── BlazeRod.json │ ├── BlazeRod.lua │ ├── BloodArrow.json │ ├── BloodArrow.lua │ ├── BlueArrow.json │ ├── BlueArrow.lua │ ├── BlueBullet.json │ ├── BlueBullet.lua │ ├── BlueWave.json │ ├── BlueWave.lua │ ├── Bomb.json │ ├── Bomb.lua │ ├── Boomerang.json │ ├── Boomerang.lua │ ├── Bullet.json │ ├── Bullet.lua │ ├── CrystalMagic.json │ ├── CrystalMagic.lua │ ├── CursedArrow.json │ ├── CursedArrow.lua │ ├── Fire.json │ ├── Fire.lua │ ├── FireArrow.json │ ├── FireArrow.lua │ ├── FireElement.json │ ├── FireElement.lua │ ├── FireFlow.json │ ├── FireFlow.lua │ ├── FireFlowLarge.json │ ├── FireFlowLarge.lua │ ├── FireMagic.json │ ├── FireMagic.lua │ ├── Fireball.json │ ├── Fireball.lua │ ├── GlowBomb.json │ ├── GlowBomb.lua │ ├── Glowball.json │ ├── Glowball.lua │ ├── Grenade.json │ ├── Grenade.lua │ ├── IceArrow.json │ ├── IceArrow.lua │ ├── IceBullet.json │ ├── IceBullet.lua │ ├── IceMagic.json │ ├── IceMagic.lua │ ├── LaserBullet.json │ ├── LaserBullet.lua │ ├── LightingArrow.json │ ├── LightingArrow.lua │ ├── LightingBulletYellow.json │ ├── LightingBulletYellow.lua │ ├── LightingWheel.json │ ├── LightingWheel.lua │ ├── MagicWave.json │ ├── MagicWave.lua │ ├── MiniRocket.json │ ├── MiniRocket.lua │ ├── RedSpeedUp.json │ ├── RedSpeedUp.lua │ ├── Rocket.json │ ├── Rocket.lua │ ├── ShadowMagic.json │ ├── ShadowMagic.lua │ ├── ShulkerBullet.json │ ├── ShulkerBullet.lua │ ├── SnowFlake.json │ ├── SnowFlake.lua │ ├── Spike.json │ ├── Spike.lua │ ├── StarArrow.json │ ├── StarArrow.lua │ ├── StarMagic.json │ ├── StarMagic.lua │ ├── SuperBullet.json │ ├── SuperBullet.lua │ ├── SuperFire.json │ ├── SuperFire.lua │ ├── SwordArrow.json │ ├── SwordArrow.lua │ ├── WaterFlow.json │ ├── WaterFlow.lua │ ├── WaterMagic.json │ └── WaterMagic.lua ├── projectile_ai_global/ │ ├── GProjectile.lua │ └── GlobalProjectile.json ├── projectiles/ │ ├── air_bullet.json │ ├── air_wave.json │ ├── amethyst_magic.json │ ├── black_hole.json │ ├── blaze_rod.json │ ├── blood_arrow.json │ ├── blue_arrow.json │ ├── bomb.json │ ├── bone.json │ ├── boomerang.json │ ├── bullet.json │ ├── bullet_laser.json │ ├── bullet_super.json │ ├── crystal_magic.json │ ├── cursed_arrow.json │ ├── fire_arrow.json │ ├── fire_boomerang.json │ ├── fire_charge.json │ ├── fire_element.json │ ├── fire_flow.json │ ├── fire_flow_large.json │ ├── fire_magic.json │ ├── fire_wave.json │ ├── glow_ball.json │ ├── glow_bomb.json │ ├── grenade.json │ ├── gun_fire.json │ ├── ice_arrow.json │ ├── ice_bullet.json │ ├── ice_magic.json │ ├── light_bullet_laser.json │ ├── lighting_arrow.json │ ├── lighting_bullet_blue.json │ ├── lighting_bullet_red_invert2.json │ ├── lighting_bullet_yellow.json │ ├── lighting_wheel.json │ ├── magic_wave.json │ ├── magic_wave3.json │ ├── mini_rocket.json │ ├── rocket.json │ ├── shadow_magic.json │ ├── shulker_bullet.json │ ├── small_air_bullet.json │ ├── snow_flake.json │ ├── spike.json │ ├── star.json │ ├── star_arrow.json │ ├── super_fire.json │ ├── sword_arrow.json │ ├── tnt.json │ ├── water_flow.json │ ├── water_magic.json │ ├── wooden_arrow.json │ └── wooden_boomerang.json ├── recipe_config/ │ ├── Brew.json │ ├── Craft3x.json │ ├── Repair.json │ └── Smelt.json ├── recipes/ │ ├── brew/ │ │ ├── potion_awkward.json │ │ ├── potion_fire_resistance.json │ │ ├── potion_fire_resistance_long.json │ │ ├── potion_glowing.json │ │ ├── potion_harming.json │ │ ├── potion_harming_2.json │ │ ├── potion_harming_super.json │ │ ├── potion_healing.json │ │ ├── potion_healing_super.json │ │ ├── potion_invisibility.json │ │ ├── potion_invisibility_long.json │ │ ├── potion_leaping.json │ │ ├── potion_leaping_long.json │ │ ├── potion_night_vision.json │ │ ├── potion_night_vision_long.json │ │ ├── potion_poison.json │ │ ├── potion_poison_2.json │ │ ├── potion_poison_long.json │ │ ├── potion_regeneration.json │ │ ├── potion_regeneration_long.json │ │ ├── potion_slow_falling.json │ │ ├── potion_slow_falling_long.json │ │ ├── potion_slowness.json │ │ ├── potion_slowness_2.json │ │ ├── potion_slowness_long.json │ │ ├── potion_strength.json │ │ ├── potion_strength_long.json │ │ ├── potion_swiftness.json │ │ ├── potion_swiftness_long.json │ │ ├── potion_water_breathing.json │ │ ├── potion_water_breathing_long.json │ │ ├── potion_weakness.json │ │ ├── potion_weakness_2.json │ │ └── potion_weakness_long.json │ ├── craft3x/ │ │ ├── acacia_plank.json │ │ ├── amethyst_staff.json │ │ ├── amethyst_staff_2.json │ │ ├── ancient_ingot.json │ │ ├── andesite.json │ │ ├── andesite_polished.json │ │ ├── anvil.json │ │ ├── barrel.json │ │ ├── bench_acacia.json │ │ ├── bench_birch.json │ │ ├── bench_dark_oak.json │ │ ├── bench_jungle.json │ │ ├── bench_nether.json │ │ ├── bench_oak.json │ │ ├── bench_palm.json │ │ ├── bench_spruce.json │ │ ├── bench_tainted.json │ │ ├── bench_volcano.json │ │ ├── birch_plank.json │ │ ├── blaze_powder.json │ │ ├── block_coal.json │ │ ├── block_diamond.json │ │ ├── block_emerald.json │ │ ├── block_gold.json │ │ ├── block_iron.json │ │ ├── block_lapis.json │ │ ├── block_netherite.json │ │ ├── block_quartz.json │ │ ├── block_redstone.json │ │ ├── blood_arrow.json │ │ ├── blood_arrow_2.json │ │ ├── blood_bow.json │ │ ├── blue_ice.json │ │ ├── blue_stone_bow.json │ │ ├── blue_torch.json │ │ ├── blue_wire.json │ │ ├── bomb.json │ │ ├── bomb_2.json │ │ ├── bone_block.json │ │ ├── bone_meal.json │ │ ├── bone_meal_2.json │ │ ├── book.json │ │ ├── book_block.json │ │ ├── bookcase_acacia.json │ │ ├── bookcase_birch.json │ │ ├── bookcase_dark_oak.json │ │ ├── bookcase_jungle.json │ │ ├── bookcase_nether.json │ │ ├── bookcase_oak.json │ │ ├── bookcase_palm.json │ │ ├── bookcase_spruce.json │ │ ├── bookcase_tainted.json │ │ ├── bookcase_volcano.json │ │ ├── boomerang.json │ │ ├── boomerang_2.json │ │ ├── bowl.json │ │ ├── bread.json │ │ ├── brewing_stand.json │ │ ├── brick.json │ │ ├── bronze_axe.json │ │ ├── bronze_chestplate.json │ │ ├── bronze_helmet.json │ │ ├── bronze_ingot.json │ │ ├── bronze_leggings.json │ │ ├── bronze_pickaxe.json │ │ ├── bronze_sword.json │ │ ├── brown_mushroom.json │ │ ├── brown_mushroom_2.json │ │ ├── bucket_empty.json │ │ ├── cabinet_acacia.json │ │ ├── cabinet_birch.json │ │ ├── cabinet_dark_oak.json │ │ ├── cabinet_jungle.json │ │ ├── cabinet_nether.json │ │ ├── cabinet_oak.json │ │ ├── cabinet_palm.json │ │ ├── cabinet_spruce.json │ │ ├── cabinet_tainted.json │ │ ├── cabinet_volcano.json │ │ ├── cake.json │ │ ├── cake_piece.json │ │ ├── campfire.json │ │ ├── campfire_2.json │ │ ├── campfire_3.json │ │ ├── campfire_4.json │ │ ├── candle.json │ │ ├── candle_holder.json │ │ ├── cauldron.json │ │ ├── chair_acacia.json │ │ ├── chair_birch.json │ │ ├── chair_dark_oak.json │ │ ├── chair_jungle.json │ │ ├── chair_nether.json │ │ ├── chair_oak.json │ │ ├── chair_palm.json │ │ ├── chair_spruce.json │ │ ├── chair_tainted.json │ │ ├── chair_volcano.json │ │ ├── chandeliers.json │ │ ├── chest.json │ │ ├── clay.json │ │ ├── clay_block.json │ │ ├── coal.json │ │ ├── coarse_dirt.json │ │ ├── cobblestone_fence.json │ │ ├── cobblestone_mossy.json │ │ ├── cobweb.json │ │ ├── cookie.json │ │ ├── copper_axe.json │ │ ├── copper_chestplate.json │ │ ├── copper_helmet.json │ │ ├── copper_leggings.json │ │ ├── copper_pickaxe.json │ │ ├── copper_sword.json │ │ ├── crafting_table.json │ │ ├── cross_bow.json │ │ ├── dark_oak_plank.json │ │ ├── dark_shadow_ingot.json │ │ ├── daylight_sensor.json │ │ ├── daylight_sensor_inverted.json │ │ ├── diamond.json │ │ ├── diamond_axe.json │ │ ├── diamond_chestplate.json │ │ ├── diamond_helmet.json │ │ ├── diamond_ingot.json │ │ ├── diamond_leggings.json │ │ ├── diamond_pickaxe.json │ │ ├── diamond_sword.json │ │ ├── diorite.json │ │ ├── diorite_polished.json │ │ ├── dirt.json │ │ ├── door_nether.json │ │ ├── dried_kelp.json │ │ ├── dried_kelp_block.json │ │ ├── dungeon_eater.json │ │ ├── dye_black.json │ │ ├── dye_blue.json │ │ ├── dye_brown.json │ │ ├── dye_cyan.json │ │ ├── dye_cyan_2.json │ │ ├── dye_gray.json │ │ ├── dye_light_blue.json │ │ ├── dye_light_blue_2.json │ │ ├── dye_light_blue_3.json │ │ ├── dye_light_gray.json │ │ ├── dye_light_gray_2.json │ │ ├── dye_light_gray_3.json │ │ ├── dye_light_gray_4.json │ │ ├── dye_lime.json │ │ ├── dye_lime_2.json │ │ ├── dye_magenta.json │ │ ├── dye_magenta_2.json │ │ ├── dye_magenta_3.json │ │ ├── dye_magenta_4.json │ │ ├── dye_magenta_5.json │ │ ├── dye_orange.json │ │ ├── dye_orange_2.json │ │ ├── dye_pink.json │ │ ├── dye_pink_2.json │ │ ├── dye_pink_3.json │ │ ├── dye_pink_4.json │ │ ├── dye_purple.json │ │ ├── dye_purple_2.json │ │ ├── dye_red.json │ │ ├── dye_red_2.json │ │ ├── dye_red_3.json │ │ ├── dye_white.json │ │ ├── dye_yellow.json │ │ ├── dye_yellow_2.json │ │ ├── emerald.json │ │ ├── enchantment_table.json │ │ ├── end_rod.json │ │ ├── end_stone_brick.json │ │ ├── ender_chest.json │ │ ├── ender_eye.json │ │ ├── ender_mirror.json │ │ ├── farmland.json │ │ ├── farmland_2.json │ │ ├── fence_acacia.json │ │ ├── fence_birch.json │ │ ├── fence_dark_oak.json │ │ ├── fence_jungle.json │ │ ├── fence_nether.json │ │ ├── fence_oak.json │ │ ├── fence_palm.json │ │ ├── fence_spruce.json │ │ ├── fence_tainted.json │ │ ├── fence_volcano.json │ │ ├── fermented_spider_eye.json │ │ ├── fire_boomerang.json │ │ ├── fire_boomerang_2.json │ │ ├── fire_bullet.json │ │ ├── fire_bullet_2.json │ │ ├── fire_charge.json │ │ ├── fire_charge_2.json │ │ ├── fire_lamp.json │ │ ├── flesh_chestplate.json │ │ ├── flesh_helmet.json │ │ ├── flesh_ingot.json │ │ ├── flesh_leggings.json │ │ ├── flesh_machine_part.json │ │ ├── flower_pot.json │ │ ├── flower_pot_large.json │ │ ├── furnace.json │ │ ├── ghost.json │ │ ├── glass_bottle.json │ │ ├── glistering_melon_slice.json │ │ ├── glow_ball.json │ │ ├── glow_bomb.json │ │ ├── glowing_mushroom.json │ │ ├── glowing_mushroom_2.json │ │ ├── glowstone.json │ │ ├── gold_ingot.json │ │ ├── gold_ingot_2.json │ │ ├── gold_nugget.json │ │ ├── golden_apple.json │ │ ├── golden_axe.json │ │ ├── golden_carrot.json │ │ ├── golden_chestplate.json │ │ ├── golden_helmet.json │ │ ├── golden_leggings.json │ │ ├── golden_pickaxe.json │ │ ├── golden_pressure_plate.json │ │ ├── golden_sword.json │ │ ├── granite.json │ │ ├── granite_polished.json │ │ ├── grass_axe.json │ │ ├── grass_pickaxe.json │ │ ├── grass_sword.json │ │ ├── green_torch.json │ │ ├── green_wire.json │ │ ├── grenade.json │ │ ├── grenade_2.json │ │ ├── hay_bale.json │ │ ├── ice_arrow.json │ │ ├── ice_bow.json │ │ ├── ice_brick.json │ │ ├── ice_element_ball.json │ │ ├── ice_packed.json │ │ ├── ice_staff.json │ │ ├── iron_axe.json │ │ ├── iron_bar.json │ │ ├── iron_bullet.json │ │ ├── iron_bullet_2.json │ │ ├── iron_chestplate.json │ │ ├── iron_door.json │ │ ├── iron_helmet.json │ │ ├── iron_ingot.json │ │ ├── iron_ingot_2.json │ │ ├── iron_leggings.json │ │ ├── iron_nugget.json │ │ ├── iron_pickaxe.json │ │ ├── iron_pressure_plate.json │ │ ├── iron_sword.json │ │ ├── jack_o_lantern.json │ │ ├── jukebox.json │ │ ├── jungle_plank.json │ │ ├── knight_chestplate.json │ │ ├── knight_helmet.json │ │ ├── knight_leggings.json │ │ ├── lantern.json │ │ ├── lapis_lazuli.json │ │ ├── lava_chestplate.json │ │ ├── lava_helmet.json │ │ ├── lava_leggings.json │ │ ├── lead_axe.json │ │ ├── lead_chestplate.json │ │ ├── lead_helmet.json │ │ ├── lead_leggings.json │ │ ├── lead_pickaxe.json │ │ ├── lead_sword.json │ │ ├── leather.json │ │ ├── leather_chestplate.json │ │ ├── leather_helmet.json │ │ ├── leather_leggings.json │ │ ├── lever.json │ │ ├── lighter.json │ │ ├── lighting_arrow.json │ │ ├── lighting_bow.json │ │ ├── lighting_staff.json │ │ ├── machine_part.json │ │ ├── magic_cell_group.json │ │ ├── magic_gold_chestplate.json │ │ ├── magic_gold_helmet.json │ │ ├── magic_gold_leggings.json │ │ ├── magic_silver_chestplate.json │ │ ├── magic_silver_helmet.json │ │ ├── magic_silver_ingot.json │ │ ├── magic_silver_leggings.json │ │ ├── magma_block.json │ │ ├── magma_cream.json │ │ ├── magma_gold_ingot.json │ │ ├── melon_seed.json │ │ ├── mossy_cobblestone_fence.json │ │ ├── mushroom_stew.json │ │ ├── nether_brick_block.json │ │ ├── nether_chest.json │ │ ├── nether_lamp.json │ │ ├── netherite_ingot.json │ │ ├── netherite_ingot_2.json │ │ ├── oak_plank.json │ │ ├── painting_2x2.json │ │ ├── painting_2x2_2.json │ │ ├── painting_2x4.json │ │ ├── painting_4x2.json │ │ ├── painting_4x4.json │ │ ├── painting_8x4.json │ │ ├── painting_8x6.json │ │ ├── painting_8x8.json │ │ ├── palm_plank.json │ │ ├── paper.json │ │ ├── platform_acacia.json │ │ ├── platform_birch.json │ │ ├── platform_dark_oak.json │ │ ├── platform_end_stone.json │ │ ├── platform_jungle.json │ │ ├── platform_nether_brick.json │ │ ├── platform_oak.json │ │ ├── platform_palm.json │ │ ├── platform_prismarine.json │ │ ├── platform_prismarine_dark.json │ │ ├── platform_purpur.json │ │ ├── platform_quartz.json │ │ ├── platform_red_sand_stone.json │ │ ├── platform_sandstone.json │ │ ├── platform_spruce.json │ │ ├── platform_stone_brick.json │ │ ├── platform_tainted.json │ │ ├── platform_volcano.json │ │ ├── poison_mushroom.json │ │ ├── prismarine.json │ │ ├── prismarine_brick.json │ │ ├── prismarine_dark.json │ │ ├── prismarine_dark_2.json │ │ ├── pumpkin_helmet.json │ │ ├── pumpkin_pie.json │ │ ├── pumpkin_seed.json │ │ ├── purpur_block.json │ │ ├── quartz.json │ │ ├── red_gold_ingot.json │ │ ├── red_mushroom.json │ │ ├── red_mushroom_2.json │ │ ├── red_nether_brick.json │ │ ├── red_sand_carved.json │ │ ├── red_sand_stone.json │ │ ├── red_torch.json │ │ ├── red_wire.json │ │ ├── redstone.json │ │ ├── redstone_lamp.json │ │ ├── redstone_torch.json │ │ ├── rocket.json │ │ ├── rocket_boost.json │ │ ├── rotten_flesh.json │ │ ├── sandstone.json │ │ ├── sandstone_carved.json │ │ ├── sea_lantern.json │ │ ├── shadow_staff.json │ │ ├── shears.json │ │ ├── shot_bow.json │ │ ├── shot_bow_2.json │ │ ├── shulker_box.json │ │ ├── sign.json │ │ ├── silver_axe.json │ │ ├── silver_bullet.json │ │ ├── silver_chestplate.json │ │ ├── silver_helmet.json │ │ ├── silver_leggings.json │ │ ├── silver_pickaxe.json │ │ ├── silver_sword.json │ │ ├── slime_block.json │ │ ├── slimeball.json │ │ ├── snow.json │ │ ├── snow_brick.json │ │ ├── snowball.json │ │ ├── spruce_plank.json │ │ ├── stained_glass_black.json │ │ ├── stained_glass_blue.json │ │ ├── stained_glass_brown.json │ │ ├── stained_glass_cyan.json │ │ ├── stained_glass_gray.json │ │ ├── stained_glass_green.json │ │ ├── stained_glass_light_blue.json │ │ ├── stained_glass_light_gray.json │ │ ├── stained_glass_lime.json │ │ ├── stained_glass_magenta.json │ │ ├── stained_glass_orange.json │ │ ├── stained_glass_pink.json │ │ ├── stained_glass_purple.json │ │ ├── stained_glass_red.json │ │ ├── stained_glass_white.json │ │ ├── stained_glass_yellow.json │ │ ├── star_arrow.json │ │ ├── star_chestplate.json │ │ ├── star_helmet.json │ │ ├── star_leggings.json │ │ ├── steel_axe.json │ │ ├── steel_chestplate.json │ │ ├── steel_helmet.json │ │ ├── steel_leggings.json │ │ ├── steel_pickaxe.json │ │ ├── steel_sword.json │ │ ├── stick.json │ │ ├── stone.json │ │ ├── stone_2.json │ │ ├── stone_axe.json │ │ ├── stone_brick.json │ │ ├── stone_brick_carved.json │ │ ├── stone_brick_mossy.json │ │ ├── stone_button.json │ │ ├── stone_chest.json │ │ ├── stone_hoe.json │ │ ├── stone_pickaxe.json │ │ ├── stone_pressure_plate.json │ │ ├── stone_sword.json │ │ ├── strange_eye.json │ │ ├── string.json │ │ ├── suger.json │ │ ├── super_bronze_sword.json │ │ ├── super_copper_sword.json │ │ ├── super_cross_bow.json │ │ ├── super_diamond_chestplate.json │ │ ├── super_diamond_helmet.json │ │ ├── super_diamond_leggings.json │ │ ├── super_diamond_sword.json │ │ ├── super_golden_sword.json │ │ ├── super_iron_sword.json │ │ ├── super_lead_sword.json │ │ ├── super_silver_sword.json │ │ ├── super_steel_sword.json │ │ ├── super_tin_sword.json │ │ ├── sword_arrow.json │ │ ├── sword_arrow_2.json │ │ ├── sword_arrow_3.json │ │ ├── table_acacia.json │ │ ├── table_birch.json │ │ ├── table_dark_oak.json │ │ ├── table_jungle.json │ │ ├── table_nether.json │ │ ├── table_oak.json │ │ ├── table_palm.json │ │ ├── table_spruce.json │ │ ├── table_tainted.json │ │ ├── table_volcano.json │ │ ├── tainted_plank.json │ │ ├── terracotta_black.json │ │ ├── terracotta_black_2.json │ │ ├── terracotta_blue.json │ │ ├── terracotta_blue_2.json │ │ ├── terracotta_brown.json │ │ ├── terracotta_cyan.json │ │ ├── terracotta_gray.json │ │ ├── terracotta_green.json │ │ ├── terracotta_light_blue.json │ │ ├── terracotta_light_gray.json │ │ ├── terracotta_lime.json │ │ ├── terracotta_magenta.json │ │ ├── terracotta_orange.json │ │ ├── terracotta_pink.json │ │ ├── terracotta_purple.json │ │ ├── terracotta_red.json │ │ ├── terracotta_white.json │ │ ├── terracotta_white_2.json │ │ ├── terracotta_yellow.json │ │ ├── tin_axe.json │ │ ├── tin_chestplate.json │ │ ├── tin_helmet.json │ │ ├── tin_leggings.json │ │ ├── tin_pickaxe.json │ │ ├── tin_sword.json │ │ ├── tnt.json │ │ ├── tnt_2.json │ │ ├── torch.json │ │ ├── torch_2.json │ │ ├── torch_3.json │ │ ├── tower_core.json │ │ ├── trapped_chest.json │ │ ├── volcano_plank.json │ │ ├── water_staff.json │ │ ├── watermelon.json │ │ ├── wheat.json │ │ ├── white_torch.json │ │ ├── wire_cutter.json │ │ ├── wooden_arrow.json │ │ ├── wooden_arrow_2.json │ │ ├── wooden_arrow_3.json │ │ ├── wooden_arrow_4.json │ │ ├── wooden_axe.json │ │ ├── wooden_bed_black.json │ │ ├── wooden_bed_black_2.json │ │ ├── wooden_bed_blue.json │ │ ├── wooden_bed_blue_2.json │ │ ├── wooden_bed_brown.json │ │ ├── wooden_bed_brown_2.json │ │ ├── wooden_bed_cyan.json │ │ ├── wooden_bed_cyan_2.json │ │ ├── wooden_bed_gray.json │ │ ├── wooden_bed_gray_2.json │ │ ├── wooden_bed_green.json │ │ ├── wooden_bed_green_2.json │ │ ├── wooden_bed_light_blue.json │ │ ├── wooden_bed_light_blue_2.json │ │ ├── wooden_bed_light_gray.json │ │ ├── wooden_bed_light_gray_2.json │ │ ├── wooden_bed_lime.json │ │ ├── wooden_bed_lime_2.json │ │ ├── wooden_bed_magenta.json │ │ ├── wooden_bed_magenta_2.json │ │ ├── wooden_bed_orange.json │ │ ├── wooden_bed_orange_2.json │ │ ├── wooden_bed_pink.json │ │ ├── wooden_bed_pink_2.json │ │ ├── wooden_bed_purple.json │ │ ├── wooden_bed_purple_2.json │ │ ├── wooden_bed_red.json │ │ ├── wooden_bed_red_2.json │ │ ├── wooden_bed_white.json │ │ ├── wooden_bed_yellow.json │ │ ├── wooden_bed_yellow_2.json │ │ ├── wooden_boomerang.json │ │ ├── wooden_bow.json │ │ ├── wooden_button.json │ │ ├── wooden_door_acacia.json │ │ ├── wooden_door_birch.json │ │ ├── wooden_door_dark_oak.json │ │ ├── wooden_door_jungle.json │ │ ├── wooden_door_oak.json │ │ ├── wooden_door_palm.json │ │ ├── wooden_door_spruce.json │ │ ├── wooden_door_tainted.json │ │ ├── wooden_door_volcano.json │ │ ├── wooden_hoe.json │ │ ├── wooden_pickaxe.json │ │ ├── wooden_pressure_plate.json │ │ ├── wooden_sword.json │ │ ├── wool_black.json │ │ ├── wool_black_2.json │ │ ├── wool_blue.json │ │ ├── wool_blue_2.json │ │ ├── wool_brown.json │ │ ├── wool_cyan.json │ │ ├── wool_gray.json │ │ ├── wool_green.json │ │ ├── wool_light_blue.json │ │ ├── wool_light_gray.json │ │ ├── wool_lime.json │ │ ├── wool_magenta.json │ │ ├── wool_orange.json │ │ ├── wool_pink.json │ │ ├── wool_purple.json │ │ ├── wool_red.json │ │ ├── wool_white.json │ │ ├── wool_yellow.json │ │ ├── yellow_torch.json │ │ └── yellow_wire.json │ ├── repair/ │ │ ├── ancient_chestplate.json │ │ ├── ancient_chestplate_2.json │ │ ├── ancient_helmet.json │ │ ├── ancient_helmet_2.json │ │ ├── ancient_leggings.json │ │ ├── ancient_leggings_2.json │ │ ├── bronze_axe.json │ │ ├── bronze_chestplate.json │ │ ├── bronze_helmet.json │ │ ├── bronze_leggings.json │ │ ├── bronze_pickaxe.json │ │ ├── bronze_sword.json │ │ ├── copper_axe.json │ │ ├── copper_chestplate.json │ │ ├── copper_helmet.json │ │ ├── copper_leggings.json │ │ ├── copper_pickaxe.json │ │ ├── copper_sword.json │ │ ├── diamond_axe.json │ │ ├── diamond_chestplate.json │ │ ├── diamond_helmet.json │ │ ├── diamond_leggings.json │ │ ├── diamond_pickaxe.json │ │ ├── diamond_sword.json │ │ ├── golden_axe.json │ │ ├── golden_chestplate.json │ │ ├── golden_helmet.json │ │ ├── golden_leggings.json │ │ ├── golden_pickaxe.json │ │ ├── golden_sword.json │ │ ├── iron_axe.json │ │ ├── iron_chestplate.json │ │ ├── iron_helmet.json │ │ ├── iron_leggings.json │ │ ├── iron_pickaxe.json │ │ ├── iron_sword.json │ │ ├── lead_axe.json │ │ ├── lead_chestplate.json │ │ ├── lead_helmet.json │ │ ├── lead_leggings.json │ │ ├── lead_pickaxe.json │ │ ├── lead_sword.json │ │ ├── leather_chestplate.json │ │ ├── leather_helmet.json │ │ ├── leather_leggings.json │ │ ├── nether_axe.json │ │ ├── nether_axe_2.json │ │ ├── nether_chestplate.json │ │ ├── nether_chestplate_2.json │ │ ├── nether_helmet.json │ │ ├── nether_helmet_2.json │ │ ├── nether_helmet_3.json │ │ ├── nether_leggings.json │ │ ├── nether_leggings_2.json │ │ ├── nether_pickaxe.json │ │ ├── nether_pickaxe_2.json │ │ ├── nether_sword.json │ │ ├── nether_sword_2.json │ │ ├── silver_axe.json │ │ ├── silver_chestplate.json │ │ ├── silver_helmet.json │ │ ├── silver_leggings.json │ │ ├── silver_pickaxe.json │ │ ├── silver_sword.json │ │ ├── steel_axe.json │ │ ├── steel_chestplate.json │ │ ├── steel_helmet.json │ │ ├── steel_leggings.json │ │ ├── steel_pickaxe.json │ │ ├── steel_sword.json │ │ ├── stone_axe.json │ │ ├── stone_hoe.json │ │ ├── stone_pickaxe.json │ │ ├── stone_sword.json │ │ ├── super_bronze_sword.json │ │ ├── super_copper_sword.json │ │ ├── super_diamond_sword.json │ │ ├── super_golden_sword.json │ │ ├── super_iron_sword.json │ │ ├── super_lead_sword.json │ │ ├── super_nether_sword.json │ │ ├── super_nether_sword_2.json │ │ ├── super_silver_sword.json │ │ ├── super_steel_sword.json │ │ ├── super_tin_sword.json │ │ ├── tin_axe.json │ │ ├── tin_chestplate.json │ │ ├── tin_helmet.json │ │ ├── tin_leggings.json │ │ ├── tin_pickaxe.json │ │ └── tin_sword.json │ └── smelt/ │ ├── baked_potato.json │ ├── charcoal.json │ ├── charcoal_10.json │ ├── charcoal_11.json │ ├── charcoal_12.json │ ├── charcoal_13.json │ ├── charcoal_14.json │ ├── charcoal_15.json │ ├── charcoal_16.json │ ├── charcoal_17.json │ ├── charcoal_18.json │ ├── charcoal_2.json │ ├── charcoal_3.json │ ├── charcoal_4.json │ ├── charcoal_5.json │ ├── charcoal_6.json │ ├── charcoal_7.json │ ├── charcoal_8.json │ ├── charcoal_9.json │ ├── coal.json │ ├── cooked_chicken.json │ ├── cooked_cod.json │ ├── cooked_mutton.json │ ├── cooked_porkchop.json │ ├── cooked_rabbit.json │ ├── cooked_salmon.json │ ├── copper_ingot.json │ ├── diamond.json │ ├── dried_kelp.json │ ├── dye_green.json │ ├── emerald.json │ ├── glass.json │ ├── glass_2.json │ ├── glass_3.json │ ├── gold_ingot.json │ ├── iron_ingot.json │ ├── lapis_lazuli.json │ ├── lead_ingot.json │ ├── nether_brick.json │ ├── netherite_scrap.json │ ├── popped_chorus_fruits.json │ ├── quartz.json │ ├── red_brick.json │ ├── red_sand_smooth.json │ ├── redstone.json │ ├── sandstone_smooth.json │ ├── silver_ingot.json │ ├── sponge.json │ ├── steak.json │ ├── steel_ingot.json │ ├── stone.json │ ├── stone_brick_cracked.json │ ├── terracotta_pink.json │ └── tin_ingot.json ├── record/ │ └── RecordData.lua ├── settings/ │ ├── Settings.lua │ └── SettingsData.lua ├── skins/ │ ├── skin_22.json │ ├── skin_33.json │ ├── skin_my.json │ ├── skin_plin.json │ ├── skin_redust.json │ ├── skin_steve.json │ ├── skin_ym.json │ ├── skin_yy.json │ ├── skin_zk.json │ ├── xqz/ │ │ ├── cloth.mdp │ │ └── hair.mdp │ └── xqz.json ├── sounds/ │ ├── README.txt │ ├── affectionate_scream.ogg │ ├── anvil_land.ogg │ ├── anvil_use.ogg │ ├── attack1.ogg │ ├── attack2.ogg │ ├── barrel_open.ogg │ ├── bat_death.ogg │ ├── bat_hurt1.ogg │ ├── bat_hurt2.ogg │ ├── bat_hurt3.ogg │ ├── bazooka_fire.ogg │ ├── blaze_death.ogg │ ├── blaze_hit1.ogg │ ├── blaze_hit2.ogg │ ├── blaze_hit3.ogg │ ├── bow.ogg │ ├── bowhit.ogg │ ├── bowhit2.ogg │ ├── broken.ogg │ ├── button1.ogg │ ├── cannon.ogg │ ├── cat_hit1.ogg │ ├── cat_hit2.ogg │ ├── cat_hit3.ogg │ ├── cat_meow1.ogg │ ├── cat_meow2.ogg │ ├── cat_meow3.ogg │ ├── chain_gun_fire.ogg │ ├── chest.ogg │ ├── chestclosed.ogg │ ├── chicken_hurt1.ogg │ ├── chicken_hurt2.ogg │ ├── chicken_say1.ogg │ ├── chicken_say2.ogg │ ├── chicken_say3.ogg │ ├── click.ogg │ ├── cloth1.ogg │ ├── cloth2.ogg │ ├── cloth3.ogg │ ├── cow_hurt1.ogg │ ├── cow_hurt2.ogg │ ├── cow_hurt3.ogg │ ├── cow_say1.ogg │ ├── cow_say2.ogg │ ├── cow_say3.ogg │ ├── creeper1.ogg │ ├── creeper2.ogg │ ├── creeper3.ogg │ ├── creeper_death.ogg │ ├── dirt1.ogg │ ├── dirt2.ogg │ ├── dirt3.ogg │ ├── dolphin_death.ogg │ ├── dolphin_hurt1.ogg │ ├── dolphin_hurt2.ogg │ ├── dolphin_hurt3.ogg │ ├── dolphin_play1.ogg │ ├── dolphin_play2.ogg │ ├── door1.ogg │ ├── door2.ogg │ ├── drink.ogg │ ├── eat1.ogg │ ├── eat2.ogg │ ├── eat3.ogg │ ├── enchant1.ogg │ ├── enchant2.ogg │ ├── enchant3.ogg │ ├── enderman_death.ogg │ ├── enderman_hit1.ogg │ ├── enderman_hit2.ogg │ ├── enderman_hit3.ogg │ ├── enderman_idle1.ogg │ ├── enderman_idle2.ogg │ ├── enderman_idle3.ogg │ ├── explode1.ogg │ ├── explode2.ogg │ ├── explode3.ogg │ ├── explode4.ogg │ ├── female_hit1.ogg │ ├── female_hit2.ogg │ ├── female_hit3.ogg │ ├── fireball.ogg │ ├── fireball2.ogg │ ├── fizz.ogg │ ├── fuse.ogg │ ├── ghast_charge.ogg │ ├── ghast_death.ogg │ ├── ghast_moan1.ogg │ ├── ghast_moan2.ogg │ ├── ghast_moan3.ogg │ ├── ghast_moan4.ogg │ ├── glass1.ogg │ ├── glass2.ogg │ ├── glass3.ogg │ ├── gore1.ogg │ ├── gore2.ogg │ ├── gore3.ogg │ ├── grass.ogg │ ├── grass1.ogg │ ├── grass2.ogg │ ├── grass3.ogg │ ├── grenade_fire.ogg │ ├── hit1.ogg │ ├── hit2.ogg │ ├── hit3.ogg │ ├── laser.ogg │ ├── launch.ogg │ ├── lavapop.ogg │ ├── levelup.ogg │ ├── monster.ogg │ ├── orb.ogg │ ├── phantom_death.ogg │ ├── phantom_hurt1.ogg │ ├── phantom_hurt2.ogg │ ├── phantom_hurt3.ogg │ ├── pig_death.ogg │ ├── pig_say1.ogg │ ├── pig_say2.ogg │ ├── pig_say3.ogg │ ├── pistol_fire.ogg │ ├── pop.ogg │ ├── portal.ogg │ ├── portal2.ogg │ ├── pufferfish_blow_out.ogg │ ├── pufferfish_blow_up.ogg │ ├── pufferfish_death.ogg │ ├── pufferfish_hurt1.ogg │ ├── pufferfish_hurt2.ogg │ ├── rabbit_hurt1.ogg │ ├── rabbit_hurt2.ogg │ ├── rabbit_hurt3.ogg │ ├── rain1.ogg │ ├── rain2.ogg │ ├── rain3.ogg │ ├── rain4.ogg │ ├── rifle_fire.ogg │ ├── sand1.ogg │ ├── sand2.ogg │ ├── sand3.ogg │ ├── shatter.ogg │ ├── shatter1.ogg │ ├── shatter2.ogg │ ├── shatter3.ogg │ ├── shear.ogg │ ├── sheep_say1.ogg │ ├── sheep_say2.ogg │ ├── sheep_say3.ogg │ ├── shotgun_fire.ogg │ ├── shulker_ambient1.ogg │ ├── shulker_box_open.ogg │ ├── shulker_close.ogg │ ├── shulker_death.ogg │ ├── shulker_hit1.ogg │ ├── shulker_hit2.ogg │ ├── shulker_hit3.ogg │ ├── shulker_hurt1.ogg │ ├── shulker_hurt2.ogg │ ├── shulker_hurt3.ogg │ ├── shulker_open.ogg │ ├── shulker_shoot.ogg │ ├── skeleton1.ogg │ ├── skeleton2.ogg │ ├── skeleton3.ogg │ ├── skeleton_death.ogg │ ├── slime_attack1.ogg │ ├── slime_attack2.ogg │ ├── snow1.ogg │ ├── snow2.ogg │ ├── snow3.ogg │ ├── spider_death.ogg │ ├── spider_say1.ogg │ ├── spider_say2.ogg │ ├── spider_say3.ogg │ ├── splash.ogg │ ├── step_cloth.ogg │ ├── step_grass1.ogg │ ├── step_grass2.ogg │ ├── step_grass3.ogg │ ├── step_grass4.ogg │ ├── step_grass5.ogg │ ├── step_grass6.ogg │ ├── step_ladder.ogg │ ├── step_sand.ogg │ ├── step_snow1.ogg │ ├── step_snow2.ogg │ ├── step_snow3.ogg │ ├── step_snow4.ogg │ ├── step_stone1.ogg │ ├── step_stone2.ogg │ ├── step_stone3.ogg │ ├── step_stone4.ogg │ ├── step_stone5.ogg │ ├── step_stone6.ogg │ ├── step_wood1.ogg │ ├── step_wood2.ogg │ ├── step_wood3.ogg │ ├── step_wood4.ogg │ ├── step_wood5.ogg │ ├── step_wood6.ogg │ ├── stone1.ogg │ ├── stone2.ogg │ ├── stone3.ogg │ ├── strip1.ogg │ ├── strip2.ogg │ ├── strip3.ogg │ ├── strip4.ogg │ ├── swim1.ogg │ ├── swim2.ogg │ ├── swim3.ogg │ ├── swim4.ogg │ ├── sys3.ogg │ ├── system1.ogg │ ├── system2.ogg │ ├── thorns_hit1.ogg │ ├── thorns_hit2.ogg │ ├── thorns_hit3.ogg │ ├── thorns_hit4.ogg │ ├── thunder1.ogg │ ├── thunder2.ogg │ ├── thunder3.ogg │ ├── tink1.ogg │ ├── tink2.ogg │ ├── tink3.ogg │ ├── travel.ogg │ ├── trigger.ogg │ ├── turtle_death.ogg │ ├── turtle_hurt1.ogg │ ├── turtle_hurt2.ogg │ ├── turtle_hurt3.ogg │ ├── villager_death.ogg │ ├── villager_hit1.ogg │ ├── villager_hit2.ogg │ ├── villager_hit3.ogg │ ├── villager_say1.ogg │ ├── villager_say2.ogg │ ├── villager_say3.ogg │ ├── wand1.ogg │ ├── wand2.ogg │ ├── wand3.ogg │ ├── wandfail.ogg │ ├── weapon.ogg │ ├── wolf_bark1.ogg │ ├── wolf_bark2.ogg │ ├── wolf_bark3.ogg │ ├── wolf_death.ogg │ ├── wolf_hurt1.ogg │ ├── wolf_hurt2.ogg │ ├── wolf_hurt3.ogg │ ├── wood1.ogg │ ├── wood2.ogg │ ├── wood3.ogg │ ├── zombie_death.ogg │ ├── zombie_hurt1.ogg │ ├── zombie_hurt2.ogg │ ├── zombie_say1.ogg │ ├── zombie_say2.ogg │ ├── zombie_say3.ogg │ ├── zpig1.ogg │ ├── zpig2.ogg │ ├── zpig3.ogg │ ├── zpigdeath.ogg │ ├── zpighurt1.ogg │ └── zpighurt2.ogg ├── spawns/ │ ├── aurora_palace.json │ ├── end_outpost.json │ └── monument_ocean.json ├── textures/ │ └── backgrounds/ │ └── atlas_config.json ├── trees/ │ ├── acacia/ │ │ └── acacia.json │ ├── bare_oak/ │ │ └── bare_oak.json │ ├── birch/ │ │ ├── birch.json │ │ └── leaf.mdp │ ├── blue_mushroom/ │ │ └── blue_mushroom.json │ ├── cactus/ │ │ └── cactus.json │ ├── dark_oak/ │ │ └── dark_oak.json │ ├── jungle/ │ │ └── jungle.json │ ├── oak/ │ │ ├── leaf.mdp │ │ └── oak.json │ ├── palm/ │ │ └── palm.json │ ├── spruce/ │ │ └── spruce.json │ ├── tainted/ │ │ └── tainted.json │ └── volcano_oak/ │ └── volcano_oak.json ├── ui/ │ ├── ContainerHelper.lua │ ├── DeathUI.lua │ ├── GuiID.lua │ ├── GuiLoader.lua │ ├── GuiLoaderProxy.lua │ ├── HotkeyUIHelper.lua │ ├── InfoPopupUI.lua │ ├── LanguageUI.lua │ ├── ModListUI.lua │ ├── MouseItemData.lua │ ├── NewPlayerUI.lua │ ├── NewServerUI.lua │ ├── NewWorldUI.lua │ ├── OptionUI.lua │ ├── PendingUI.lua │ ├── PlayerListUI.lua │ ├── RawHotkeyUIHelper.lua │ ├── ServerListUI.lua │ ├── SettingUI.lua │ ├── StartUI.lua │ ├── TipUI.lua │ ├── TipsOfTheDay.lua │ ├── UIDefault.lua │ ├── UIDesign.lua │ ├── UILayerDefine.lua │ ├── UIManager.lua │ ├── UISlotOp.lua │ ├── UISpritePool.lua │ ├── UIUtil.lua │ ├── UIWindow.lua │ ├── WorldListUI.lua │ ├── advancement/ │ │ ├── AdvancementContainerClient.lua │ │ ├── AdvancementTree.lua │ │ ├── AdvancementUI.lua │ │ └── AdvancementUIData.lua │ ├── backpack/ │ │ ├── BackpackContainerClient.lua │ │ ├── BackpackContainerServer.lua │ │ ├── BackpackUI.lua │ │ └── BackpackUIData.lua │ ├── brewing/ │ │ ├── BrewingContainerClient.lua │ │ ├── BrewingContainerServer.lua │ │ ├── BrewingUI.lua │ │ └── BrewingUIData.lua │ ├── chest/ │ │ ├── Chest30ContainerClient.lua │ │ ├── Chest30ContainerServer.lua │ │ ├── Chest30UI.lua │ │ ├── ChestUIData.lua │ │ ├── EnderChest30ContainerServer.lua │ │ ├── EnderChest30UI.lua │ │ ├── IChestContainerClient.lua │ │ ├── IChestContainerServer.lua │ │ └── IChestUI.lua │ ├── craft3x/ │ │ ├── Craft3xContainerClient.lua │ │ ├── Craft3xContainerServer.lua │ │ ├── Craft3xHelper.lua │ │ ├── Craft3xUI.lua │ │ └── Craft3xUIData.lua │ ├── enchant/ │ │ ├── EnchantContainerClient.lua │ │ ├── EnchantContainerServer.lua │ │ ├── EnchantUI.lua │ │ └── EnchantUIData.lua │ ├── hud/ │ │ └── HudUI.lua │ ├── nei/ │ │ ├── NeiDataBrewing.lua │ │ ├── NeiDataCrafting.lua │ │ ├── NeiDataProxy.lua │ │ ├── NeiDataRepairing.lua │ │ ├── NeiDataSmelting.lua │ │ └── NeiUI.lua │ ├── recipe_book/ │ │ ├── RecipeBookServer.lua │ │ └── RecipeBookUI.lua │ ├── repair/ │ │ ├── RepairContainerClient.lua │ │ ├── RepairContainerServer.lua │ │ ├── RepairUI.lua │ │ └── RepairUIData.lua │ ├── shooter/ │ │ ├── IShooterContainerClient.lua │ │ ├── IShooterContainerServer.lua │ │ ├── IShooterUI.lua │ │ ├── Shooter9ContainerClient.lua │ │ ├── Shooter9ContainerServer.lua │ │ └── Shooter9UI.lua │ └── smelt/ │ ├── SmeltContainerClient.lua │ ├── SmeltContainerServer.lua │ ├── SmeltUI.lua │ └── SmeltUIData.lua ├── ui_res/ │ ├── advance_tip.json │ ├── advancement_cell.json │ ├── base.json │ ├── base2.json │ ├── base3.json │ ├── base_list_cell.json │ ├── base_list_cell_highlight.json │ ├── base_list_cell_highlight_2.json │ ├── black.json │ ├── button_disabled.json │ ├── button_highlight.json │ ├── button_normal.json │ ├── button_pressed.json │ ├── cell_empty.json │ ├── cell_empty_2.json │ ├── cell_empty_3.json │ ├── cell_empty_4.json │ ├── cell_normal.json │ ├── cell_selected.json │ ├── cell_selected_2.json │ ├── cell_selected_3.json │ ├── cell_selected_4.json │ ├── cursor.cur │ ├── round_rect_white.json │ ├── tab.json │ ├── tab_clicked.json │ ├── tipbox.json │ ├── white.json │ ├── white_circle.json │ └── window_frame_01.json ├── util/ │ ├── Algorithm.lua │ ├── DictUtil.lua │ ├── MiscHelper.lua │ ├── OrderedArray.lua │ ├── PhysicsUtil.lua │ ├── SnakeModel.lua │ ├── StringUtil.lua │ └── ValidChecker.lua ├── world/ │ ├── Portals.lua │ └── TCModWorldData.lua ├── world_gen/ │ ├── ChunkGenerator.lua │ ├── ModChunkGenerator.lua │ ├── SpecialTerrainProxies.lua │ ├── TerrainProxies.lua │ ├── TransitionProxies.lua │ └── WorldGenDefine.lua └── world_gen_init.lua ================================================ FILE CONTENTS ================================================ ================================================ FILE: DebugHelper.lua ================================================ local DebugHelper = class("DebugHelper") local DebugHelperConfig = require("DebugHelperConfig") local function PrintRecipe(rid) local s = "recipe: " local recipe = RecipeUtils.GetRecipe(rid) if recipe.configID == Reg.RecipeConfigID("Craft3x") then ---@param e RecipeInputSlot for i, e in each(recipe.inputs) do if e.type == RecipeInputSlotType.Item then s = s .. string.format("[%s(%d)]", e.itemStack:GetItem().idName, e.itemStack.stackSize) elseif e.type == RecipeInputSlotType.OreDictionary then s = s .. string.format("[%s(%d)]", Reg.OreDictionaryIDName(e.id), e.stackSize) else s = s .. "[]" end end s = s .. " -> " ---@param e Slot for i, e in each(recipe.outputs) do if e.hasStack then s = s .. string.format("[%s(%d)]", e:GetStack():GetItem().idName, e:GetStack().stackSize) else s = s .. "[]" end end print(s) end end function DebugHelper.RunDebug(player) if not DebugHelperConfig.Enable then return end if NetMode.current == NetMode.Server then DebugHelper.DebugNpc(player) DebugHelper.DebugDay() DebugHelper.DebugWeather() else DebugHelper.DebugFly(player) end end function DebugHelper.RunDebugStart(player) if not DebugHelperConfig.Enable then return end if NetMode.current == NetMode.Server then DebugHelper.DebugItemStart(player) end end ---@param player Player function DebugHelper.RunDebugProp(player) if not DebugHelperConfig.Enable then return end local propDebug = DebugHelperConfig.PropDebug if not propDebug.Enable then return end local TEST_ATTACK = propDebug.Attack local TEST_DEFENSE = propDebug.Defense player.baseAttack.attack = player.baseAttack.attack + TEST_ATTACK.attack player.baseAttack.knockBack = player.baseAttack.knockBack + TEST_ATTACK.knockBack player.baseAttack.crit = player.baseAttack.crit + TEST_ATTACK.crit player.baseDefense.defense = player.baseDefense.defense + TEST_DEFENSE.defense player.baseDefense.blastDefense = player.baseDefense.blastDefense + TEST_DEFENSE.blastDefense player.baseDefense.flameDefense = player.baseDefense.flameDefense + TEST_DEFENSE.flameDefense player.baseDefense.projectileDefense = player.baseDefense.projectileDefense + TEST_DEFENSE.projectileDefense player.baseDefense.breathDefense = player.baseDefense.breathDefense + TEST_DEFENSE.breathDefense player.baseDefense.fallDefense = player.baseDefense.fallDefense + TEST_DEFENSE.fallDefense player.baseDefense.knockBackDefense = player.baseDefense.knockBackDefense + TEST_DEFENSE.knockBackDefense if propDebug.FullFood then player.foodLevel = 100 player.foodSaturationLevel = 100 end end local s_tmpTickFly = 0 function DebugHelper.DebugFly(player) local flyDebug = DebugHelperConfig.FlyDebug if s_tmpTickFly == nil then s_tmpTickFly = 0 end s_tmpTickFly = s_tmpTickFly + 1 if s_tmpTickFly >= 60 and Input.keyboard:isKeyPressed(flyDebug.HotKey) then s_tmpTickFly = 0 local g = require("player.GPlayer").GetInstance(player) g.observeMode = not g.observeMode end end function DebugHelper.DebugDay() local dayDebug = DebugHelperConfig.DayDebug if Input.keyboard:isKeyPressed(dayDebug.HotKeySub) then MiscUtils.SetDayTime(MiscUtils.GetDayTime() - dayDebug.SubTime) elseif Input.keyboard:isKeyPressed(dayDebug.HotKeyAdd) then MiscUtils.SetDayTime(MiscUtils.GetDayTime() + dayDebug.AddTime) end end function DebugHelper.DebugWeather() local weaDebug = DebugHelperConfig.WeatherDebug if Input.keyboard:isKeyPressed(weaDebug.HotKeySub) then MiscUtils.SetWeatherTime(MiscUtils.GetWeatherTime() - weaDebug.SubTime) elseif Input.keyboard:isKeyPressed(weaDebug.HotKeyAdd) then MiscUtils.SetWeatherTime(MiscUtils.GetWeatherTime() + weaDebug.AddTime) end end local s_tmpTickNpc = 0 function DebugHelper.DebugNpc(player) if s_tmpTickNpc == nil then s_tmpTickNpc = 0 end s_tmpTickNpc = s_tmpTickNpc + 1 local npcDebug = DebugHelperConfig.NpcDebug if s_tmpTickNpc > 30 and Input.keyboard:isKeyPressed(npcDebug.HotKey) then s_tmpTickNpc = 0 local cx = player.centerX - GameWindow.width / 2 + Input.mouse.position.x local cy = player.centerY - GameWindow.height / 2 + Input.mouse.position.y for i, idName in ipairs(npcDebug.GenList) do NpcUtils.Create(Reg.NpcID(idName), cx - i * 20, cy) end end end ---@param player Player function DebugHelper.DebugItemStart(player) local itemDebug = DebugHelperConfig.ItemDebug if not itemDebug.Enable then return end local items = itemDebug.StartItems for idx, data in ipairs(items) do local index = idx - 1 if idx < player.backpackInventory.slotCount then local slot = player.backpackInventory:GetSlot(index) slot:ClearStack() slot:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName(data[1]), data[2])) end end local equipments = itemDebug.StartEquipments for idx, data in ipairs(equipments) do if data then local index = idx - 1 if idx < player.equipmentInventory.slotCount then local slot = player.equipmentInventory:GetSlot(index) slot:ClearStack() slot:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName(data), 1)) end end end end return DebugHelper ================================================ FILE: DebugHelperConfig.lua ================================================ local DebugHelperConfig = { Enable = true, FlyDebug = { HotKey = Keys.P, }, DayDebug = { HotKeyAdd = Keys.X, HotKeySub = Keys.Z, AddTime = 500, SubTime = 500, }, WeatherDebug = { HotKeyAdd = Keys.C, HotKeySub = Keys.V, AddTime = 500, SubTime = 500, }, PropDebug = { Enable = true, Attack = { attack = 0, knockBack = 1, crit = 10, }, Defense = { defense = 18, blastDefense = 0, flameDefense = 0, projectileDefense = 0, breathDefense = 0, fallDefense = 0, knockBackDefense = 0, }, FullFood = true, }, EquipmentDebug = { Enable = true, Equipments = { --"i_hat_10", --"i_cloth_10", --"i_leg_10", } }, ItemDebug = { Enable = true, HotKey = Keys.B, StartEquipments = { "lava_helmet", "lava_chestplate", "lava_leggings", }, StartItems = { --{ "blue_shot_bow", 1 }, --{ "bone_gun", 1 }, --{ "curse_bow", 1 }, --{ "dark_staff", 1 }, --{ "fire_book", 1 }, --{ "fire_shooter", 1 }, --{ "fire_staff", 1 }, --{ "frosen_staff", 1 }, --{ "lava_sword", 1 }, --{ "mini_laser_gun", 1 }, { "tc:ender_mirror", 1 }, { "tc:blaze_rod", 11 }, { "tc:shotgun", 1 }, { "tc:shot_bow", 1 }, { "tc:brewing_stand", 111 }, { "tc:diamond_pickaxe", 1 }, { "tc:diamond_axe", 1 }, { "tc:diamond_sword", 1 }, { "tc:tower_core", 1 }, { "tc:boomerang", 1 }, { "td:energy_tower", 11 }, { "td:burn_tower", 15 }, { "potion_weakness", 111 }, { "wooden_arrow", 111 }, { "mini_laser_gun", 1 }, { "wooden_arrow", 111 }, { "ender_mirror", 1 }, { "strange_eye", 8 }, { "air_sword", 1 }, { "bread", 111 }, { "crafting_table", 2 }, { "blue_talisman", 1 }, { "gold_talisman", 1 }, { "heart_talisman", 1 }, { "lava_necklace", 1 }, { "lighting_talisman", 1 }, { "sword_fish", 1 }, { "sword_fish_gun", 1 }, { "water_book", 1 }, { "ice_bow", 1 }, { "blue_arrow", 11 }, { "iron_bullet", 411 }, }, Items = { { "iron_bullet", 21 }, }, }, NpcDebug = { HotKey = Keys.I, GenList = { --"shulker", --"skeleton", --"crison_eye", --"dungeon_eater_head", --"dungeon_slime", --"dungeon_knight", --"dungeon_soul", --"bone_officer", --"dead_mage", --"dark_mage", --"cursed_skull", --"dragon_skull", --"dungeon_creeper", --"evil", --"eye_guard", --"eye_guard_laser", --"flame_soul", --"fly_eye", --"fly_mouth", --"fly_skeleton", --"ghost_gunner", --"ghost_soul", --"giant_cursed_skull", --"grim_reaper", --"ragged_mage", --"red_mage", --"large_bat", --"mad_skeleton", --"mad_skeleton_armed", --"mad_skeleton_tall", --"mad_skeleton_tall_armed", --"mad_skeleton_tall_helmet_armed", --"skeleton_blue_armed", --"skeleton_blue_armed_masked", --"skeleton_blue_knight", --"skeleton_fire_armed", --"skeleton_fire_armed_swordsman", --"large_spider", --"mini_ghast", --"red_phantom", --"rock_man", --"rolling_fire_ball", --"skeleton_assaulter", --"skeleton_guard", --"undead_miner", --"vampire_miner", --"bone_officer", --"black_rabbit", --"guardian", --"skeleton", --"skeleton", --"creeper", --"snow_queen", } } } return DebugHelperConfig ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2022 skyblueyoshi 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. ================================================ FILE: README.md ================================================ # TerraCraft The TerraCraft official vanilla mod. ================================================ FILE: advancements/AdvancementTriggers.lua ================================================ ---@class TC.AdvancementTriggers local AdvancementTriggers = class("AdvancementProxies") local s_instance ---@return TC.AdvancementTriggers function AdvancementTriggers.getInstance() if s_instance == nil then s_instance = AdvancementTriggers.new() end return s_instance end function AdvancementTriggers:__init() self._itemTriggerProxies = {} self._oreDictionaryTriggerProxies = {} self._npcKillTriggerProxies = {} self._biomeTypeTriggerProxies = {} self._biomeTriggerProxies = {} end function AdvancementTriggers:TriggerEnterBiome(player, biomeID) local biomeData = BiomeUtils.GetData(biomeID) self:_TryTriggerProxy(player, self._biomeTriggerProxies[biomeID]) self:_TryTriggerProxy(player, self._biomeTypeTriggerProxies[biomeData.biomeType]) end ---TriggerGetItem ---@param player Player ---@param itemID int ---@param stackSize int function AdvancementTriggers:TriggerGetItem(player, itemID, stackSize) -- trigger by single item self:_TryTriggerProxy(player, self._itemTriggerProxies[itemID]) -- trigger by item ore dictionary local item = ItemRegistry.GetItemByID(itemID) for _, oreDictionaryID in each(item.oreDictionaryIDs) do self:_TryTriggerProxy(player, self._oreDictionaryTriggerProxies[oreDictionaryID]) end end ---TriggerKillNpc ---@param player Player ---@param npc Npc function AdvancementTriggers:TriggerKillNpc(player, npc) self:_TryTriggerProxy(player, self._npcKillTriggerProxies[npc.id]) end function AdvancementTriggers:_TryTriggerProxy(player, proxy) if proxy ~= nil then self:_TriggerAll(player, proxy) end end ---_TriggerAll ---@param player Player ---@param advancementIDs int[] function AdvancementTriggers:_TriggerAll(player, advancementIDs) for _, advancementID in ipairs(advancementIDs) do player:FinishAdvancement(advancementID) end end function AdvancementTriggers:_AddProxyAdvancement(triggerProxies, key, advancementIDName) local advancementID = Reg.AdvancementID(advancementIDName) if triggerProxies[key] == nil then triggerProxies[key] = {} end local exist = false for _, v in ipairs(triggerProxies[key]) do if v == advancementID then exist = true break end end if not exist then table.insert(triggerProxies[key], advancementID) end end function AdvancementTriggers:RegisterItemTrigger(advancementIDName, itemIDName) self:_AddProxyAdvancement(self._itemTriggerProxies, Reg.ItemID(itemIDName), advancementIDName) end function AdvancementTriggers:RegisterOreDictionaryTrigger(advancementIDName, oreDictionaryName) self:_AddProxyAdvancement(self._oreDictionaryTriggerProxies, Reg.OreDictionaryID(oreDictionaryName), advancementIDName) end function AdvancementTriggers:RegisterNpcKillTrigger(advancementIDName, npcIDName) self:_AddProxyAdvancement(self._npcKillTriggerProxies, Reg.NpcID(npcIDName), advancementIDName) end function AdvancementTriggers:RegisterBiomeTypeTrigger(advancementIDName, biomeTypeIDName) self:_AddProxyAdvancement(self._biomeTypeTriggerProxies, Reg.BiomeTypeID(biomeTypeIDName), advancementIDName) end function AdvancementTriggers:RegisterBiomeTrigger(advancementIDName, biomeIDName) self:_AddProxyAdvancement(self._biomeTriggerProxies, Reg.BiomeID(biomeIDName), advancementIDName) end function AdvancementTriggers:RegisterAll() self:RegisterItemTrigger("crafting_table", "crafting_table") self:RegisterItemTrigger("ender_chest", "ender_chest") self:RegisterItemTrigger("blaze_rod", "blaze_rod") self:RegisterItemTrigger("crafting_table", "crafting_table") self:RegisterItemTrigger("bow", "wooden_bow") self:RegisterItemTrigger("crossbow", "cross_bow") self:RegisterItemTrigger("crossbow", "shot_bow") self:RegisterItemTrigger("bread", "bread") self:RegisterItemTrigger("brew", "brewing_stand") self:RegisterItemTrigger("bronze", "bronze_ingot") self:RegisterItemTrigger("cake", "cake") self:RegisterItemTrigger("diamond", "diamond") self:RegisterItemTrigger("enchant", "enchantment_table") self:RegisterItemTrigger("ender_pearl", "ender_pearl") self:RegisterItemTrigger("furnace", "furnace") self:RegisterItemTrigger("lava", "bucket_lava") self:RegisterItemTrigger("leather", "leather") self:RegisterItemTrigger("mine", "wooden_pickaxe") self:RegisterItemTrigger("mine_up", "stone_pickaxe") self:RegisterItemTrigger("netherite", "ore_ancient_debris") self:RegisterItemTrigger("pumpkin_helmet", "pumpkin_helmet") self:RegisterItemTrigger("redstone", "redstone") self:RegisterItemTrigger("redstone_wire", "red_wire") self:RegisterItemTrigger("steel", "steel_ingot") self:RegisterItemTrigger("stone", "cobblestone") self:RegisterItemTrigger("strange_len", "strange_len") self:RegisterItemTrigger("rocket_boost", "rocket_boost") self:RegisterItemTrigger("mine_copper", "copper_pickaxe") self:RegisterItemTrigger("mine_copper", "tin_pickaxe") self:RegisterItemTrigger("mine_iron", "iron_pickaxe") self:RegisterItemTrigger("mine_iron", "lead_pickaxe") self:RegisterItemTrigger("mine_bronze", "bronze_pickaxe") self:RegisterItemTrigger("mine_bronze", "steel_pickaxe") self:RegisterItemTrigger("mine_gold", "golden_pickaxe") self:RegisterItemTrigger("mine_gold", "silver_pickaxe") self:RegisterItemTrigger("mine_diamond", "diamond_pickaxe") self:RegisterItemTrigger("mine_netherite", "nether_pickaxe") self:RegisterItemTrigger("repair", "anvil") self:RegisterItemTrigger("gold", "gold_ingot") self:RegisterItemTrigger("super_diamond_sword", "super_diamond_sword") self:RegisterItemTrigger("ghost_crystal", "ghost_crystal") self:RegisterItemTrigger("ghost", "ghost") self:RegisterItemTrigger("ice_element_ball", "ice_element_ball") self:RegisterItemTrigger("diamond_ingot", "diamond_ingot") self:RegisterItemTrigger("ancient_ingot", "ancient_ingot") self:RegisterItemTrigger("knight_ingot", "knight_ingot") self:RegisterItemTrigger("flesh_ingot", "flesh_ingot") self:RegisterItemTrigger("gun", "handgun") self:RegisterItemTrigger("gun", "rocket_launcher") self:RegisterItemTrigger("gun", "shotgun") self:RegisterItemTrigger("gun", "sniper") self:RegisterItemTrigger("gun", "rifle") self:RegisterItemTrigger("magic_limit", "mana_piece") self:RegisterOreDictionaryTrigger("wood", "OD_WOOD") self:RegisterOreDictionaryTrigger("farm", "OD_HOE") self:RegisterOreDictionaryTrigger("sword", "OD_SWORD") self:RegisterOreDictionaryTrigger("staff", "OD_STAFF") self:RegisterOreDictionaryTrigger("iron", "OD_IRON_INGOT") self:RegisterNpcKillTrigger("guardian", "guardian") self:RegisterNpcKillTrigger("ghast", "ghast") self:RegisterNpcKillTrigger("snow_guard", "snow_guardian") self:RegisterNpcKillTrigger("snow_guard", "snow_guardian_archer") self:RegisterBiomeTypeTrigger("nether", "Nether") self:RegisterBiomeTrigger("go_ghost_house", "more_dungeons:ghost_dungeon") self:RegisterBiomeTrigger("go_bone_dungeon", "more_dungeons:bone_dungeon") self:RegisterBiomeTrigger("go_dark_dungeon", "more_dungeons:tr_dungeon") self:RegisterBiomeTrigger("go_deep_snow", "deep_ice_cave") self:RegisterBiomeTrigger("go_ice_dungeon", "more_dungeons:blue_dungeon") self:RegisterBiomeTrigger("go_lava_dungeon", "more_dungeons:volcano_dungeon") self:RegisterBiomeTrigger("go_desert_dungeon", "more_dungeons:desert_dungeon") end return AdvancementTriggers ================================================ FILE: advancements/ancient_ingot.json ================================================ { "ancient_ingot": { "itemId": "ancient_ingot", "parentId": "netherite", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/ancient_wear.json ================================================ { "ancient_wear": { "itemId": "ancient_helmet", "parentId": "ancient_ingot", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/blaze_rod.json ================================================ { "blaze_rod": { "itemId": "blaze_rod", "parentId": "nether", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/bow.json ================================================ { "bow": { "itemId": "wooden_bow", "parentId": "crafting_table", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/bread.json ================================================ { "bread": { "itemId": "bread", "parentId": "farm", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/brew.json ================================================ { "brew": { "itemId": "brewing_stand", "parentId": "blaze_rod", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/bronze.json ================================================ { "bronze": { "itemId": "bronze_ingot", "parentId": "iron", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/cake.json ================================================ { "cake": { "itemId": "cake", "parentId": "farm", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/crafting_table.json ================================================ { "crafting_table": { "itemId": "crafting_table", "parentId": "wood", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/crison_eye.json ================================================ { "crison_eye": { "itemId": "strange_eye", "parentId": "strange_len", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/crison_eye_killed.json ================================================ { "crison_eye_killed": { "itemId": "strange_eye", "parentId": "crison_eye", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/crossbow.json ================================================ { "crossbow": { "itemId": "cross_bow", "parentId": "bow", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/diamond.json ================================================ { "diamond": { "itemId": "diamond", "parentId": "iron", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/diamond_ingot.json ================================================ { "diamond_ingot": { "itemId": "diamond_ingot", "parentId": "diamond", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/diamond_wear.json ================================================ { "diamond_wear": { "itemId": "diamond_chestplate", "parentId": "diamond", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/dungeon_eater.json ================================================ { "dungeon_eater": { "itemId": "dungeon_eater", "parentId": "go_dark_dungeon", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/dungeon_eater_killed.json ================================================ { "dungeon_eater_killed": { "itemId": "dungeon_eater", "parentId": "dungeon_eater", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/enchant.json ================================================ { "enchant": { "itemId": "enchantment_table", "parentId": "diamond", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/ender_chest.json ================================================ { "ender_chest": { "itemId": "ender_chest", "parentId": "ender_pearl", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/ender_pearl.json ================================================ { "ender_pearl": { "itemId": "ender_pearl", "parentId": "hunter", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/farm.json ================================================ { "farm": { "itemId": "stone_hoe", "parentId": "crafting_table", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/flesh_ingot.json ================================================ { "flesh_ingot": { "itemId": "flesh_ingot", "parentId": "gold", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/flesh_wear.json ================================================ { "flesh_wear": { "itemId": "flesh_helmet", "parentId": "flesh_ingot", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/furnace.json ================================================ { "furnace": { "itemId": "furnace", "parentId": "stone", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/ghast.json ================================================ { "ghast": { "itemId": "ghast_tear", "parentId": "nether", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/ghost.json ================================================ { "ghost": { "itemId": "ghost", "parentId": "ghost_crystal", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/ghost_crystal.json ================================================ { "ghost_crystal": { "itemId": "ghost_crystal", "parentId": "go_ghost_house", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/go_bone_dungeon.json ================================================ { "go_bone_dungeon": { "itemId": "more_dungeons:skull_block", "parentId": "crafting_table", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/go_dark_dungeon.json ================================================ { "go_dark_dungeon": { "itemId": "more_dungeons:dungeon_wall_green", "parentId": "go_ghost_house", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/go_deep_snow.json ================================================ { "go_deep_snow": { "itemId": "tc:snow", "parentId": "go_ghost_house", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/go_desert_dungeon.json ================================================ { "go_desert_dungeon": { "itemId": "more_dungeons:castle_pile_block", "parentId": "go_dark_dungeon", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/go_ghost_house.json ================================================ { "go_ghost_house": { "itemId": "more_dungeons:statue_mini_ghast", "parentId": "crafting_table", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/go_ice_dungeon.json ================================================ { "go_ice_dungeon": { "itemId": "more_dungeons:dungeon_wall_blue", "parentId": "go_deep_snow", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/go_lava_dungeon.json ================================================ { "go_lava_dungeon": { "itemId": "bucket_lava", "parentId": "go_ice_dungeon", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/gold.json ================================================ { "gold": { "itemId": "gold_ingot", "parentId": "iron", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/gold_wear.json ================================================ { "gold_wear": { "itemId": "golden_chestplate", "parentId": "gold", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/guardian.json ================================================ { "guardian": { "itemId": "guardian", "parentId": "hunter", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/gun.json ================================================ { "gun": { "itemId": "handgun", "parentId": "nether", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/hunter.json ================================================ { "hunter": { "itemId": "bone", "parentId": "sword", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/ice_element_ball.json ================================================ { "ice_element_ball": { "itemId": "ice_element_ball", "parentId": "snow_guard", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/inventory.json ================================================ { "inventory": { "itemId": "book", "showTip": true, "broadcase": true, "trigger": { "name": "open_advance_ui", "conditions": {} } } } ================================================ FILE: advancements/iron.json ================================================ { "iron": { "itemId": "iron_ingot", "parentId": "furnace", "showTip": true, "broadcase": true, "trigger": { "name": "get_item_group", "conditions": { "group": "GROUP_INGOT" } } } } ================================================ FILE: advancements/knight_ingot.json ================================================ { "knight_ingot": { "itemId": "knight_ingot", "parentId": "go_dark_dungeon", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/knight_wear.json ================================================ { "knight_wear": { "itemId": "knight_helmet", "parentId": "knight_ingot", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/lava.json ================================================ { "lava": { "itemId": "bucket_lava", "parentId": "iron", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/leather.json ================================================ { "leather": { "itemId": "leather", "parentId": "sword", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/magic_gold_wear.json ================================================ { "magic_gold_wear": { "itemId": "magic_gold_helmet", "parentId": "gold", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/magic_limit.json ================================================ { "magic_limit": { "itemId": "mana_piece", "parentId": "staff", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/mine.json ================================================ { "mine": { "itemId": "wooden_pickaxe", "parentId": "crafting_table", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/mine_bronze.json ================================================ { "mine_bronze": { "itemId": "bronze_pickaxe", "parentId": "mine_iron", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/mine_copper.json ================================================ { "mine_copper": { "itemId": "copper_pickaxe", "parentId": "mine_up", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/mine_diamond.json ================================================ { "mine_diamond": { "itemId": "diamond_pickaxe", "parentId": "mine_gold", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/mine_gold.json ================================================ { "mine_gold": { "itemId": "golden_pickaxe", "parentId": "mine_bronze", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/mine_iron.json ================================================ { "mine_iron": { "itemId": "iron_pickaxe", "parentId": "mine_copper", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/mine_netherite.json ================================================ { "mine_netherite": { "itemId": "nether_pickaxe", "parentId": "mine_diamond", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/mine_up.json ================================================ { "mine_up": { "itemId": "stone_pickaxe", "parentId": "stone", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/mirror.json ================================================ { "mirror": { "itemId": "ender_mirror", "parentId": "ender_pearl", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/nether.json ================================================ { "nether": { "itemId": "soul_sand", "parentId": "diamond", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/nether_destroyer.json ================================================ { "nether_destroyer": { "itemId": "nether_altar", "parentId": "nether", "showTip": true, "broadcase": true, "trigger": { "name": "nether_destroyer_wake", "conditions": {} } } } ================================================ FILE: advancements/nether_destroyer_killed.json ================================================ { "nether_destroyer_killed": { "itemId": "nether_destroyer_loot", "parentId": "nether_destroyer", "showTip": true, "broadcase": true, "trigger": { "name": "nether_destroyer_killed", "conditions": {} } } } ================================================ FILE: advancements/netherite.json ================================================ { "netherite": { "itemId": "ore_ancient_debris", "parentId": "nether", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/netherite_full_wear.json ================================================ { "netherite_full_wear": { "itemId": "nether_helmet", "parentId": "netherite", "showTip": true, "broadcase": true, "trigger": { "name": "full_wear_sub_group", "conditions": { "subGroup": "SUB_GROUP_NETHERITE" } } } } ================================================ FILE: advancements/portal.json ================================================ { "portal": { "itemId": "portal:nature_portal", "parentId": "crafting_table", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/pumpkin_helmet.json ================================================ { "pumpkin_helmet": { "itemId": "pumpkin_helmet", "parentId": "farm", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/recipe_book.json ================================================ { "recipe_book": { "itemId": "book", "parentId": "crafting_table", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/redstone.json ================================================ { "redstone": { "itemId": "redstone", "parentId": "stone", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/redstone_wire.json ================================================ { "redstone_wire": { "itemId": "red_wire", "parentId": "redstone", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/repair.json ================================================ { "repair": { "itemId": "anvil", "parentId": "iron", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/rocket_boost.json ================================================ { "rocket_boost": { "itemId": "rocket_boost", "parentId": "crafting_table", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/snow_guard.json ================================================ { "snow_guard": { "itemId": "steel_helmet", "parentId": "hunter", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/snow_queen.json ================================================ { "snow_queen": { "itemId": "snow_glass_ball", "parentId": "snow_guard", "showTip": true, "broadcase": true, "trigger": { "name": "snow_queen_wake", "conditions": {} } } } ================================================ FILE: advancements/snow_queen_killed.json ================================================ { "snow_queen_killed": { "itemId": "snow_queen_loot", "parentId": "snow_queen", "showTip": true, "broadcase": true, "trigger": { "name": "snow_queen_killed", "conditions": {} } } } ================================================ FILE: advancements/staff.json ================================================ { "staff": { "itemId": "amethyst_staff", "parentId": "hunter", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/star_wear.json ================================================ { "star_wear": { "itemId": "star_helmet", "parentId": "crison_eye_killed", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/steel.json ================================================ { "steel": { "itemId": "steel_ingot", "parentId": "iron", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/stone.json ================================================ { "stone": { "itemId": "stone_brick", "parentId": "mine", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/strange_len.json ================================================ { "strange_len": { "itemId": "strange_len", "parentId": "hunter", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/super_diamond_sword.json ================================================ { "super_diamond_sword": { "itemId": "super_diamond_sword", "parentId": "diamond", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/super_diamond_wear.json ================================================ { "super_diamond_wear": { "itemId": "super_diamond_helmet", "parentId": "diamond_ingot", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/sword.json ================================================ { "sword": { "itemId": "wooden_sword", "parentId": "crafting_table", "showTip": true, "broadcase": true } } ================================================ FILE: advancements/wood.json ================================================ { "wood": { "itemId": "wood_oak", "parentId": "inventory", "showTip": true, "broadcase": true } } ================================================ FILE: api.lua ================================================ ---@class TC.API local API = class("API") local s_instance ---@return TC.API function API.getInstance() if s_instance == nil then s_instance = API.new() end return s_instance end function API:__init() self.uiModifyDict = {} end function API:_ModifyUI(uiClassName, modifyClass) if self.uiModifyDict[uiClassName] == nil then self.uiModifyDict[uiClassName] = {} end table.insert(self.uiModifyDict[uiClassName], modifyClass) end ---data: ---{ --- initContentCallback=???, ---} ---@param data table function API.ModifyUI(uiClassName, modifyClass) API.getInstance():_ModifyUI(uiClassName, modifyClass) end return API ================================================ FILE: apis/Account.lua ================================================ ---@API ---@class Account 描述一个账号信息。 ---@field name string 当前账号的名称。 ---@field skinID int 当前账号的皮肤ID。 local Account = {} ---创建一个账号对象。 ---@return Account 新的账号对象。 function Account.new() end return Account ================================================ FILE: apis/AccountUtils.lua ================================================ ---@API ---@class AccountUtils 账号通用类,封装了账号相关操作函数。 local AccountUtils = {} ---从存档中加载一个账号。 ---@param accountName string 账号名称。 ---@param account Account 如果成功加载账号,将把账号信息写入该参数。 ---@return boolean 是否成功加载账号。 function AccountUtils.Load(accountName, account) end ---将一个账号保存到存档中。 ---@param account Account 账号。 function AccountUtils.Save(account) end ---将一个账号从存档中移除。 ---@param accountName string 账号名称。 function AccountUtils.Remove(accountName) end return AccountUtils ================================================ FILE: apis/Advancement.lua ================================================ ---@API ---@class Advancement 描述一项成就。 ---@field itemID int 成就使用的物品ID,用于在成就树界面显示物品图标。 ---@field parentID int 成就在成就树的父成就ID。 ---@field showTip boolean 玩家完成该成就时,是否在界面右上角弹出完成成就提示。 ---@field broadcast boolean 玩家完成成就时,是否广播给所有人。 local Advancement = {} return Advancement ================================================ FILE: apis/AdvancementUtils.lua ================================================ ---@API ---@class AdvancementUtils 成就通用类。 local AdvancementUtils = {} ---由成就ID,获得一个成就信息。 ---@param advancementID int 成就ID。 ---@return Advancement 成就信息。 function AdvancementUtils.Get(advancementID) end return AdvancementUtils ================================================ FILE: apis/Attack.lua ================================================ ---@API ---@class Attack 表示一个攻击属性。 ---@field attack int 伤害值。 ---@field knockBack int 击退值。 ---@field crit int 攻击的百分暴击率。1-100表示1-100%的概率产生双倍暴击伤害,大于100表示总是产生双倍暴击伤害,小于1表示不产生暴击伤害。 local Attack = {} --- 创建一个攻击属性对象。 ---@param attack int 伤害值。 ---@param knockBack int 击退值。 ---@param crit int 攻击的百分暴击率。 ---@return Attack 新的攻击属性对象。 function Attack.new(attack, knockBack, crit) end --- 重置所有攻击属性数值。 function Attack:Restore() end return Attack ================================================ FILE: apis/BiomeData.lua ================================================ ---@API ---@class BiomeTerrain 描述一个地形信息。 ---@field name string 地形名称。 ---@field times double 生成次数(小于1表示概率) ---@field size int 地形大小(生成器参数) ---@field height int 地形高度(生成器参数) local BiomeTerrain = {} ---@class BiomeTerrains 描述地形信息。 ---@field terrains BiomeTerrain[] 允许出现的所有地形。 ---@field specialTerrains BiomeTerrain[] 允许出现的特殊地形。 ---@field transition string 过渡方式(生成器参数) ---@field transitionTag int 过渡附加值(生成器参数) local BiomeTerrains = {} ---@class BiomeLiquidInfo 描述湖泊信息。 ---@field liquidID int 液体ID。 ---@field maxAllowCount int 湖泊最多有多少格子的当前液体。 local BiomeLiquidInfo = {} ---@class BiomeTreeInfo 描述树信息。 ---@field styles int[] 不同数目的方块id。 ---@field density double 种植密度(生成器参数) local BiomeTreeInfo = {} ---@class BiomeMushroomInfo 描述巨型蘑菇信息。 ---@field styles int[] 不同数目的方块id。 ---@field density double 种植密度(生成器参数) local BiomeMushroomInfo = {} ---@class BiomeData 描述一个群系信息。 ---@field biomeType int 群系类型。 ---@field scale double 群系大小(生成器参数,相对于perlin参考值) ---@field terrains BiomeTerrains 地形信息。 ---@field treeInfo BiomeTreeInfo 树信息。 ---@field mushroomInfo BiomeMushroomInfo 巨型蘑菇信息。 ---@field oreGroupName string 当前群系指定矿物名称批量生成矿物。 local BiomeData = {} return BiomeData ================================================ FILE: apis/BiomeUtils.lua ================================================ ---@API ---@class BiomeUtils 生物群系通用类。 local BiomeUtils = {} ---由指定生物群系类型和在该生物群系类型的索引,返回生物群系数据。 ---@param biomeTypeID int 生物群系类型。 ---@param index int 在该生物群系类型的索引。 ---@return int 生物群系数据。 function BiomeUtils.GetBiomeIDByType(biomeTypeID, index) end ---返回指定生物群系类型的生物群系数量。 ---@param biomeTypeID int 生物群系类型。 ---@return int 指定生物群系类型的生物群系数量。 function BiomeUtils.GetBiomeCountByType(biomeTypeID) end ---由生物群系ID,返回生物群系数据。 ---@param biomeID int 生物群系ID。 ---@return BiomeData 生物群系数据。 function BiomeUtils.GetData(biomeID) end return BiomeUtils ================================================ FILE: apis/BlockData.lua ================================================ ---@API ---@class BlockData 描述一个方块数据。 ---@field textureLocation TextureLocation 方块渲染在地图中的纹理。 ---@field group int 方块组,决定渲染在地图中纹理衔接方式。 ---@field subGroup int 方块子组。 ---@field stepSoundId int 踩在方块上发出的音效ID。 ---@field stepSoundGroupId int 踩在方块上发出的音效组ID。 ---@field functionSoundId int ---@field functionSoundGroupId int ---@field functionSoundId2 int ---@field functionSoundGroupId2 int ---@field functionSoundId3 int ---@field functionSoundGroupId3 int ---@field functionSoundId4 int ---@field functionSoundGroupId4 int ---@field isRipen boolean 是否允许催熟。 ---@field isDoorOpened boolean 是否为开启了的门。 ---@field isDoorClosed boolean 是否为关闭了的门。 local BlockData = {} ---判断指定物品,能否种植在当前方块上。 ---@param itemID int 物品ID。 ---@return boolean 物品能否种植在方块上。 function BlockData:CanSeed(itemID) end ---当前方块是否拥有动画效果。 ---@return boolean 是否拥有动画效果。 function BlockData:HasAnimation() end return BlockData ================================================ FILE: apis/BlockEntity.lua ================================================ ---@API ---@class BlockEntity ---@field id int ---@field xi int ---@field yi int ---@field dataWatcher DataWatcher local BlockEntity = {} ---SetAnimation ---@param animationIndex int function BlockEntity:SetAnimation(animationIndex) end ---GetAnimation ---@return int function BlockEntity:GetAnimation() end ---GetModBlockEntity ---@return ModBlockEntity function BlockEntity:GetModBlockEntity() end return BlockEntity ================================================ FILE: apis/BlockUtils.lua ================================================ ---@class BlockUtils ---@field maxID int ---@field oreGroups OreDataGroup[] local BlockUtils = {} ---@param blockID int ---@return BlockData function BlockUtils.GetData(blockID) end return BlockUtils ================================================ FILE: apis/Buff.lua ================================================ ---@class Buff ---@field id int ---@field time int local Buff = {} ---@param id int ---@param time int ---@return Buff function Buff.new(id, time) end return Buff ================================================ FILE: apis/ClientBoundPacketWriter.lua ================================================ ---@class ClientBoundPacket ---@field writerBuffer ByteStream ---@field readerBuffer ByteStream local ClientBoundPacket = {} ---Send ---@param player Player function ClientBoundPacket:Send(player) end ---@return ByteStream function ClientBoundPacket:GetWriterBuffer() end ---@return ByteStream function ClientBoundPacket:GetReaderBuffer() end return ClientBoundPacket ================================================ FILE: apis/ClientState.lua ================================================ ---@class ClientState ---@field LoadingResource int ---@field InMenu int ---@field Joining int ---@field LoadingWorld int ---@field SavingWorld int ---@field LosingConnection int ---@field Gaming int ---@field Exiting int ---@field current int local ClientState = {} return ClientState ================================================ FILE: apis/ClientStateManager.lua ================================================ ---@class ClientStateManager local ClientStateManager = class("ClientStateManager") ---StartJoining ---@param joinData JoinData function ClientStateManager.StartJoining(joinData) end function ClientStateManager.SaveAndExitGaming() end function ClientStateManager.QuitGame() end return ClientStateManager ================================================ FILE: apis/Container.lua ================================================ ---@class Container local Container = {} ---AddSlotToContainer ---@overload function(inventory:Inventory,slotIndex:int):int ---@param inventory Inventory ---@param slotIndex int ---@param ownedByGui boolean ---@return int function Container:AddSlotToContainer(inventory, slotIndex, ownedByGui) end ---GetSlot ---@param index int ---@return Slot function Container:GetSlot(index) end ---@return int function Container:GetSlotCount() end ---CanInteractWith ---@param player Player ---@return boolean function Container:CanInteractWith(player) end function Container:OnUpdate() end function Container:OnClose() end function Container:DetectAndSendChangeInteger(id, value) end function Container:DetectAndSendChangeDouble(id, value) end function Container:DetectAndSendChangeString(id, value) end function Container:DetectAndSendChangeBoolean(id, value) end function Container:OnDetectChange() end function Container:OnReceiveChange(id, value) end ---OnEvent ---@param eventId int ---@param eventString string function Container:OnEvent(eventId, eventString) end ---EnsureSlotEmpty ---@param container Container ---@param slotIndex int function Container:CommandEnsureSlotEmpty(container, slotIndex) end ---EnsureSlotHasItem ---@param container Container ---@param slotIndex int ---@param itemStack ItemStack function Container:CommandEnsureSlotHasItem(container, slotIndex, itemStack) end ---SwapSlot ---@param containerA Container ---@param slotIndexA int ---@param containerB Container ---@param slotIndexB int function Container:CommandSwapSlot(containerA, slotIndexA, containerB, slotIndexB) end ---SlotMoveTo ---@param containerFrom Container ---@param slotIndexFrom int ---@param containerTo Container ---@param slotIndexTo int ---@param moveStackSize int function Container:CommandSlotMoveTo(containerFrom, slotIndexFrom, containerTo, slotIndexTo, moveStackSize) end ---@return int function Container:GetID() end return Container ================================================ FILE: apis/DataWatcher.lua ================================================ ---@API ---@class DataWatcher 数据同步类,内部封装了网络同步逻辑。 local DataWatcher = {} --- ---@overload fun(value:int):int ---@param value boolean ---@param canRemote boolean ---@return int function DataWatcher:AddBool(value, canRemote) end ---由指定通道,向 ---@param channel int ---@param value boolean function DataWatcher:UpdateBool(channel, value) end ---由指定通道,从远端获取数据。 ---@param channel int 通道。 ---@return boolean 布尔型数据。 function DataWatcher:GetBool(channel) end --- ---@overload fun(value:int):int ---@param value int ---@param canRemote boolean ---@return int function DataWatcher:AddByte(value, canRemote) end --- ---@param channel int ---@param value int function DataWatcher:UpdateByte(channel, value) end --- ---@param channel int ---@return int function DataWatcher:GetByte(channel) end --- ---@overload fun(value:int):int ---@param value int ---@param canRemote boolean ---@return int function DataWatcher:AddShort(value, canRemote) end --- ---@param channel int ---@param value int function DataWatcher:UpdateShort(channel, value) end --- ---@param channel int ---@return int function DataWatcher:GetShort(channel) end --- ---@overload fun(value:int):int ---@param value int ---@param canRemote boolean ---@return int function DataWatcher:AddInteger(value, canRemote) end --- ---@param channel int ---@param value int function DataWatcher:UpdateInteger(channel, value) end --- ---@param channel int ---@return int function DataWatcher:GetInteger(channel) end --- ---@overload fun(value:boolean):int ---@param value double ---@param canRemote boolean ---@return int function DataWatcher:AddDouble(value, canRemote) end --- ---@param channel int ---@param value double function DataWatcher:UpdateDouble(channel, value) end --- ---@param channel int ---@return double function DataWatcher:GetDouble(channel) end --- ---@overload fun(value:string):int ---@param value string ---@param canRemote boolean ---@return int function DataWatcher:AddString(value, canRemote) end --- ---@param channel int ---@param value string function DataWatcher:UpdateString(channel, value) end --- ---@param channel int ---@return string function DataWatcher:GetString(channel) end --- ---@param value Inventory ---@return int function DataWatcher:AddInventory(value) end --- ---@param channel int ---@param value Inventory function DataWatcher:UpdateInventory(channel, value) end --- ---@param channel int ---@return Inventory function DataWatcher:GetInventory(channel) end return DataWatcher ================================================ FILE: apis/DeathReason.lua ================================================ ---@class DeathReason ---@field UNKNOWN int ---@field SUICIDE int ---@field FALL int ---@field DROWN int ---@field BOOM int ---@field BURN int ---@field LAVA int ---@field STARVE int ---@field BUFF int ---@field POISON int local DeathReason = {} return DeathReason ================================================ FILE: apis/Defense.lua ================================================ -- Document -- Defense Class: https://blueyoshi.gitbook.io/terracraft/en/mod/api/type#defense -- -- Defense类: https://blueyoshi.gitbook.io/terracraft/cn/mod/api/type#defense -- -- Copyright (c) 2021. BlueYoshi(blueyoshi@foxmail.com) ---@class Defense Represents a defense property. (表示一个防御属性) ---@field defense int The defense value. (防御值) ---@field blastDefense int The value of explosion defense. (爆炸防御值) ---@field flameDefense int The value of fire defense. (火焰防御值) ---@field projectileDefense int The value of projectile defense. (抛掷物防御值) ---@field breathDefense int The value of breath defense. (呼吸防御值) ---@field fallDefense int The value of fall defense. (掉落防御值) ---@field knockBackDefense int The value of knock back defense. (击退防御值) local Defense = {} function Defense:Restore() end return Defense ================================================ FILE: apis/Direction.lua ================================================ -- Document -- Direction Enum Class: https://blueyoshi.gitbook.io/terracraft/en/mod/api/type#direction -- -- Direction枚举类: https://blueyoshi.gitbook.io/terracraft/cn/mod/api/type#direction -- -- Copyright (c) 2021. BlueYoshi(blueyoshi@foxmail.com) ---@class Direction Enum class (Enum Format: `DIRECTION_XXX`) local Direction = {} ---@type Direction DIRECTION_LEFT = nil ---@type Direction DIRECTION_TOP = nil ---@type Direction DIRECTION_BOTTOM = nil ---@type Direction DIRECTION_RIGHT = nil return Direction ================================================ FILE: apis/Effect.lua ================================================ ---@class Effect:Entity ---@field decSpeed double ---@field decScale double ---@field decAlpha double ---@field decRotateSpeed double ---@field scale double ---@field alpha double ---@field rotateSpeed double ---@field gravity boolean ---@field lightAlpha int ---@field lightRed int ---@field lightGreen int ---@field lightBlue int ---@field disappearTime int local Effect = {} ---SetDisappearTime ---@param disappearTime int function Effect:SetDisappearTime(disappearTime) end --- Destroy the current effect object. --- --- 清除当前抛射物对象。 function Effect:Kill() end --- If the player owner exists and is alive, return the player, otherwise return nil. --- --- 若玩家拥有者存在且存活,返回该玩家,否则返回nil。 ---@return Player|nil function Effect:GetPlayerOwner() end --- If the npc owner exists and is alive, return the npc, otherwise return nil. --- --- 若NPC拥有者存在且存活,返回该NPC,否则返回nil。 ---@return Npc|nil function Effect:GetNpcOwner() end --- If the player target exists and is alive, return the player, otherwise return nil. --- --- 若当前抛射物的玩家锁定目标存在且存活,返回该玩家,否则返回nil。 ---@return Player|nil function Effect:GetPlayerTarget() end --- If the npc target exists and is alive, return the npc, otherwise return nil. --- --- 若当前抛射物的NPC锁定目标存在且存活,返回该NPC,否则返回nil。 ---@return Npc|nil function Effect:GetNpcTarget() end --- Set the locked player target of the current effect. --- --- 设定当前抛射物的锁定玩家目标。 ---@return Player|nil function Effect:SetPlayerTarget(player) end --- Set the locked NPC target of the current effect. --- --- 设定当前抛射物的锁定NPC目标。 ---@return Npc|nil function Effect:SetNpcTarget(npc) end return Effect ================================================ FILE: apis/EffectUtils.lua ================================================ ---@class EffectUtils local EffectUtils = {} --- --- ---@overload fun(id:int,centerX:double,centerY:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double,speedY:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double,speedY:double,rotateSpeed:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double,speedY:double,rotateSpeed:double,scale:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double,speedY:double,rotateSpeed:double,scale:double,alpha:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double,speedY:double,rotateSpeed:double,scale:double,alpha:double,color:Color):Effect ---@param id int ---@param centerX double ---@param centerY double ---@param speedX double ---@param speedY double ---@param rotateSpeed double ---@param scale double ---@param alpha double ---@param color Color ---@return Effect function EffectUtils.Create(id, centerX, centerY, speedX, speedY, rotateSpeed, scale, alpha, color) end ---@overload fun(id:int,centerX:double,centerY:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double,speedY:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double,speedY:double,rotateSpeed:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double,speedY:double,rotateSpeed:double,scale:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double,speedY:double,rotateSpeed:double,scale:double,alpha:double):Effect ---@overload fun(id:int,centerX:double,centerY:double,speedX:double,speedY:double,rotateSpeed:double,scale:double,alpha:double,color:Color):Effect ---@param id int ---@param centerX double ---@param centerY double ---@param speedX double ---@param speedY double ---@param rotateSpeed double ---@param scale double ---@param alpha double ---@param color Color ---@return Effect function EffectUtils.SendFromServer(id, centerX, centerY, speedX, speedY, rotateSpeed, scale, alpha, color) end return EffectUtils ================================================ FILE: apis/Enchantment.lua ================================================ ---@class Enchantment ---@field id int ---@field level int local Enchantment = {} ---@param id int ---@param level int ---@return Enchantment function Enchantment.new(id, level) end return Enchantment ================================================ FILE: apis/EnchantmentData.lua ================================================ ---@class EnchantmentData ---@field allowMaxLevel int ---@field minCreatingLevel int ---@field noCreating boolean local EnchantmentData = {} ---IsToolTypeValid ---@param toolType string ---@return boolean function EnchantmentData:IsToolTypeValid(toolType) end return EnchantmentData ================================================ FILE: apis/EnchantmentUtils.lua ================================================ ---@class EnchantmentUtils local EnchantmentUtils = {} ---@param enchantmentID int ---@return EnchantmentData function EnchantmentUtils.GetData(enchantmentID) end ---IsConflict ---@param enchantmentID int ---@param enchantmentID2 int ---@return boolean function EnchantmentUtils.IsConflict(enchantmentID, enchantmentID2) end return EnchantmentUtils ================================================ FILE: apis/Entity.lua ================================================ ---@API ---@class Entity 描述一个基本实体类。 ---@field x double 实体左上角x坐标。 ---@field y double 实体左上角y坐标。 ---@field centerX double Read-only 返回实体正中间x坐标。 ---@field centerY double Read-only 返回实体正中间y坐标。 ---@field centerXi int Read-only 返回实体正中间格子横坐标。 ---@field centerYi int Read-only 返回实体正中间格子纵坐标。 ---@field rightX double Read-only 返回实体最右侧x坐标。 ---@field bottomY double Read-only 返回实体最底部y坐标。 ---@field speedX double 实体横向速度。 ---@field speedY double 实体纵向速度。 ---@field gravity double 实体的重力加速度。 ---@field width int Read-only 返回实体碰撞箱宽度。 ---@field height int Read-only 返回实体碰撞箱高度。 ---@field direction boolean 实体面朝右侧为true,面朝左侧为false。 ---@field rotateAngle double 实体碰撞箱的旋转角度。 ---@field speedAngle double Read-only 返回当前实体运动速度的向量夹角。 ---@field randX double Read-only 返回实体在x轴投影上的随机坐标。 ---@field randY double Read-only 返回实体在y轴投影上的随机坐标。 ---@field shape Shape Read-only 返回实体碰撞箱形状。 ---@field stand boolean Read-only 返回实体是否为站立状态。 ---@field isCollisionTop boolean Read-only 返回实体是否顶部发生碰撞。 ---@field isCollisionLeft boolean Read-only 返回实体是否左侧发生碰撞。 ---@field isCollisionRight boolean Read-only 返回实体是否右侧发生碰撞。 ---@field isCollisionStuck boolean Read-only 返回实体是否卡在方块内部。 ---@field isNoCollision boolean Read-only 返回实体是否没有发生任何形式的碰撞。 ---@field onSlope boolean Read-only 返回实体是否站在斜坡上。 ---@field hitbox Hitbox Read-only 若实体为轴对齐矩形,返回轴对齐碰撞箱,否则返回旋转矩形碰撞箱。 ---@field aabb Hitbox Read-only 实体旋转角度为0的轴对齐碰撞箱。 ---@field minAABB Hitbox Read-only 完全包裹实体的最小轴对齐碰撞箱。 ---@field allowCheckCollision boolean 决定是否执行与方块的碰撞检测。 ---@field spriteDefaultWidth int Read-only 实体默认绘制宽度。 ---@field spriteDefaultHeight int Read-only 实体默认绘制高度。 ---@field spriteRect Rectangle 表示实体绘制时在目标贴图的剪裁区域。 ---@field spriteEx SpriteEx 实体绘制时的精灵拓展信息。 ---@field spriteOffsetX int @[ default `0.0` ] 实体绘制的横向偏移量。 ---@field spriteOffsetY int @[ default `0.0` ] 实体绘制的纵向偏移量。 ---@field color Color @[ default `COLOR_WHITE` ] 实体绘制时的颜色。 ---@field frameTickTime int 实体绘制用的帧计时器,每帧自增1。 ---@field frameIndex int Read-only 当前实体帧索引。 ---@field frameStyles int Read-only 实体样式数。 ---@field frames int Read-only 实体总帧数。 ---@field frameSpeed int Read-only 实体帧切换周期。 ---@field tickTime int Read-only 实体的实际生存的时间。 ---@field randSeed int Read-only 实体的随机数种子。 local Entity = {} --- 将实体中心x坐标设为指定位置。 ---@param newCenterX double function Entity:SetCenterX(newCenterX) end --- 将实体中心y坐标设为指定位置。 ---@param newCenterY double function Entity:SetCenterY(newCenterY) end --- 返回实体中心点到目标点的角度。 ---@param desX double 目标点x坐标。 ---@param desY double 目标点y坐标。 ---@return double function Entity:GetAngleTo(desX, desY) end --- 返回来源点到实体中心点的角度。 ---@param srcX double 来源点x坐标。 ---@param srcY double 来源点y坐标。 ---@return double function Entity:GetAngleFrom(srcX, srcY) end --- 返回实体中心到指定点的距离。 ---@param otherX double 目标点x坐标。 ---@param otherX double 目标点y坐标。 ---@return double function Entity:GetDistance(otherX, otherY) end --- 在原有角度基础上继续旋转指定角度。 ---@param angle double 旋转的角度。 function Entity:Rotate(angle) end --- 在原有速度角度基础上继续旋转指定速度角度。 ---@param angle double 旋转的角度。 function Entity:RotateSpeed(angle) end return Entity ================================================ FILE: apis/EntityIndex.lua ================================================ ---@class EntityIndex ---@field entityID int ---@field uniqueID int local EntityIndex = {} ---@overload fun():EntityIndex ---@param entityID int ---@param uniqueID int ---@return EntityIndex function EntityIndex.new(entityID, uniqueID) end return EntityIndex ================================================ FILE: apis/GameMode.lua ================================================ ---@class GameMode ---@field Survival int ---@field Creative int ---@field Adventure int local GameMode = {} return GameMode ================================================ FILE: apis/GlobalBlock.lua ================================================ ================================================ FILE: apis/GlobalNpc.lua ================================================ ---@class GlobalNpc ---@field npc Npc local GlobalNpc = {} --- This function is called once when the NPC is spawned. --- --- NPC生成时调用一次该函数。 function GlobalNpc:Init() end --- --- --- NPC每帧运行Update()函数前调用,如果返回true则执行所有Update逻辑,返回false则不执行所有Update逻辑。可在该函数写入新的逻辑,并屏蔽原有逻辑。默认返回true。 ---@return boolean function GlobalNpc:CanUpdate() return true end --- Called when NPC runs every update tick, usually write logic in this function. --- --- NPC每帧运行时调用,通常在该函数内编写运动等逻辑。 function GlobalNpc:Update() end --- Called before the NPC runs the `Update()` function every update tick. --- It is usually used to insert new logic before the original logic. --- --- NPC每帧运行`Update()`函数前调用。通常用于在原逻辑前插入新逻辑。 function GlobalNpc:PreUpdate() end --- Called after the NPC runs the `Update()` function every update tick. --- It is usually used to insert new logic after the original logic. --- --- NPC每帧运行`Update()`函数后调用。通常用于追加逻辑。 function GlobalNpc:PostUpdate() end --- If the NPC has a skeleton model, --- it is called after `PostUpdate()` to process the logic of the custom skeleton model. --- After executing this function, all joints of the skeleton model will be recalculated. --- --- 若NPC拥有骨骼模型,每帧执行完`PostUpdate()`后调用,用于处理自定义骨骼模型逻辑。 --- 执行完该函数后,会对所有骨骼模型关节重新计算。 --- @param skeleton Skeleton Represents the skeleton model of the current NPC. (当前NPC的骨骼模型) function GlobalNpc:UpdateSkeleton(skeleton) end --- Called before the NPC runs the `UpdateSkeleton(skeleton)` function every update tick. --- It is usually used to insert new logic before the original logic. --- --- NPC每帧运行`UpdateSkeleton(skeleton)`函数前调用。通常用于在原逻辑前插入新逻辑。 --- @param skeleton Skeleton Represents the skeleton model of the current NPC. (当前NPC的骨骼模型) function GlobalNpc:PreUpdateSkeleton(skeleton) end --- Called after the NPC runs the `UpdateSkeleton(skeleton)` function every update tick. --- It is usually used to insert new logic after the original logic. --- --- NPC每帧运行`UpdateSkeleton(skeleton)`函数后调用。通常用于在原逻辑后追加新逻辑。 --- @param skeleton Skeleton Represents the skeleton model of the current NPC. (当前NPC的骨骼模型) function GlobalNpc:PostUpdateSkeleton(skeleton) end --- --- --- NPC每帧绘制前调用,如果返回true则执行所有Draw逻辑,返回false则不执行所有Draw逻辑。可在该函数写入新的逻辑,并屏蔽原有逻辑。默认返回true。 ---@return boolean function GlobalNpc:CanDraw() return true end --- Called before each tick of NPC drawing, --- just write custom drawing behavior in this function. --- --- NPC每帧绘制前调用,在该函数内编写自定义绘制属性。 function GlobalNpc:OnDraw() end --- Called when NPC was killed. --- --- NPC死亡时调用一次该函数。 function GlobalNpc:OnKilled() end --- Called when NPC collides the tiles. --- --- NPC与图块碰撞时调用该函数。 --- @param oldSpeedX double The X speed before colliding tiles. (击中图块前一帧的横向速度) --- @param oldSpeedY double The Y speed before colliding tiles. (击中图块前一帧的纵向速度) function GlobalNpc:OnTileCollide(oldSpeedX, oldSpeedY) end function GlobalNpc:OnLoot() end ---@return table function GlobalNpc:Save() end ---Load ---@param tagTable table function GlobalNpc:Load(tagTable) end return GlobalNpc ================================================ FILE: apis/GlobalPlayer.lua ================================================ ---@class GlobalPlayer ---@field player Player local GlobalPlayer = {} function GlobalPlayer:Awake() end --- This function is called once when the player is spawned. --- --- 玩家生成时调用一次该函数。 function GlobalPlayer:Init() end --- --- --- 玩家每帧运行Update()函数前调用,如果返回true则执行所有Update逻辑,返回false则不执行所有Update逻辑。可在该函数写入新的逻辑,并屏蔽原有逻辑。默认返回true。 ---@return boolean function GlobalPlayer:CanUpdate() return true end function GlobalPlayer:Motion() end --- Called when player runs every update tick, usually write logic in this function. --- --- 玩家每帧运行时调用,通常在该函数内编写运动等逻辑。 function GlobalPlayer:Update() end --- Called before the player runs the `Update()` function every update tick. --- It is usually used to insert new logic before the original logic. --- --- 玩家每帧运行`Update()`函数前调用。通常用于在原逻辑前插入新逻辑。 function GlobalPlayer:PreUpdate() end --- Called after the player runs the `Update()` function every update tick. --- It is usually used to insert new logic after the original logic. --- --- 玩家每帧运行`Update()`函数后调用。通常用于追加逻辑。 function GlobalPlayer:PostUpdate() end --- If the player has a skeleton model, --- it is called after `PostUpdate()` to process the logic of the custom skeleton model. --- After executing this function, all joints of the skeleton model will be recalculated. --- --- 若玩家拥有骨骼模型,每帧执行完`PostUpdate()`后调用,用于处理自定义骨骼模型逻辑。 --- 执行完该函数后,会对所有骨骼模型关节重新计算。 --- @param skeleton Skeleton Represents the skeleton model of the current 玩家. (当前玩家的骨骼模型) function GlobalPlayer:UpdateSkeleton(skeleton) end --- Called before the player runs the `UpdateSkeleton(skeleton)` function every update tick. --- It is usually used to insert new logic before the original logic. --- --- 玩家每帧运行`UpdateSkeleton(skeleton)`函数前调用。通常用于在原逻辑前插入新逻辑。 --- @param skeleton Skeleton Represents the skeleton model of the current 玩家. (当前玩家的骨骼模型) function GlobalPlayer:PreUpdateSkeleton(skeleton) end --- Called after the player runs the `UpdateSkeleton(skeleton)` function every update tick. --- It is usually used to insert new logic after the original logic. --- --- 玩家每帧运行`UpdateSkeleton(skeleton)`函数后调用。通常用于在原逻辑后追加新逻辑。 --- @param skeleton Skeleton Represents the skeleton model of the current 玩家. (当前玩家的骨骼模型) function GlobalPlayer:PostUpdateSkeleton(skeleton) end --- --- --- 玩家每帧绘制前调用,如果返回true则执行所有Draw逻辑,返回false则不执行所有Draw逻辑。可在该函数写入新的逻辑,并屏蔽原有逻辑。默认返回true。 ---@return boolean function GlobalPlayer:CanDraw() return true end --- Called before each tick of player drawing, --- just write custom drawing behavior in this function. --- --- 玩家每帧绘制前调用,在该函数内编写自定义绘制属性。 function GlobalPlayer:OnDraw() end --- Called when player was killed. --- --- 玩家死亡时调用一次该函数。 function GlobalPlayer:OnKilled() end function GlobalPlayer:OnRespawn() end --- Called when player collides the tiles. --- --- 玩家与图块碰撞时调用该函数。 --- @param oldSpeedX double The X speed before colliding tiles. (击中图块前一帧的横向速度) --- @param oldSpeedY double The Y speed before colliding tiles. (击中图块前一帧的纵向速度) function GlobalPlayer:OnTileCollide(oldSpeedX, oldSpeedY) end function GlobalPlayer:OnRender() end function GlobalPlayer:RecalculateProperties() end ---OnHitByNpc ---@param npc Npc function GlobalPlayer:OnHitByNpc(npc) end ---OnHitByProjectile ---@param projectile Projectile function GlobalPlayer:OnHitByProjectile(projectile) end function GlobalPlayer:OnFirstTimeJoin() end function GlobalPlayer:OnInventoryChanged() end ---OnInventoryItemAdded ---@param itemID int ---@param stackSize int function GlobalPlayer:OnInventoryItemAdded(itemID, stackSize) end ---OnInventoryItemRemoved ---@param itemID int ---@param stackSize int function GlobalPlayer:OnInventoryItemRemoved(itemID, stackSize) end ---OnAdvancementMade ---@param advancementID int function GlobalPlayer:OnAdvancementMade(advancementID) end ---OnAdvancementRemoved ---@param advancementID int function GlobalPlayer:OnAdvancementRemoved(advancementID) end ---@return table function GlobalPlayer:Save() end ---Load ---@param tagTable table function GlobalPlayer:Load(tagTable) end ---@return table function GlobalPlayer:SaveCSC() end ---@param tagTable table function GlobalPlayer:LoadCSC(tagTable) end return GlobalPlayer ================================================ FILE: apis/GuiContainer.lua ================================================ ---@class GuiContainer ---@field container Container local GuiContainer = {} ---__init ---@param container Container function GuiContainer:__init(container) end function GuiContainer:OnUpdate() end function GuiContainer:OnClose() end ---TriggerClientEvent ---@overload fun(eventId:int) ---@param eventId int ---@param eventString string function GuiContainer:TriggerClientEvent(eventId, eventString) end ---TriggerServerEvent ---@overload fun(eventId:int) ---@param eventId int ---@param eventString string function GuiContainer:TriggerServerEvent(eventId, eventString) end return GuiContainer ================================================ FILE: apis/Hitbox.lua ================================================ -- Document -- Hitbox Class: https://blueyoshi.gitbook.io/terracraft/en/mod/api/type#hitbox -- -- Hitbox类: https://blueyoshi.gitbook.io/terracraft/cn/mod/api/type#hitbox -- -- Copyright (c) 2021. BlueYoshi(blueyoshi@foxmail.com) ---@class Hitbox Represents a collision box. If the angle attribute is 0, it means axis aligned collision box (AABB). Otherwise, it represents a collision box rotating around the center point. (表示一个碰撞箱。若angle属性为0,表示轴对齐碰撞箱(AABB)。否则表示一个绕中心点旋转的碰撞箱。) ---@field x double The x coordinate of the upper left corner of the hitbox when the rotation angle is 0. (碰撞箱在旋转角度为0时左上角x坐标) ---@field y double The y coordinate of the upper left corner of the hitbox when the rotation angle is 0. (碰撞箱在旋转角度为0时左上角y坐标) ---@field width int The width of the hitbox. (碰撞箱宽度) ---@field height int The height of the hitbox. (碰撞箱高度) ---@field centerX double @[ Read-only ] Returns the center x coordinate of the hitbox. (返回碰撞箱正中间x坐标) ---@field centerY double @[ Read-only ] Returns the center y coordinate of the hitbox. (返回碰撞箱正中间y坐标) ---@field angle double @[ Read-only ] Returns the rotation angle of the collision box if the collision box can be rotated. (若碰撞箱可以旋转,表示碰撞箱的旋转角度) local Hitbox = {} --- Returns whether the current hitbox overlaps with another hitbox. --- --- 返回当前碰撞箱与另一个碰撞箱是否重叠。 ---@param other Hitbox The other hitbox. (另一个碰撞箱) ---@return boolean function Hitbox:Overlap(other) end --- Returns whether the current axis-aligned rectangle overlaps with another axis-aligned rectangle. --- --- 返回当前轴对齐矩形与另一个轴对齐矩形是否重叠。 ---@param other Hitbox The other hitbox. (另一个碰撞箱) ---@return boolean function Hitbox:OverlapAABB(other) end return Hitbox ================================================ FILE: apis/Inventory.lua ================================================ ---@API ---@class Inventory 描述物品格子集合。 ---@field slotCount int 物品格子的总数。 local Inventory = {} ---场景一个物品格子集合对象。 ---@param slotCount int 物品格子的总数。 ---@return Inventory 新的物品格子集合对象。 function Inventory.new(slotCount) end ---判断当前物品格子集合对象是否有效。 ---@return boolean function Inventory:Valid() end ---改变格子数量,若新增了格子,则格子将默认为空格子。 ---@param count int 新的格子总数。 function Inventory:SetSlotCount(count) end ---由格子索引获取格子对象。 ---@param index int 格子索引。 ---@return Slot 物品格子对象。 function Inventory:GetSlot(index) end ---往当前集合加入一组堆叠物品。 ---@param itemStack ItemStack 堆叠物品。 ---@return ItemStack 当放入堆叠物品后导致集合满时,返回未能放入的堆叠物品。如果能完全放入,则返回无效ItemStack。 function Inventory:AddItemStack(itemStack) end ---为当前集合的所有物品格子进行排序。 function Inventory:SortAll() end ---为当前集合的指定格子范围进行排序。 ---@param index int 格子范围起始索引。 ---@param count int 待排序的格子总数。 function Inventory:Sort(index, count) end ---将当前集合的指定格子范围内的物品快速转移到另一个物品格子集合的指定范围。 ---@overload fun(start:int,slotCount:int,inventoryTo:Inventory,inventoryToStart:int,inventoryToSlotCount:int) ---@param start int 当前集合待转移的格子范围起始索引。 ---@param slotCount int 当前集合待转移的格子总数。 ---@param inventoryTo Inventory 将要转移到的格子集合对象。 ---@param inventoryToStart int 将要转移到的格子集合对象的格子范围起始索引。 ---@param inventoryToSlotCount int 将要转移到的格子集合对象的格子总数。 ---@param pushSameItemOnly boolean function Inventory:QuickPushAllTo(start, slotCount, inventoryTo, inventoryToStart, inventoryToSlotCount, pushSameItemOnly) end ---序列化得到lua表。 ---@return table lua表。 function Inventory:Serialization() end ---由lua表反序列化得到当前物品格子集合对象。 ---@param serializedTable table lua表。 function Inventory:Deserialization(serializedTable) end return Inventory ================================================ FILE: apis/Item.lua ================================================ ---@class Item ---@field id int ---@field idName string ---@field mod Mod ---@field type ItemType_Value ---@field maxStackSize int ---@field groupID int ---@field isBlock boolean ---@field isTool boolean ---@field isMaterial boolean ---@field isProjectile boolean ---@field isWire boolean ---@field toolType string ---@field iconTextureLocation TextureLocation ---@field entityTextureLocation TextureLocation ---@field iconColor Color ---@field iconColor2 Color ---@field iconColor3 Color ---@field iconColor4 Color ---@field iconColor5 Color ---@field iconColor6 Color ---@field maxDurable int ---@field coldTime int ---@field entityWidth int ---@field entityHeight int ---@field entityOffsetX int ---@field entityOffsetY int ---@field handX int ---@field handY int ---@field hasEntity boolean ---@field oreDictionaryIDs int[] ---@field toolGrade int ---@field toolGradeName string ---@field firePointCount int ---@field usePosture int ---@field twoHands boolean ---@field ammoID int ---@field ammoLevel int ---@field shootProjectileID int ---@field projectileID int ---@field fuelTime int ---@field fuelReturnItemID int ---@field isSeed boolean ---@field shootable boolean ---@field shootTimes int ---@field blockID int ---@field wireID int ---@field efficiency double ---@field noConsumeChance double ---@field deviation double ---@field speed double ---@field showHair boolean ---@field canThrow boolean ---@field baseAttack Attack ---@field defense int ---@field useSoundID int ---@field useSoundGroupID int ---@field eatable boolean ---@field buffs Buff[] ---@field enchantments Enchantment[] ---@field addHealth int ---@field addMagic int ---@field addMaxMagic int ---@field food int ---@field foodSaturation int ---@field consumeMana int local Item = {} ---GetFirePoint ---@param index int ---@return Vector2 function Item:GetFirePoint(index) end return Item ================================================ FILE: apis/ItemRegistry.lua ================================================ ---@class ItemRegistry local ItemRegistry = {} ---GetItemByID ---@param id int ---@return Item function ItemRegistry.GetItemByID(id) end ---GetItemByIDName ---@param idName string ---@return Item function ItemRegistry.GetItemByIDName(idName) end return ItemRegistry ================================================ FILE: apis/ItemStack.lua ================================================ ---@API ---@class ItemStack 描述一组堆叠物品。 ---@field stackSize int Read-only 当前堆叠数量。 ---@field durable double 当前物品耐久。 ---@field enchantmentCount int 当前堆叠物品挂接的附魔数量。 local ItemStack = {} ---创建一个堆叠物品对象。 --- ---[Example] -----创建堆叠234个由钻石的堆叠物品对象。 ---local itemStackDiamond = ItemStack.new(ItemRegistry.GetItemByID("diamond"), 234) -----创建一个铁剑堆叠物品对象。 ---local itemStackSword = ItemStack.new(ItemRegistry.GetItemByID("iron_sword")) --- ---@overload fun(item:Item):ItemStack ---@param item Item 物品。 ---@param stackSize int 堆叠数量。 ---@return ItemStack 新的堆叠物品对象。 function ItemStack.new(item, stackSize) end ---判断当前堆叠物品数据是否有效。 function ItemStack:Valid() end ---为当前堆叠物品新增一项附魔。 ---@param enchantmentId int 附魔ID。 ---@param enchantmentLevel int 附魔等级。 ---@return boolean 新增附魔是否有变化,当且仅当之前已经存在附魔且新增附魔等级小于之前等级则无变化。 function ItemStack:AddEnchantment(enchantmentId, enchantmentLevel) end ---克隆返回一个新的堆叠物品对象。 ---@overload fun():ItemStack ---@param stackSize int 新的堆栈数量。 ---@return ItemStack 新的堆叠物品对象。 function ItemStack:Clone(stackSize) end ---设置堆栈数量。 function ItemStack:SetStackSize(value) end ---增加耐久值。 function ItemStack:AddDurable(value) end ---直接设置耐久值。 function ItemStack:SetDurable(value) end ---减少耐久值。 ---@return boolean 减少后耐久是否为0。 function ItemStack:LoseDurable(value) end ---获取当前堆栈物品指定附魔的等级。 ---@param enchantmentId int 附魔ID。 ---@return int 附魔等级。 function ItemStack:GetEnchantmentLevel(enchantmentId) end ---判断当前堆叠物品是否拥有了指定附魔。 ---@overload fun():boolean ---@param enchantmentId int 附魔ID。 ---@return boolean function ItemStack:HasEnchantment(enchantmentId) end ---由附魔索引得到附魔对象。 ---@param index int 附魔索引。 ---@return Enchantment 附魔对象。 function ItemStack:GetEnchantmentByIndex(index) end ---由附魔索引删除附魔对象。 ---@param index int 附魔索引。 function ItemStack:RemoveEnchantmentByIndex(index) end ---由附魔ID删除一个附魔对象。 ---@param enchantmentID int 附魔ID。 function ItemStack:RemoveEnchantment(enchantmentID) end ---清空所有附魔。 function ItemStack:ClearEnchantments() end ---判断当前堆叠物品的物品数据是否与另一个堆叠物品的物品数据相同。 ---@param itemStack ItemStack 另一个堆叠物品。 ---@return boolean function ItemStack:IsItemEqual(itemStack) end ---判断当前堆叠物品是否与另一个堆叠物品相同。 ---@overload fun(itemStack:ItemStack):boolean ---@param itemStack ItemStack 另一个堆叠物品。 ---@param ignoreStackSize boolean 是否忽略堆叠物品数量判断。 ---@return boolean function ItemStack:IsItemStackEqual(itemStack, ignoreStackSize) end ---返回当前堆叠物品与另一个堆叠物品可合并的数量。 ---@param itemStack ItemStack 另一个堆叠物品。 ---@return int function ItemStack:GetMergeCount(itemStack) end ---拆分当前堆叠物品,返回新的拆出来的堆叠物品对象。 ---@param count int 拆出来的堆叠数量。 ---@return ItemStack 新的拆出来的堆叠物品对象。 function ItemStack:SplitStack(count) end ---获得当前堆叠物品的物品数据。 ---@return Item function ItemStack:GetItem() end ---绘制当前堆叠物品。 ---@param position Vector2 ---@param color Color ---@param spriteExData SpriteExData function ItemStack:Render(position, color, spriteExData) end ---绘制当前堆叠物品的堆叠数量。 ---@param position Vector2 ---@param color Color ---@param spriteExData SpriteExData function ItemStack:RenderNum(position, color, spriteExData) end ---自定义绘制当前堆叠物品的堆叠数量。 ---@param num int ---@param position Vector2 ---@param color Color ---@param spriteExData SpriteExData function ItemStack:RenderCustomNum(num, position, color, spriteExData) end ---执行堆叠物品挂接ModItem的`OnHeld`函数。 ---@param player Player 玩家 function ItemStack:RunOnHeldEvent(player) end ---执行堆叠物品挂接ModItem的`OnHeldRender`函数。 ---@param player Player 玩家 function ItemStack:RunOnHeldRenderEvent(player) end ---执行堆叠物品挂接ModItem的`OnHeld`函数。 ---@param npc Npc function ItemStack:RunOnHeldByNpcEvent(npc) end ---返回当前堆叠物品是否能被玩家使用。 ---@param player Player 玩家 ---@return boolean function ItemStack:CanUse(player) end ---执行堆叠物品挂接ModItem的`OnUsed`函数。 ---@param player Player 玩家 function ItemStack:RunOnUsedEvent(player) end ---执行堆叠物品挂接ModItem的`OnUsedByNpc`函数。 ---@param npc Npc function ItemStack:RunOnUsedByNpcEvent(npc) end ---执行堆叠物品挂接ModItem的`OnDurableEmpty`函数。 ---@param player Player 玩家 ---@return boolean function ItemStack:RunOnDurableEmptyEvent(player) end ---序列化得到lua表。 ---@return table lua表。 function ItemStack:Serialization() end ---由lua表反序列化创建一个堆叠物品对象。 ---@param serializedTable table lua表。 ---@return ItemStack 新的堆叠物品对象。 function ItemStack.Deserialization(serializedTable) end ---返回当前堆叠物品挂接的ModItem对象。 ---@return ModItem 挂接的ModItem对象,如果无挂接,返回nil。 function ItemStack:GetModItem() end return ItemStack ================================================ FILE: apis/ItemType.lua ================================================ ---@class ItemType_Value ---@class ItemType ---@field Block ItemType_Value ---@field Tool ItemType_Value ---@field Material ItemType_Value ---@field Projectile ItemType_Value ---@field Wire ItemType_Value local ItemType = {} return ItemType ================================================ FILE: apis/ItemUtils.lua ================================================ ---@class ItemUtils ---@field maxRootGroupCount int local ItemUtils = {} ---CreateDrop ---@overload fun(itemStack:ItemStack, centerX:double, centerY:double) ---@overload fun(itemStack:ItemStack, centerX:double, centerY:double, speedX:double, speedY:double) ---@param itemStack ItemStack ---@param centerX double ---@param centerY double ---@param speedX double ---@param speedY double ---@param coldTime int function ItemUtils.CreateDrop(itemStack, centerX, centerY, speedX, speedY, coldTime) end ---GetOreDictionaryItemIDs ---@param oreDictionaryID int ---@return int[] function ItemUtils.GetOreDictionaryItemIDs(oreDictionaryID) end ---GetGroupItemIDs ---@param itemGroupID int ---@return int[] function ItemUtils.GetGroupItemIDs(itemGroupID) end ---GetGroupIDsFromRootID ---@param rootGroupID int ---@return int[] function ItemUtils.GetGroupIDsFromRootID(rootGroupID) end ---GetRootGroupIconItemID ---@param rootGroupID int ---@return int function ItemUtils.GetRootGroupIconItemID(rootGroupID) end return ItemUtils ================================================ FILE: apis/JoinData.lua ================================================ ---@class JoinData ---@field playerName string ---@field worldName string ---@field address string ---@field port int ---@field multiplayer boolean local JoinData = {} ---@return JoinData function JoinData.new() end return JoinData ================================================ FILE: apis/LangUtils.lua ================================================ ---@class LangUtils local LangUtils = {} --- ---@param itemID int ---@return string function LangUtils.ItemName(itemID) end --- ---@param itemID int ---@return string function LangUtils.ItemIntroduction(itemID) end --- ---@param buffID int ---@return string function LangUtils.BuffName(buffID) end ---EnchantmentName ---@param enchantmentID int ---@return string function LangUtils.EnchantmentName(enchantmentID) end ---NpcName ---@param npcID int ---@return string function LangUtils.NpcName(npcID) end ---AdvancementName ---@param advancementID int ---@return string function LangUtils.AdvancementName(advancementID) end ---AdvancementDescription ---@param advancementID int ---@return string function LangUtils.AdvancementDescription(advancementID) end return LangUtils ================================================ FILE: apis/LightingUtils.lua ================================================ ---@class LightingUtils local LightingUtils = {} ---Add ---@overload fun(xi:int,yi:int,alpha:int) ---@overload fun(xi:int,yi:int,alpha:int,red:int) ---@overload fun(xi:int,yi:int,alpha:int,red:int,green:int) ---@overload fun(xi:int,yi:int,alpha:int,red:int,green:int,blue:int) ---@param xi int ---@param yi int ---@param alpha int ---@param red int ---@param green int ---@param blue int function LightingUtils.Add(xi, yi, alpha, red, green, blue) end ---AddDelay ---@overload fun(xi:int,yi:int,delayTime:int,alpha:int) ---@overload fun(xi:int,yi:int,delayTime:int,alpha:int,red:int) ---@overload fun(xi:int,yi:int,delayTime:int,alpha:int,red:int,green:int) ---@overload fun(xi:int,yi:int,delayTime:int,alpha:int,red:int,green:int,blue:int) ---@param xi int ---@param yi int ---@param delayTime int ---@param alpha int ---@param red int ---@param green int ---@param blue int function LightingUtils.AddDelay(xi, yi, delayTime, alpha, red, green, blue) end return LightingUtils ================================================ FILE: apis/MapPos.lua ================================================ ---@class MapPos ---@field xi int ---@field yi int local MapPos = {} return MapPos ================================================ FILE: apis/MapUtils.lua ================================================ ---@class MapUtils local MapUtils = {} ---IsValid ---@param xi int ---@param yi int ---@return boolean function MapUtils.IsValid(xi, yi) end ---IsAreaValid ---@param xi int ---@param yi int ---@param width int ---@param height int ---@return boolean function MapUtils.IsAreaValid(xi, yi, width, height) end ---IsSolid ---@param xi int ---@param yi int ---@return boolean function MapUtils.IsSolid(xi, yi) end ---HasFront ---@param xi int ---@param yi int ---@return boolean function MapUtils.HasFront(xi, yi) end ---GetFrontID ---@param xi int ---@param yi int ---@return int function MapUtils.GetFrontID(xi, yi) end ---GetFrontCenterXY ---@param xi int ---@param yi int ---@return double,double function MapUtils.GetFrontCenterXY(xi, yi) end ---@param xi int ---@param yi int ---@return int,int function MapUtils.GetBodyPos(xi, yi) end ---GetFrontIDTag ---@param xi int ---@param yi int ---@return int,int function MapUtils.GetFrontIDTag(xi, yi) end ---CanSetFrontTag ---@param xi int ---@param yi int ---@return boolean function MapUtils.CanSetFrontTag(xi, yi) end ---SetFrontTag ---@param xi int ---@param yi int ---@param tag int ---@return boolean function MapUtils.SetFrontTag(xi, yi, tag) end ---CanSetFront ---@overload fun(xi:int, yi:int, frontID:int):boolean ---@overload fun(xi:int, yi:int, frontID:int, isDestroyFragile:boolean):boolean ---@param xi int ---@param yi int ---@param frontID int ---@param isDestroyFragile boolean ---@param isCheckingEntities boolean ---@return boolean function MapUtils.CanSetFront(xi, yi, frontID, isDestroyFragile, isCheckingEntities) end ---SetFront ---@overload fun(xi:int, yi:int, frontID:int):boolean ---@overload fun(xi:int, yi:int, frontID:int, isDestroyFragile:boolean):boolean ---@overload fun(xi:int, yi:int, frontID:int, isDestroyFragile:boolean, showEffect:boolean):boolean ---@param xi int ---@param yi int ---@param frontID int ---@param isDestroyFragile boolean ---@param showEffect boolean ---@param playSound boolean ---@return boolean function MapUtils.SetFront(xi, yi, frontID, isDestroyFragile, showEffect, playSound) end ---CanPlaceFront ---@overload fun(xi:int, yi:int, frontID:int):boolean ---@overload fun(xi:int, yi:int, frontID:int, isDestroyFragile:boolean):boolean ---@param xi int ---@param yi int ---@param frontID int ---@param isDestroyFragile boolean ---@param isCheckingEntities boolean ---@return boolean function MapUtils.CanPlaceFront(xi, yi, frontID, isDestroyFragile, isCheckingEntities) end ---PlaceFront ---@overload fun(xi:int, yi:int, frontID:int):boolean ---@overload fun(xi:int, yi:int, frontID:int, isDestroyFragile:boolean):boolean ---@overload fun(xi:int, yi:int, frontID:int, isDestroyFragile:boolean, showEffect:boolean):boolean ---@param xi int ---@param yi int ---@param frontID int ---@param isDestroyFragile boolean ---@param showEffect boolean ---@param playSound boolean ---@return boolean function MapUtils.PlaceFront(xi, yi, frontID, isDestroyFragile, showEffect, playSound) end ---RemoveFront ---@overload fun(xi:int, yi:int):boolean ---@overload fun(xi:int, yi:int, showEffect:boolean):boolean ---@param xi int ---@param yi int ---@param showEffect boolean ---@param playSound boolean ---@return boolean function MapUtils.RemoveFront(xi, yi, showEffect, playSound) end ---RemoveFrontAndDrop ---@overload fun(xi:int, yi:int):boolean ---@overload fun(xi:int, yi:int, isDropOriginal:boolean):boolean ---@overload fun(xi:int, yi:int, isDropOriginal:boolean, dropFortune:int):boolean ---@overload fun(xi:int, yi:int, isDropOriginal:boolean, dropFortune:int, showEffect:boolean):boolean ---@param xi int ---@param yi int ---@param isDropOriginal boolean ---@param dropFortune int ---@param showEffect boolean ---@param playSound boolean ---@return boolean function MapUtils.RemoveFrontAndDrop(xi, yi, isDropOriginal, dropFortune, showEffect, playSound) end ---HasWall ---@param xi int ---@param yi int ---@return boolean function MapUtils.HasWall(xi, yi) end ---GetWallID ---@param xi int ---@param yi int ---@return int function MapUtils.GetWallID(xi, yi) end ---CanSetWall ---@param xi int ---@param yi int ---@param wallID int ---@return boolean function MapUtils.CanSetWall(xi, yi, wallID) end ---SetWall ---@overload fun(xi:int,yi:int,id:int):boolean ---@overload fun(xi:int,yi:int,id:int,showEffect:boolean):boolean ---@overload fun(xi:int,yi:int,id:int,showEffect:boolean,playSound:boolean):boolean ---@param xi int ---@param yi int ---@param id int ---@param showEffect boolean ---@param playSound boolean ---@return boolean function MapUtils.SetWall(xi, yi, id, showEffect, playSound) end ---CanPlaceWall ---@param xi int ---@param yi int ---@param wallID int ---@return boolean function MapUtils.CanPlaceWall(xi, yi, wallID) end ---PlaceWall ---@overload fun(xi:int,yi:int,id:int):boolean ---@overload fun(xi:int,yi:int,id:int,showEffect:boolean):boolean ---@overload fun(xi:int,yi:int,id:int,showEffect:boolean,playSound:boolean):boolean ---@param xi int ---@param yi int ---@param id int ---@param showEffect boolean ---@param playSound boolean ---@return boolean function MapUtils.PlaceWall(xi, yi, id, showEffect, playSound) end ---RemoveWall ---@overload fun(xi:int,yi:int):boolean ---@overload fun(xi:int,yi:int,showEffect:boolean):boolean ---@param xi int ---@param yi int ---@param showEffect boolean ---@param playSound boolean function MapUtils.RemoveWall(xi, yi, showEffect, playSound) end ---RemoveWallAndDrop ---@overload fun(xi:int, yi:int):boolean ---@overload fun(xi:int, yi:int, isDropOriginal:boolean):boolean ---@overload fun(xi:int, yi:int, isDropOriginal:boolean, dropFortune:int):boolean ---@overload fun(xi:int, yi:int, isDropOriginal:boolean, dropFortune:int, showEffect:boolean):boolean ---@param xi int ---@param yi int ---@param isDropOriginal boolean ---@param dropFortune int ---@param showEffect boolean ---@param playSound boolean ---@return boolean function MapUtils.RemoveWallAndDrop(xi, yi, isDropOriginal, dropFortune, showEffect, playSound) end ---HasLiquid ---@param xi int ---@param yi int ---@return boolean function MapUtils.HasLiquid(xi, yi) end ---GetLiquidID ---@param xi int ---@param yi int ---@return int function MapUtils.GetLiquidID(xi, yi) end ---GetLiquidIDAmount ---@param xi int ---@param yi int ---@return int,int function MapUtils.GetLiquidIDAmount(xi, yi) end ---SetLiquid ---@overload fun(xi:int,yi:int,liquidID:int):boolean ---@param xi int ---@param yi int ---@param liquidID int ---@param amount int ---@return boolean function MapUtils.SetLiquid(xi, yi, liquidID, amount) end ---RemoveLiquid ---@param xi int ---@param yi int ---@return boolean function MapUtils.RemoveLiquid(xi, yi) end ---TriggerLiquid ---@param xi int ---@param yi int function MapUtils.TriggerLiquid(xi, yi) end ---TriggerSignal ---@param xi int ---@param yi int ---@param isTurningOn boolean ---@return boolean function MapUtils.TriggerSignal(xi, yi, isTurningOn) end ---DelayTriggerSignal ---@param xi int ---@param yi int ---@param isTurningOn boolean ---@param delayTicks int ---@return boolean function MapUtils.DelayTriggerSignal(xi, yi, isTurningOn, delayTicks) end ---GetBlockEntity ---@param blockEntityID int ---@param xi int ---@param yi int ---@return BlockEntity function MapUtils.GetBlockEntity(blockEntityID, xi, yi) end ---CreateBlockEntity ---@param blockEntityID int ---@param xi int ---@param yi int function MapUtils.CreateBlockEntity(blockEntityID,xi,yi) end ---WeaponCollideWithMap ---@param obb ObbDouble ---@param isDestroyByWeapon boolean ---@return boolean,boolean function MapUtils.WeaponCollideWithMap(obb, isDestroyByWeapon) end ---PlayAnimation ---@param xi int ---@param yi int ---@param startFrameIndex int ---@param totalFrames int ---@param frameSpeed int ---@param isPositiveDirection boolean function MapUtils.PlayAnimation(xi, yi, startFrameIndex, totalFrames, frameSpeed, isPositiveDirection) end ---SetAnimationIndex ---@param xi int ---@param yi int ---@param animationIndex int function MapUtils.SetAnimationIndex(xi, yi, animationIndex) end ---SyncUnit ---@param xi int ---@param yi int function MapUtils.SyncUnit(xi, yi) end ---SetWireVisible ---@param visible boolean function MapUtils.SetWireVisible(visible) end ---IsWireVisible ---@return boolean function MapUtils.IsWireVisible() end ---HasWire ---@param xi int ---@param yi int ---@return boolean function MapUtils.HasWire(xi, yi) end ---GetWireID ---@param xi int ---@param yi int ---@return int function MapUtils.GetWireID(xi, yi) end ---SetWire ---@param xi int ---@param yi int ---@param wireID int ---@return boolean function MapUtils.SetWire(xi, yi, wireID) end ---RemoveWire ---@param xi int ---@param yi int ---@return boolean function MapUtils.RemoveWire(xi, yi) end ---RemoveWireAndDrop ---@overload fun(xi:int,yi:int):boolean ---@param xi int ---@param yi int ---@param playSound boolean ---@return boolean function MapUtils.RemoveWireAndDrop(xi, yi, playSound) end ---SetWireActivate ---@param xi int ---@param yi int ---@param activated boolean function MapUtils.SetWireActivate(xi, yi, activated) end ---DoRandomTick ---@param xi int ---@param yi int function MapUtils.DoRandomTick(xi, yi) end ---SetRenderPreview ---@param blockID int ---@param xi int ---@param yi int ---@param canPlace boolean ---@param playerCenterX double ---@param playerCenterY double function MapUtils.SetBlockRenderPreview(blockID, centerX, centerY, canPlace, playerCenterX, playerCenterY) end function MapUtils.ClearBlockRenderPreview() end return MapUtils ================================================ FILE: apis/MiscUtils.lua ================================================ ---@class MiscUtils ---@field screenX double ---@field screenY double ---@field screenWidth int ---@field screenHeight int ---@field inGame boolean ---@field isSinglePlayerMode boolean ---@field isNight boolean local MiscUtils = {} ---CreateExplosion ---@overload fun(xi:int, yi:int, power:double, hurtNpc:boolean, hurtPlayer:boolean) ---@overload fun(xi:int, yi:int, power:double, hurtNpc:boolean, hurtPlayer:boolean, killTiles:boolean) ---@overload fun(xi:int, yi:int, power:double, hurtNpc:boolean, hurtPlayer:boolean, killTiles:boolean, killBack:boolean) ---@overload fun(xi:int, yi:int, power:double, hurtNpc:boolean, hurtPlayer:boolean, killTiles:boolean, killBack:boolean, makeSound:boolean) ---@param xi int ---@param yi int ---@param power double ---@param hurtNpc boolean ---@param hurtPlayer boolean ---@param killTiles boolean ---@param killBack boolean ---@param makeSound boolean ---@param tileLimit int function MiscUtils.CreateExplosion(xi, yi, power, hurtNpc, hurtPlayer, killTiles, killBack, makeSound, tileLimit) end ---UnicastUTF8 ---@param player Player ---@param message string function MiscUtils.UnicastUTF8(player, message) end ---BroadcastUTF8 ---@param message string function MiscUtils.BroadcastUTF8(message) end ---SetDayTime ---@param dayTime int function MiscUtils.SetDayTime(dayTime) end ---GetDayTime ---@return int function MiscUtils.GetDayTime() end ---SetDaySpeed ---@param daySpeed int function MiscUtils.SetDaySpeed(daySpeed) end ---@return int function MiscUtils.GetDaySpeed() end ---SetWeatherTime ---@param weatherTime int function MiscUtils.SetWeatherTime(weatherTime) end ---@return int function MiscUtils.GetWeatherTime() end ---SetDayTimeFormat ---@param hours int ---@param minutes int ---@param seconds int function MiscUtils.SetDayTimeFormat(hours, minutes, seconds) end ---@return int,int,int function MiscUtils.GetDayTimeFormat() end ---RayDistance ---@overload fun(fromX:double, fromY:double, shootAngle:double):double ---@param fromX double ---@param fromY double ---@param shootAngle double ---@param maxDistance int ---@return double function MiscUtils.RayDistance(fromX, fromY, shootAngle, maxDistance) end ---RayReach ---@param fromX double ---@param fromY double ---@param toX double ---@param toY double ---@return boolean function MiscUtils.RayReach(fromX, fromY, toX, toY) end function MiscUtils.SaveAll() end ---SetAutoSaveEnabled ---@param enabled boolean function MiscUtils.SetAutoSaveEnabled(enabled) end ---GetPortNumber ---@return int function MiscUtils.GetPortNumber() end ---SetPVP ---@param enabled boolean function MiscUtils.SetPVP(enabled) end ---GetPVP ---@return boolean function MiscUtils.GetPVP() end ---SetSafeBlow ---@param enabled boolean function MiscUtils.SetSafeBlow(enabled) end ---GetSafeBlow ---@return boolean function MiscUtils.GetSafeBlow() end ---SetGameMode ---@param gameMode int function MiscUtils.SetGameMode(gameMode) end ---GetGameMode ---@return int function MiscUtils.GetGameMode() end ---@return Player[] function MiscUtils.GetOnlinePlayerList() end ---KickPlayer ---@param playerName string function MiscUtils.KickPlayer(playerName) end ---KickAllPlayers function MiscUtils.KickAllPlayers() end ---@return string[] function MiscUtils.GetBlackList() end ---Ban ---@param ip string function MiscUtils.Ban(ip) end ---RemoveBan ---@param id string function MiscUtils.RemoveBan(id) end ---AddTips ---@param x double ---@param y double ---@param tipsText string ---@param color Color function MiscUtils.AddTips(x, y, tipsText, color) end ---@return double function MiscUtils.GetMapDisplayScale() end ---SetMapDisplayScale ---@param scale double function MiscUtils.SetMapDisplayScale(scale) end return MiscUtils ================================================ FILE: apis/Mod.lua ================================================ ---@class Mod 描述一个模组,维护模组的基本信息。 ---@field modId string 模组的命名空间。 ---@field displayName string 模组显示名称。 ---@field version string 模组版本号。 ---@field gameVersion string 游戏版本号。 ---@field assetRootPath string 模组文件夹在assets系统中的文件夹根目录。 ---@field current Mod 返回当前执行的脚本环境的模组。 ---@field serverBoundPacket ServerBoundPacket ---@field clientBoundPacket ClientBoundPacket ---@field registry Registry ---@field modList Array local Mod = {} ---RegisterClientGuiLoaderCallback ---@param callback function|table ---@return ListenerID function Mod:RegisterClientGuiLoaderCallback(callback) end ---@param callback function|table ---@return ListenerID function Mod:RegisterServerGuiLoaderCallback(callback) end ---RegisterClientGuiLoaderCallback ---@param callback function|table ---@return ListenerID function Mod:RegisterClientBoundReaderCallback(callback) end ---@param callback function|table ---@return ListenerID function Mod:RegisterServerBoundReaderCallback(callback) end ---@param callback function|table ---@return ListenerID function Mod:RegisterWorldServerLoader(callback) end ---@param callback function|table ---@return ListenerID function Mod:RegisterWorldServerSaver(callback) end ---通过模组命名空间,返回已加载模组。 ---@param modID string 模组的命名空间。 ---@return nil|Mod 已加载的模组,如果模组不存在,返回nil。 function Mod.GetByID(modID) end return Mod ================================================ FILE: apis/ModBlock.lua ================================================ ---@class ModBlock local ModBlock = {} ---OnPlayerCollide ---@param xi int ---@param yi int ---@param player Player ---@param collisionDirection int function ModBlock.OnPlayerCollide(xi, yi, player, collisionDirection) end ---OnPlayerOverlap ---@param xi int ---@param yi int ---@param player Player function ModBlock.OnPlayerOverlap(xi, yi, player) end ---UpdateScreen ---@param xi int ---@param yi int ---@param tickTime int function ModBlock.UpdateScreen(xi, yi, tickTime) end ---RenderFurniture ---@param xi int ---@param yi int ---@param tickTime int function ModBlock.RenderFurniture(xi, yi, tickTime) end ---PreRenderFurniture ---@param xi int ---@param yi int ---@param tickTime int function ModBlock.PreRenderFurniture(xi, yi, tickTime) end ---PostRenderFurniture ---@param xi int ---@param yi int ---@param tickTime int function ModBlock.PostRenderFurniture(xi, yi, tickTime) end ---OnRandomTick ---@param xi int ---@param yi int function ModBlock.OnRandomTick(xi, yi) end ---OnPlaced ---@param xi int ---@param yi int function ModBlock.OnPlaced(xi, yi) end ---OnClicked ---@param xi int ---@param yi int ---@param parameterClick ParameterClick function ModBlock.OnClicked(xi, yi, parameterClick) end ---OnSignal ---@param xi int ---@param yi int ---@param isActivated boolean function ModBlock.OnSignal(xi, yi, isActivated) end ---OnDestroy ---@param xi int ---@param yi int ---@param parameterDestroy ParameterDestroy function ModBlock.OnDestroy(xi, yi, parameterDestroy) end return ModBlock ================================================ FILE: apis/ModBlockEntity.lua ================================================ ---@class ModBlockEntity ---@field blockEntity BlockEntity local ModBlockEntity = {} function ModBlockEntity:OnPlaced() end function ModBlockEntity:Init() end function ModBlockEntity:CanUpdate() end function ModBlockEntity:Update() end ---OnKilled ---@param parameterDestroy ParameterDestroy function ModBlockEntity:OnKilled(parameterDestroy) end ---OnClicked ---@param parameterClick ParameterClick function ModBlockEntity:OnClicked(parameterClick) end function ModBlockEntity:OnActivated(isActive) end ---@return table function ModBlockEntity:Save() end ---Load ---@param tagTable table function ModBlockEntity:Load(tagTable) end return ModBlockEntity ================================================ FILE: apis/ModItem.lua ================================================ ---@class ModItem ---@field itemStack ItemStack local ModItem = {} function ModItem:Init() end ---DrawIcon ---@param position Vector2 ---@param color Color ---@param spriteExData SpriteExData function ModItem:DrawIcon(position, color, spriteExData) end ---OnHeld ---@param player Player function ModItem:OnHeld(player) end ---OnHeldRender ---@param player Player function ModItem:OnHeldRender(player) end ---OnUsed ---@param player Player function ModItem:OnUsed(player) end ---CanUse ---@param player Player ---@return boolean function ModItem:CanUse(player) end ---OnHeldByNpc ---@param npc Npc function ModItem:OnHeldByNpc(npc) end ---OnUsedByNpc ---@param npc Npc function ModItem:OnUsedByNpc(npc) end ---ModifyHitNpc ---@param npc Npc ---@param baseAttack Attack ---@return boolean function ModItem:ModifyHitNpc(npc, baseAttack) end ---ModifyHitPlayer ---@param player Player ---@param baseAttack Attack ---@return boolean function ModItem:ModifyHitPlayer(player, baseAttack) end ---Load ---@param tagTable table function ModItem:Load(tagTable) end ---@return table function ModItem:Save() end return ModItem ================================================ FILE: apis/ModNpc.lua ================================================ ---@class ModNpc ---@field npc Npc ---@field syncData table local ModNpc = {} --- This function is called once when the NPC is spawned. --- --- NPC生成时调用一次该函数。 function ModNpc:Init() end --- --- --- NPC每帧运行Update()函数前调用,如果返回true则执行所有Update逻辑,返回false则不执行所有Update逻辑。可在该函数写入新的逻辑,并屏蔽原有逻辑。默认返回true。 ---@return boolean function ModNpc:CanUpdate() return true end --- Called when NPC runs every update tick, usually write logic in this function. --- --- NPC每帧运行时调用,通常在该函数内编写运动等逻辑。 function ModNpc:Update() end --- Called before the NPC runs the `Update()` function every update tick. --- It is usually used to insert new logic before the original logic. --- --- NPC每帧运行`Update()`函数前调用。通常用于在原逻辑前插入新逻辑。 function ModNpc:PreUpdate() end --- Called after the NPC runs the `Update()` function every update tick. --- It is usually used to insert new logic after the original logic. --- --- NPC每帧运行`Update()`函数后调用。通常用于追加逻辑。 function ModNpc:PostUpdate() end --- --- --- NPC每帧绘制前调用,如果返回true则执行所有Draw逻辑,返回false则不执行所有Draw逻辑。可在该函数写入新的逻辑,并屏蔽原有逻辑。默认返回true。 ---@return boolean function ModNpc:CanDraw() return true end --- Called before each tick of NPC drawing, --- just write custom drawing behavior in this function. --- --- NPC每帧绘制前调用,在该函数内编写自定义绘制属性。 function ModNpc:OnDraw() end function ModNpc:OnRender() end --- Called when NPC was killed. --- --- NPC死亡时调用一次该函数。 function ModNpc:OnKilled() end ---ModifyHit ---@param attack Attack ---@return boolean function ModNpc:ModifyHit(attack) end --- Called when NPC collides the tiles. --- --- NPC与图块碰撞时调用该函数。 --- @param oldSpeedX double The X speed before colliding tiles. (击中图块前一帧的横向速度) --- @param oldSpeedY double The Y speed before colliding tiles. (击中图块前一帧的纵向速度) function ModNpc:OnTileCollide(oldSpeedX, oldSpeedY) end function ModNpc:OnLoot() end ---@return table function ModNpc:Save() end ---Load ---@param tagTable table function ModNpc:Load(tagTable) end return ModNpc ================================================ FILE: apis/ModProjectile.lua ================================================ ---@class ModProjectile ---@field projectile Projectile local ModProjectile = {} return ModProjectile ================================================ FILE: apis/ModTextureData.lua ================================================ ---@class ModTextureData ---@field textureLocation TextureLocation ---@field width int ---@field height int ---@field frameXs int ---@field frameYs int ---@field frameSpeed int ---@field tagUsage int ---@field loopPlay boolean ---@field userDisabled boolean local ModTextureData = {} return ModTextureData ================================================ FILE: apis/ModTextureUtils.lua ================================================ ---@class ModTextureUtils local ModTextureUtils = {} ---GetData ---@param modTextureID int ---@return ModTextureData function ModTextureUtils.GetData(modTextureID) end return ModTextureUtils ================================================ FILE: apis/Npc.lua ================================================ ---@API ---@class Npc:Entity 描述一个NPC实体。 ---@field entityIndex EntityIndex ---@field id int 当前NPC的动态ID。 ---@field dataWatcher DataWatcher ---@field data table ---@field texture TextureLocation ---@field baseAttack Attack 当前NPC的基础攻击属性。 ---@field maxSpeed double 当前NPC的最大横向移动速度。每帧重置为所在环境(流体黏性等)决定的最大移动速度。 ---@field defaultGravity double Read-only 当前NPC的默认重力加速度。 ---@field gravity double 当前NPC的纵向加速度。每帧重置为作用了所在环境纵向受力以及重力后的纵向加速度。 ---@field defaultMaxFallSpeed double Read-only 当前NPC的默认最大下落速度。 ---@field maxFallSpeed double 当前NPC的最大下落速度。每帧重置为作用了所在环境纵向阻力后的最大下落速度。 ---@field jumpForce double 当前NPC的跳跃力度。每帧重置为作用了所在环境纵向阻力后的跳跃力度。 ---@field noMove boolean 决定当前NPC是否停止行走。 ---@field inLiquid boolean Read-only 当前NPC是否处在流体环境中。 ---@field oldInLiquid boolean Read-only 上一帧的NPC是否处在流体环境中。 ---@field isEnemy boolean Read-only 当前NPC是否会伤害玩家。 ---@field state int NPC当前在简单有限状态机中的状态。 ---@field stateTimer int NPC的状态机计时器。 ---@field hurry boolean 当前NPC是否为匆忙状态。匆忙状态下随机走模板不会停下来。 ---@field maxHealth int 当前NPC的生命值上限。 ---@field health int 当前NPC的生命值。 ---@field angry boolean 当前NPC是否为愤怒状态。易怒的NPC在被玩家击中后会将该玩家视为目标,并置愤怒状态为true。 ---@field animation int NPC当前执行的动画状态。通常用于表示骨骼模型的动画状态。 ---@field animationTickTime int NPC在当前动画索引所经过的时间。每帧自动自增1,当动画状态切换时自动重置为0。 ---@field watchAngle double Read-only NPC的目视角度。若NPC目标存在,则总是目视目标。否则总是根据朝向水平目视。 ---@field type NpcType Read-only NPC类型。 ---@field spawnCount double 占用生成量。 ---@field defaultKnockBackDefenseValue double 击退抗性。 ---@field toolUseRate double 工具使用概率。 ---@field maxDisappearTime int 最大消失时间。 ---@field defaultDefenseValue int 防御力。 ---@field defaultAttackValue int 攻击力。 ---@field defaultCritValue int 双倍暴击率百分比。 ---@field defaultKnockBackValue int 击退力。 ---@field movement int 运动方式。 ---@field gfxOffsetX int 贴图偏移量X。 ---@field gfxOffsetY int 贴图偏移量Y。 ---@field gfxWidth int 贴图宽度。 ---@field gfxHeight int 贴图高度。 ---@field frameStyle int 贴图方式 0-不分左右 1-分左右。 ---@field exps int 经验值。 ---@field checkTargetDistance int 检测目标的半径。 ---@field special int 特殊值。 ---@field magicRate int 产生魔法碎片概率的反比。 ---@field friendly boolean 是否友好。 ---@field hasGravity boolean 是否受重力。 ---@field canClimbWall boolean 是否能爬墙。 ---@field isForeground boolean 是否置前。 ---@field isAntiLava boolean 是否抵抗岩浆。 ---@field noFixByBlock boolean 是否不根据方块修正位置。 ---@field willBurnUnderSun boolean 是否白天自燃。 ---@field defaultAngry boolean 是否易怒。 ---@field isBoss boolean 是否作为BOSS。 ---@field noShowHp boolean 是否不显示血条。 ---@field noBurnSound boolean 是否不播放燃烧音效。 ---@field usingBoneModule boolean Read-only 是否使用骨骼模型。 ---@field isCheckPlayerTarget boolean 是否自动检测玩家目标。 ---@field isVisionNoCrossTile boolean 是否视野不穿墙。 ---@field isAutoSave boolean 是否保存到存档。 ---@field noHurt boolean ---@field noCollisionByWeapon boolean ---@field noLooting boolean ---@field isWatchAngleForTarget boolean ---@field netUpdate boolean 是否使用逻辑网络同步。 local Npc = {} --- 不掉落物品直接清除当前NPC对象。 function Npc:Kill() end ---KillByStrike ---@overload fun(hitAngle:double) ---@overload fun(hitAngle:double,hurtSound:boolean) ---@param hitAngle double ---@param hurtSound boolean ---@param lootingLevel int function Npc:KillByStrike(hitAngle, hurtSound, lootingLevel) end --- 制造一个对当前NPC的伤害。 ---@overload fun(attack:Attack) ---@overload fun(attack:Attack,hitAngle:double) ---@overload fun(attack:Attack,hitAngle:double,immune:boolean) ---@overload fun(attack:Attack,hitAngle:double,immune:boolean,hurtSound:boolean) ---@overload fun(attack:Attack,hitAngle:double,immune:boolean,hurtSound:boolean,lootingLevel:int) ---@param attack Attack 当前伤害属性。 ---@param hitAngle double @[ default `0.0` ] 产生伤害的角度。 ---@param immune boolean @[ default `true` ] 产生当前伤害后是否让NPC处于无敌帧状态。 ---@param hurtSound boolean @[ default `true` ] 是否播放NPC受伤音效。 ---@param lootingLevel int @[ default `0` ] 掠夺等级。 function Npc:Strike(attack, hitAngle, immune, hurtSound, lootingLevel) end --- 制造一个某玩家对当前NPC的伤害。 ---@overload fun(player:Player,attack:Attack) ---@overload fun(player:Player,attack:Attack,hitAngle:double) ---@overload fun(player:Player,attack:Attack,hitAngle:double,immune:boolean) ---@overload fun(player:Player,attack:Attack,hitAngle:double,immune:boolean,hurtSound:boolean) ---@overload fun(player:Player,attack:Attack,hitAngle:double,immune:boolean,hurtSound:boolean,lootingLevel:int) ---@param player Player 表示造成伤害的玩家。 ---@param attack Attack 当前伤害属性。 ---@param hitAngle double @[ default `0.0` ] 产生伤害的角度。 ---@param immune boolean @[ default `true` ] 产生当前伤害后是否让NPC处于无敌帧状态。 ---@param hurtSound boolean @[ default `true` ] 是否播放NPC受伤音效。 ---@param lootingLevel int @[ default `0` ] 掠夺等级。 function Npc:StrikeFromPlayer(player, attack, hitAngle, immune, hurtSound, lootingLevel) end --- 制造一个某玩家对当前NPC的伤害。 ---@overload fun(npc:Npc,attack:Attack) ---@overload fun(npc:Npc,attack:Attack,hitAngle:double) ---@overload fun(npc:Npc,attack:Attack,hitAngle:double,immune:boolean) ---@overload fun(npc:Npc,attack:Attack,hitAngle:double,immune:boolean,hurtSound:boolean) ---@overload fun(npc:Npc,attack:Attack,hitAngle:double,immune:boolean,hurtSound:boolean,lootingLevel:int) ---@param npc Npc 表示造成伤害的NPC。 ---@param attack Attack 当前伤害属性。 ---@param hitAngle double @[ default `0.0` ] 产生伤害的角度。 ---@param immune boolean @[ default `true` ] 产生当前伤害后是否让NPC处于无敌帧状态。 ---@param hurtSound boolean @[ default `true` ] 是否播放NPC受伤音效。 ---@param lootingLevel int @[ default `0` ] 掠夺等级。 function Npc:StrikeFromNpc(npc, attack, hitAngle, immune, hurtSound, lootingLevel) end --- 为当前NPC添加一个状态效果。若原状态效果存在,以最长时间为新状态效果的持续时间。 ---@param buffID int 状态效果ID。 ---@param buffTime int 状态效果持续时间。 function Npc:AddBuff(buffID, buffTime) end --- 移除一个状态效果。 ---@param buffID int function Npc:RemoveBuff(buffID) end --- 移除全部状态效果。 function Npc:RemoveAllBuff() end --- 返回NPC是否拥有指定状态效果。 ---@param buffID int 状态效果ID。 ---@return boolean function Npc:HasBuff(buffID) end --- 返回NPC是否存在状态效果。 ---@return boolean function Npc:HasAnyBuff() end --- NPC尝试发出平时声音。平均经过`tryTimes`次发出一次平时声音。 ---@param tryTimes int function Npc:TryMakeSound(tryTimes) end --- NPC发出平时声音。 function Npc:MakeSound() end --- 站立静止不动。 ---@overload fun() ---@param faceToTarget boolean @[ default `true` ] 是否始终面朝玩家。 function Npc:Stand(faceToTarget) end --- 随机地朝一个方向行走或停下或转弯。 --- 停下时闲置`idleTime ± idleTimeOffset`范围内随机时间。 --- 朝一个方向行走时持续`walkTime ± walkTimeOffset`范围内随机时间。 --- 使用内置寻路逻辑,遇到墙壁会尝试跳跃3次。 ---@overload fun() ---@overload fun(idleTime:int) ---@overload fun(idleTime:int,idleTimeOffset:int) ---@overload fun(idleTime:int,idleTimeOffset:int,walkTime:int) ---@param idleTime int @[ default `128` ] ---@param idleTimeOffset int @[ default `64` ] ---@param walkTime int @[ default `96` ] ---@param walkTimeOffset int @[ default `32` ] function Npc:RandomWalk(idleTime, idleTimeOffset, walkTime, walkTimeOffset) end --- 持续行走而不停下。使用内置寻路逻辑,遇到墙壁会尝试跳跃3次。 ---@overload fun() ---@param followTarget boolean @[ default `true` ] 表示在目标存在的情况下,尽可能靠近目标。 function Npc:KeepWalking(followTarget) end --- 目标存在时,调用`KeepWalking(followTarget)`,否则调用`RandomWalk()`。 ---@overload fun() ---@param followTarget boolean @[ default `true` ] 表示在目标存在的情况下,尽可能靠近目标。 function Npc:Walk(followTarget) end --- 在流体中游泳,在空气中蹦跶。目标不存在时,在流体中随机运动。 ---@overload fun() ---@param followTarget boolean @[ default `true` ] 表示在目标存在的情况下,尽可能靠近目标。 function Npc:Swim(followTarget) end --- 在空气中飞行。 ---@overload fun() ---@overload fun(followTarget:boolean) ---@overload fun(followTarget:boolean,force:double) ---@param followTarget boolean @[ default `true` ] 表示在目标存在的情况下,尽可能靠近目标,否则随机飞行。 ---@param force double @[ default '0.1' ] 表示飞向目标的力。 ---@param gradientSpeed boolean @[ default `false` ] 表示是否使用渐变速度,否则运动速度的向量大小总是恒定的。 function Npc:Fly(followTarget, force, gradientSpeed) end --- 传送NPC自己到以自己为圆心的圆形区域随机位置。 ---@overload fun(distance:int):boolean ---@overload fun(distance:int,noToAir:boolean):boolean ---@param distance int 圆形区域的半径。 ---@param noToAir boolean @[ default `true` ] 表示是否传送到地面上。 ---@param noToLiquid boolean @[ default true` ] 表示是否不传送到流体内。 ---@return boolean 成功传送返回true,失败返回false。 function Npc:RandomTeleport(distance, noToAir, noToLiquid) end --- --- ---@return ModNpc function Npc:GetModNpc() end --- --- ---@param globalNpcName string ---@return GlobalNpc function Npc:GetGlobalNpc(globalNpcName) end function Npc:SyncAll() end return Npc ================================================ FILE: apis/NpcType.lua ================================================ ---@class NpcType Enum class (Enum Format: `NPC_TYPE_XXX`) local NpcType = {} ---@type NpcType NPC_TYPE_NORMAL = nil ---@type NpcType NPC_TYPE_ANIMAL = nil ---@type NpcType NPC_TYPE_VILLAGER = nil ---@type NpcType NPC_TYPE_ARTHROPODS = nil ---@type NpcType NPC_TYPE_SMITE = nil ---@type NpcType NPC_TYPE_BOSS = nil return NpcType ================================================ FILE: apis/NpcUtils.lua ================================================ ---@class NpcUtils @NPC Util Module (NPC通用模块) local NpcUtils = {} ---@return Npc[] function NpcUtils.GetAllEntities() end ---Get ---@param entityIndex EntityIndex ---@return Npc function NpcUtils.Get(entityIndex) end ---IsAlive ---@param entityIndex EntityIndex ---@return boolean function NpcUtils.IsAlive(entityIndex) end ---Create an NPC at the specified location and return the created NPC entity. --- ---在指定位置创建一个NPC,返回创建好的NPC实体。 ---@overload fun(id:int,x:double,y:double):Npc ---@overload fun(id:int,x:double,y:double,speedX:double):Npc ---@param id int ---@param x double @The x coordinate (x坐标) ---@param y double @The y coordinate (y坐标) ---@param speedX double @[ default '0.0' ] (横向速度,默认0) ---@param speedY double @[ default '0.0' ] (纵向速度,默认0) ---@return Npc @创建好的NPC实体 function NpcUtils.Create(id, x, y, speedX, speedY) end ---WeaponCollide ---@overload fun(itemStack:ItemStack,hitAngle:double,obb:ObbDouble,attackInAndOut:Attack,outNpcIndex:EntityIndex):boolean ---@param itemStack ItemStack ---@param hitAngle double ---@param obb ObbDouble ---@param attackInAndOut Attack ---@param ignoreNpcIndex EntityIndex ---@param outNpcIndex EntityIndex ---@return boolean function NpcUtils.WeaponCollide(itemStack, hitAngle, obb, attackInAndOut, ignoreNpcIndex, outNpcIndex) end ---SearchByRect ---@param x double ---@param y double ---@param width int ---@param height int ---@return Npc[] function NpcUtils.SearchByRect(x, y, width, height) end ---SearchByCircle ---@param x double ---@param y double ---@param radius int ---@return Npc[] function NpcUtils.SearchByCircle(x, y, radius) end ---SearchNearestNpc ---@param x double ---@param y double ---@param radius int ---@param noCrossTiles boolean ---@return Npc function NpcUtils.SearchNearestNpc(x, y, radius, noCrossTiles) end ---SearchNearestEnemy ---@param x double ---@param y double ---@param radius int ---@param noCrossTiles boolean ---@return Npc function NpcUtils.SearchNearestEnemy(x, y, radius, noCrossTiles) end return NpcUtils ================================================ FILE: apis/OreDataGroup.lua ================================================ ---@class OreData ---@field oreID int 矿物的方块id ---@field density int 矿脉密度(每区块生成次数) ---@field radius int 矿脉半径 ---@field startYi int 矿脉开始分布的Y值 ---@field endYi int 矿脉结束分布的Y值 local OreData = {} ---@class OreDataGroup ---@field name string 矿物组名称 ---@field dataList OreData[] 矿物列表 local OreDataGroup = {} return OreDataGroup ================================================ FILE: apis/ParameterClick.lua ================================================ ---@class ParameterClick ---@field playerEntityIndex EntityIndex local ParameterClick = {} return ParameterClick ================================================ FILE: apis/ParameterDestroy.lua ================================================ ---@class ParameterDestroy ---@field silkTouch int ---@field fortune int ---@field boom boolean ---@field dropItem boolean ---@field showEffect boolean ---@field playSound boolean local ParameterDestroy = {} return ParameterDestroy ================================================ FILE: apis/ParameterPlace.lua ================================================ ---@class ParameterPlace ---@field placeDir int local ParameterPlace = {} return ParameterPlace ================================================ FILE: apis/ParameterStrike.lua ================================================ ---@class ParameterStrike ---@field lootingLevel int local ParameterStrike = {} return ParameterStrike ================================================ FILE: apis/Player.lua ================================================ ---@class Player:Entity ---@field entityIndex EntityIndex ---@field dataWatcher DataWatcher ---@field remoteDataWatcher DataWatcher ---@field lookAngle double ---@field facingDirection boolean ---@field hostXi int ---@field hostYi int ---@field biomeType int ---@field biomeID int ---@field defaultMaxSpeed double ---@field defaultJumpTime int ---@field defaultJumpSpeed double ---@field defaultFallSpeed double ---@field speedRate double ---@field jumpRate double ---@field jumpSpeedRate double ---@field fallSpeedRate double ---@field digSpeedRate double ---@field isInvisibility boolean ---@field health int ---@field maxHealth int ---@field mana int ---@field maxMana int ---@field expLevel int ---@field remainExp int ---@field isNoBreathing boolean ---@field breathRate double ---@field foodLevel int ---@field foodSaturationLevel int ---@field touchLiquidID int ---@field inLiquid boolean ---@field oldInLiquid boolean ---@field gameMode int ---@field op int ---@field name string ---@field ip string ---@field port int ---@field isCurrentClientPlayer boolean ---@field mouseInventory Inventory ---@field backpackInventory Inventory ---@field equipmentInventory Inventory ---@field enderInventory Inventory ---@field heldSlotIndex int ---@field heldSlotIndexJustChanged boolean ---@field smartMode SmartMode_Value ---@field isSmartPositionFound boolean ---@field holdColdTime int ---@field isDownPlatform boolean ---@field baseAttack Attack ---@field baseDefense Defense ---@field ignoreCollisionWithTiles boolean ---@field dying boolean local Player = {} ---Strike ---@overload fun(deathReason:int, attack:Attack) ---@overload fun(deathReason:int, attack:Attack, hitAngle:double) ---@overload fun(deathReason:int, attack:Attack, hitAngle:double, immune:boolean) ---@param deathReason int ---@param attack Attack ---@param hitAngle double ---@param immune boolean ---@param makeHurtSound boolean function Player:Strike(deathReason, attack, hitAngle, immune, makeHurtSound) end ---StrikeFromPlayer ---@overload fun(player:Player, attack:Attack) ---@overload fun(player:Player, attack:Attack, hitAngle:double) ---@overload fun(player:Player, attack:Attack, hitAngle:double, immune:boolean) ---@param player Player ---@param attack Attack ---@param hitAngle double ---@param immune boolean ---@param makeHurtSound boolean function Player:StrikeFromPlayer(player, attack, hitAngle, immune, makeHurtSound) end ---StrikeFromNpc ---@overload fun(npc:Npc, attack:Attack) ---@overload fun(npc:Npc, attack:Attack, hitAngle:double) ---@overload fun(npc:Npc, attack:Attack, hitAngle:double, immune:boolean) ---@param npc Npc ---@param attack Attack ---@param hitAngle double ---@param immune boolean ---@param makeHurtSound boolean function Player:StrikeFromNpc(npc, attack, hitAngle, immune, makeHurtSound) end ---Heal ---@overload fun(healValue:int) ---@param healValue int ---@param showTip boolean function Player:Heal(healValue, showTip) end ---AddMagic ---@overload fun(magicValue:int) ---@param magicValue int ---@param showTip boolean function Player:AddMagic(magicValue, showTip) end ---AddBreath ---@param breathValue double function Player:AddBreath(breathValue) end ---DecBreath ---@param breathValue double function Player:DecBreath(breathValue) end ---SetBreath ---@param breathValue double function Player:SetBreath(breathValue) end ---AddFood ---@param foodLevel int ---@param foodSaturationLevel int function Player:AddFood(foodLevel, foodSaturationLevel) end ---DecFood ---@overload fun(foodLevel:int) ---@param foodLevel int ---@param foodSaturationLevel int function Player:DecFood(foodLevel, foodSaturationLevel) end ---OpenGui ---@param mod Mod ---@param guiID int ---@param xi int ---@param yi int function Player:OpenGui(mod, guiID, xi, yi) end --- ---@param mod Mod ---@param guiID int ---@param xi int ---@param yi int function Player:OpenGuiRemote(mod, guiID, xi, yi) end ---CloseGui ---@param mod Mod ---@param guiID int function Player:CloseGui(mod, guiID) end ---IsGuiOpened ---@param mod Mod ---@param guiID int ---@return boolean function Player:IsGuiOpened(mod, guiID) end ---DropItem ---@overload fun(itemStack:ItemStack) ---@param itemStack ItemStack ---@param onlyDropOne boolean function Player:DropItem(itemStack, onlyDropOne) end ---RequestPlaceBlock ---@param xi int ---@param yi int ---@param slotIndex int ---@param isPlacingWall boolean ---@return boolean function Player:RequestPlaceBlock(xi, yi, slotIndex, isPlacingWall) end ---RequestPlaceWire ---@param xi int ---@param yi int ---@param slotIndex int ---@return boolean function Player:RequestPlaceWire(xi, yi, slotIndex) end ---RequestDigBlock ---@param xi int ---@param yi int ---@param slotIndex int ---@param isDiggingWall boolean ---@param toolType string ---@return boolean function Player:RequestDigBlock(xi, yi, slotIndex, isDiggingWall, toolType) end ---RequestClickMap ---@param xi int ---@param yi int ---@return boolean function Player:RequestClickMap(xi, yi) end ---SetSmartMode ---@overload fun(smartMode:SmartMode_Value) ---@param smartMode SmartMode_Value ---@param pointedXi int ---@param pointedYi int ---@param operatingWall boolean ---@param itemStack ItemStack ---@param toolType string function Player:SetSmartMode(smartMode, pointedXi, pointedYi, operatingWall, itemStack, toolType) end ---@return int,int function Player:GetSmartPosition() end --- --- ---@param globalPlayerName string ---@return GlobalPlayer function Player:GetGlobalPlayer(globalPlayerName) end ---FinishAdvancement ---@param advancementID int function Player:FinishAdvancement(advancementID) end ---ClearAdvancement ---@param advancementID int function Player:ClearAdvancement(advancementID) end ---ClearAllAdvancement function Player:ClearAllAdvancement() end ---IsAdvancementFinished ---@param advancementID int ---@return boolean function Player:IsAdvancementFinished(advancementID) end ---GetSaveString ---@return string function Player:GetSaveString() end ---GetLevelNeedExp ---@param expLevel int ---@return int function Player:GetLevelNeedExp(expLevel) end ---AddExperience ---@param amount int function Player:AddExperience(amount) end ---RemoveExpLevel ---@param level int function Player:RemoveExpLevel(level) end ---AddBuff ---@param buffID int ---@param buffTime int function Player:AddBuff(buffID, buffTime) end ---RemoveBuff ---@param buffID int function Player:RemoveBuff(buffID) end ---RemoveAllBuff function Player:RemoveAllBuff() end function Player:RemoveAllBuffExceptHealthCold() end ---HasBuff ---@param buffID int function Player:HasBuff(buffID) end ---HasAnyBuff function Player:HasAnyBuff() end ---@return Buff[] function Player:GetBuffList() end ---@return boolean function Player:GoHome() end function Player:TeleportToSpawn() end function Player:Teleport(x, y) end return Player ================================================ FILE: apis/PlayerUtils.lua ================================================ ---@class PlayerUtils local PlayerUtils = {} ---@return Player function PlayerUtils.GetCurrentClientPlayer() end ---Get ---@param entityIndex EntityIndex ---@return Player function PlayerUtils.Get(entityIndex) end ---IsAlive ---@param entityIndex EntityIndex ---@return boolean function PlayerUtils.IsAlive(entityIndex) end --WeaponCollide ---@overload fun(itemStack:ItemStack,hitAngle:double,obb:ObbDouble,attackInAndOut:Attack,outPlayerIndex:EntityIndex):boolean ---@param itemStack ItemStack ---@param hitAngle double ---@param obb ObbDouble ---@param attackInAndOut Attack ---@param ignorePlayerIndex EntityIndex ---@param outPlayerIndex EntityIndex ---@return boolean function PlayerUtils.WeaponCollide(itemStack, hitAngle, obb, attackInAndOut, ignorePlayerIndex, outPlayerIndex) end ---SearchByRect ---@param x double ---@param y double ---@param width int ---@param height int ---@return Player[] function PlayerUtils.SearchByRect(x, y, width, height) end ---SearchByCircle ---@param x double ---@param y double ---@param radius int ---@return Player[] function PlayerUtils.SearchByCircle(x, y, radius) end ---SearchNearestPlayer ---@param x double ---@param y double ---@param radius int ---@param noCrossTiles boolean ---@return Player function PlayerUtils.SearchNearestPlayer(x, y, radius, noCrossTiles) end return PlayerUtils ================================================ FILE: apis/Point.lua ================================================ -- Document -- Point Class: https://blueyoshi.gitbook.io/terracraft/en/mod/api/type#point -- -- Point类: https://blueyoshi.gitbook.io/terracraft/cn/mod/api/type#point -- -- Copyright (c) 2021. BlueYoshi(blueyoshi@foxmail.com) ---@class Point Represents a point. (表示一个点) ---@field x int The x coordinate of the point. (点的横坐标) ---@field y int The y coordinate of the point. (点的纵坐标) local Point = {} return Point ================================================ FILE: apis/Projectile.lua ================================================ ---@class Projectile:Entity ---@field id int The dynamic ID of the current projectile. (当前抛射物的动态ID) ---@field entityIndex EntityIndex ---@field common ProjectileCommon The common data of current projectile. (当前抛射物的通用数据) ---@field baseAttack Attack The basic attack property of the current projectile. (当前抛射物的基础攻击属性) ---@field targetTime int The target time of the current projectile. It is generally given when it is created, and is usually used to trigger related logic after reaching the target time. (当前抛射物的目标时间。一般由创建时给定,通常用于实现达到目标时间后触发相关逻辑) ---@field isCheckNpc boolean @[ default `false` ] Whether the current projectile is acting on the NPC. It is generally specified when it is created, and determines whether to collide or damage NPCs. (当前抛射物是否作用于NPC。一般由创建时指定,决定是否碰撞、伤害NPC) ---@field isCheckPlayer boolean @[ default `false` ] Whether the current projectile is acting on the player. It is generally specified when it is created, and determines whether to collide or damage players. (当前抛射物是否作用于玩家。一般由创建时指定,决定是否碰撞、伤害玩家) ---@field state int The current state of the projectile in a simple finite state machine. (抛射物当前在简单有限状态机中的状态) ---@field stateTimer int The timer use for state machine. (抛射物的状态机计时器) ---@field playerTargetIndex EntityIndex ---@field npcTargetIndex EntityIndex ---@field special int local Projectile = {} --- Destroy the current projectile object. --- --- 清除当前抛射物对象。 function Projectile:Kill() end return Projectile ================================================ FILE: apis/ProjectileUtils.lua ================================================ ---@class ProjectileUtils local ProjectileUtils = {} ---Get ---@param entityIndex EntityIndex ---@return Projectile function ProjectileUtils.Get(entityIndex) end ---IsAlive ---@param entityIndex EntityIndex ---@return boolean function ProjectileUtils.IsAlive(entityIndex) end ---@overload fun(id:int,x:double,y:double):Projectile ---@overload fun(id:int,x:double,y:double,speedX:double):Projectile ---@overload fun(id:int,x:double,y:double,speedX:double,speedY:double):Projectile ---@param id int ---@param x double ---@param y double ---@param speedX double ---@param speedY double ---@param attack Attack ---@return Projectile function ProjectileUtils.Create(id, x, y, speedX, speedY, attack) end ---@overload fun(player:Player,id:int,x:double,y:double):Projectile ---@overload fun(player:Player,id:int,x:double,y:double,speedX:double):Projectile ---@overload fun(player:Player,id:int,x:double,y:double,speedX:double,speedY:double):Projectile ---@param player Player ---@param id int ---@param x double ---@param y double ---@param speedX double ---@param speedY double ---@param attack Attack ---@return Projectile function ProjectileUtils.CreateFromPlayer(player, id, x, y, speedX, speedY, attack) end ---@overload fun(npc:Npc,id:int,x:double,y:double):Projectile ---@overload fun(npc:Npc,id:int,x:double,y:double,speedX:double):Projectile ---@overload fun(npc:Npc,id:int,x:double,y:double,speedX:double,speedY:double):Projectile ---@param npc Npc ---@param id int ---@param x double ---@param y double ---@param speedX double ---@param speedY double ---@param attack Attack ---@return Projectile function ProjectileUtils.CreateFromNpc(npc, id, x, y, speedX, speedY, attack) end return ProjectileUtils ================================================ FILE: apis/Recipe.lua ================================================ ---@class RecipeInputSlotType_Value ---@class RecipeInputSlotType ---@field Empty RecipeInputSlotType_Value ---@field Item RecipeInputSlotType_Value ---@field OreDictionary RecipeInputSlotType_Value local RecipeInputSlotType = {} ---@class RecipeInputSlot ---@field type RecipeInputSlotType_Value ---@field id int ---@field stackSize int ---@field itemStack ItemStack ---@field isImportant boolean local RecipeInputSlot = {} ---@class Recipe ---@field configID int ---@field inputs RecipeInputSlot[] ---@field outputs Slot[] ---@field exData table local Recipe = {} ---GetGroupSearchAction ---@param groupIndex int ---@return int function Recipe:GetGroupSearchAction(groupIndex) end ---IsValidByMask ---@param mask string ---@return boolean function Recipe:IsValidByMask(mask) end return Recipe ================================================ FILE: apis/RecipeConfig.lua ================================================ ---@class RecipeConfig ---@field iconItemID int ---@field inputCount int ---@field outputCount int local RecipeConfig = {} return RecipeConfig ================================================ FILE: apis/RecipeSearchAction.lua ================================================ ---@class RecipeSearchAction ---@field Fixed int ---@field Unordered int local RecipeSearchAction = {} return RecipeSearchAction ================================================ FILE: apis/RecipeUtils.lua ================================================ ---@API ---@class RecipeUtils 配方组件。 local RecipeUtils = {} ---通过配方的ID获取配方。 ---@param recipeID int 配方ID (请通过搜索配方的方法 RecipeUtils.SearchRecipe() 动态获取)。 ---@return Recipe 配方。 function RecipeUtils.GetRecipe(recipeID) end ---获取某一合成实体的配方配置。 ---@param recipeConfigID int 配方配置ID (请通过Reg.RecipeConfigID()动态获取)。 ---@return RecipeConfig 配方配置。 function RecipeUtils.GetConfig(recipeConfigID) end ---搜索配方。 ---[Example] -----获取酿造台的某一配方,使用酿造台中的两个合成的格子作为输入物品 ---local recipeID = RecipeUtils.SearchRecipe(Reg.RecipeConfigID("Brew"), self.inventory, 0, 2) ---@overload fun(configID:int,inventory:Inventory):int ---@param configID int 配方配置ID (请通过Reg.RecipeConfigID()动态获取)。 ---@param inventory Inventory 物品格子的集合(一般为合成中使用的物品的格子的集合)。 ---@param offset int 偏移值(从物品格子的哪里开始)。 ---@param length int 长度(调用物品格子的数目)。 ---@return int 配方ID function RecipeUtils.SearchRecipe(configID, inventory, offset, length) end ---检查某一物品是否有对应的配方 ---@param configID int 配方配置ID (请通过Reg.RecipeConfigID()动态获取)。 ---@param inputItemStack ItemStack 合成输入的堆叠物品。 ---@param inputIndex int 合成输入的Index。 ---@return int 配方ID。 function RecipeUtils.HasRecipe(configID, inputItemStack, inputIndex) end ---检查某一配方配置里所有的配方中是否有对应的输入物品 ---@param configID int 配方配置ID (请通过Reg.RecipeConfigID()动态获取)。 ---@param inputItemStack ItemStack 搜索对应的堆叠物品。 ---@return int[] 搜索到的配方ID的数组。 function RecipeUtils.SearchRecipeHasInputItem(configID, inputItemStack) end ---检查某一配方配置里所有的配方中是否有对应的输出物品 ---@param configID int 配方配置ID (请通过Reg.RecipeConfigID()动态获取)。 ---@param outputItemStack ItemStack 搜索对应的堆叠物品。 ---@param outputIndex int 合成输出的Index。 ---@return int[] 搜索到的配方ID的数组。 function RecipeUtils.SearchRecipeHasOutputItem(configID, outputItemStack, outputIndex) end return RecipeUtils ================================================ FILE: apis/Rectangle.lua ================================================ -- Document -- Rectangle Class: https://blueyoshi.gitbook.io/terracraft/en/mod/api/type#rectangle -- -- Rectangle类: https://blueyoshi.gitbook.io/terracraft/cn/mod/api/type#rectangle -- -- Copyright (c) 2021. BlueYoshi(blueyoshi@foxmail.com) ---@class Rectangle Represents an axis-aligned rectangle. (表示一个轴对齐矩形) ---@field x int The x coordinate of the upper left corner of the rectangle. (矩形左上角横坐标) ---@field y int The y coordinate of the upper left corner of the rectangle. (矩形左上角纵坐标) ---@field width int The width of the rectangle. (矩形宽度) ---@field height int The height of the rectangle. (矩形高度) local Rectangle = {} --- Set a new rectangle. --- --- 设置新的矩形。 ---@param x int ---@param y int ---@param width int ---@param height int function Rectangle:Set(x, y, width, height) end return Rectangle ================================================ FILE: apis/Reg.lua ================================================ ---@API ---@class Reg 描述游戏内的注册信息。 local Reg = {} ---根据物品名返回注册的动态ID。 ---@param name string ---@return int function Reg.ItemID(name) end ---根据动态ID返回物品的全局ID名称。 ---@param id int ---@return string function Reg.ItemIDName(id) end ---返回最大物品ID。 ---@return int function Reg.MaxItemID() end ---根据方块名返回注册的动态ID。 ---@param name string ---@return int function Reg.BlockID(name) end ---根据动态ID返回方块的全局ID名称。 ---@param id int ---@return string function Reg.BlockIDName(id) end ---根据方块组名返回注册的动态ID。 ---@param name string ---@return int function Reg.BlockGroupID(name) end ---根据动态ID返回方块组的全局ID名称。 ---@param id int ---@return string function Reg.BlockGroupIDName(id) end ---根据方块子组名返回注册的动态ID。 ---@param name string ---@return int function Reg.BlockSubGroupID(name) end ---根据动态ID返回方块子组的全局ID名称。 ---@param id int ---@return string function Reg.BlockSubGroupIDName(id) end ---根据方块实体名返回注册的动态ID。 ---@param name string ---@return int function Reg.BlockEntityID(name) end ---根据动态ID返回方块实体的全局ID名称。 ---@param id int ---@return string function Reg.BlockEntityIDName(id) end ---根据特效名返回注册的动态ID。 ---@param name string ---@return int function Reg.EffectID(name) end ---根据动态ID返回特效的全局ID名称。 ---@param id int ---@return string function Reg.EffectIDName(id) end ---根据BUFF名返回注册的动态ID。 ---@param name string ---@return int function Reg.BuffID(name) end ---根据动态ID返回BUFF的全局ID名称。 ---@param id int ---@return string function Reg.BuffIDName(id) end ---根据附魔名返回注册的动态ID。 ---@param name string ---@return int function Reg.EnchantmentID(name) end ---根据动态ID返回附魔的全局ID名称。 ---@param id int ---@return string function Reg.EnchantmentIDName(id) end ---返回附魔的最大ID。 ---@return int function Reg.MaxEnchantmentID() end ---根据NPC名返回注册的动态ID。 ---@param name string ---@return int function Reg.NpcID(name) end ---根据动态ID返回NPC的全局ID名称。 ---@param id int ---@return string function Reg.NpcIDName(id) end ---根据抛射物名返回注册的动态ID。 ---@param name string ---@return int function Reg.ProjectileID(name) end ---根据动态ID返回抛射物的全局ID名称。 ---@param id int ---@return string function Reg.ProjectileIDName(id) end ---根据音效名返回注册的动态ID。 ---@param name string ---@return int function Reg.SoundID(name) end ---根据动态ID返回音效的全局ID名称。 ---@param id int ---@return string function Reg.SoundIDName(id) end ---根据音效组名返回注册的动态ID。 ---@param name string ---@return int function Reg.SoundGroupID(name) end ---根据动态ID返回音效组的全局ID名称。 ---@param id int ---@return string function Reg.SoundGroupIDName(id) end ---根据流体名返回注册的动态ID。 ---@param name string ---@return int function Reg.LiquidID(name) end ---根据动态ID返回流体的全局ID名称。 ---@param id int ---@return string function Reg.LiquidIDName(id) end ---根据生物群系名返回注册的动态ID。 ---@param name string ---@return int function Reg.BiomeID(name) end ---根据动态ID返回生物群系的全局ID名称。 ---@param id int ---@return string function Reg.BiomeIDName(id) end ---返回最大生物群系ID。 ---@return int function Reg.MaxBiomeID() end ---根据生物群系类型名返回注册的动态ID。 ---@param name string ---@return int function Reg.BiomeTypeID(name) end ---根据动态ID返回生物群系类型的全局ID名称。 ---@param id int ---@return string function Reg.BiomeTypeIDName(id) end ---返回最大生物群系类型ID。 ---@return int function Reg.MaxBiomeTypeID() end ---根据配方配置名返回注册的动态ID。 ---@param name string ---@return int function Reg.RecipeConfigID(name) end ---根据动态ID返回配方配置的全局ID名称。 ---@param id int ---@return string function Reg.RecipeConfigIDName(id) end ---返回最大配方配置ID。 ---@return int function Reg.MaxRecipeConfigID() end ---返回最大配方ID。 ---@return int function Reg.MaxRecipeID() end ---根据动态ID返回矿物字典的全局ID名称。 ---@param id int ---@return string function Reg.OreDictionaryIDName(id) end ---根据矿物字典名返回注册的动态ID。 ---@param name string ---@return int function Reg.OreDictionaryID(name) end ---根据工具优先级名返回注册的动态ID。 ---@param gradeName string ---@return int function Reg.ToolGradePriority(gradeName) end ---根据弹药名返回注册的动态ID。 ---@param name string ---@return int function Reg.AmmoID(name) end ---根据动态ID返回弹药的全局ID名称。 ---@param id int ---@return string function Reg.AmmoIDName(id) end ---根据成就名返回注册的动态ID。 ---@param name string ---@return int function Reg.AdvancementID(name) end ---根据动态ID返回成就的全局ID名称。 ---@param id int ---@return string function Reg.AdvancementIDName(id) end ---返回最大成就ID。 ---@return int function Reg.MaxAdvancementID() end ---@param name string ---@return int function Reg.ModTextureID(name) end ---@param id int ---@return string function Reg.ModTextureIDName(id) end ---根据建筑名返回注册的动态ID。 ---@param name string ---@return int function Reg.BuildingID(name) end ---根据动态ID返回建筑的全局ID名称。 ---@param id int ---@return string function Reg.BuildingIDName(id) end return Reg ================================================ FILE: apis/ServerBoundPacketWriter.lua ================================================ ---@class ServerBoundPacket ---@field writerBuffer ByteStream ---@field readerBuffer ByteStream local ServerBoundPacket = {} function ServerBoundPacket:Send() end ---@return ByteStream function ServerBoundPacket:GetWriterBuffer() end ---@return ByteStream function ServerBoundPacket:GetReaderBuffer() end return ServerBoundPacket ================================================ FILE: apis/Shape.lua ================================================ -- Document -- Shape Enum Class: https://blueyoshi.gitbook.io/terracraft/en/mod/api/type#shape -- -- Shape枚举类: https://blueyoshi.gitbook.io/terracraft/cn/mod/api/type#shape -- -- Copyright (c) 2021. BlueYoshi(blueyoshi@foxmail.com) ---@class Shape Enum class (Enum Format: `SHAPE_XXX`) local Shape = {} --- The shape of the hitbox is an axis-aligned rectangle. --- --- 碰撞箱形状为轴对齐矩形。 --- ---@type Shape SHAPE_BOX = nil --- The shape of the hitbox is a rotating rectangle. --- --- 碰撞箱形状为旋转矩形。 --- ---@type Shape SHAPE_ROTATE_BOX = nil return Shape ================================================ FILE: apis/Skeleton.lua ================================================ ---@class Skeleton local Skeleton = {} return Skeleton ================================================ FILE: apis/Skin.lua ================================================ ---@class Skin ---@field headTexture TextureLocation ---@field bodyTexture TextureLocation ---@field legTexture TextureLocation ---@field hairTexture TextureLocation ---@field clothTexture TextureLocation ---@field pantTexture TextureLocation ---@field isFemale boolean ---@field name string ---@field authors Array ---@field mod Mod local Skin = {} return Skin ================================================ FILE: apis/SkinUtils.lua ================================================ ---@class SkinUtils ---@field maxID int local SkinUtils = {} ---GetSkin ---@param skinID int ---@return Skin function SkinUtils.GetSkin(skinID) end return SkinUtils ================================================ FILE: apis/Slot.lua ================================================ ---@API ---@class Slot 描述一个物品格子,物品格子可能为空格子,也可能包含一个ItemStack。 ---@field hasStack boolean 当前格子是否包含物品堆栈。 ---@field tag int 格子附加值。 local Slot = {} ---判断格子是否有效。 ---@return boolean function Slot:Valid() end ---@return ItemStack function Slot:GetStack() end ---PushStack ---@param stack ItemStack function Slot:PushStack(stack) end ---DecrStackSize ---@param value int ---@return ItemStack function Slot:DecrStackSize(value) end function Slot:ClearStack() end ---SwapStack ---@param slot Slot function Slot:SwapStack(slot) end ---CanPush ---@param itemStack ItemStack ---@return boolean function Slot:CanPush(itemStack) end --- ---@param itemStack ItemStack ---@return boolean function Slot:CanPick(itemStack) end ---OnPush ---@param itemStack ItemStack function Slot:OnPush(itemStack) end ---OnPick ---@param ItemStack ItemStack function Slot:OnPick(ItemStack) end --- ---@param listener table|function ---@return ListenerID function Slot:AddCanPushListener(listener) end --- ---@param listenerID ListenerID function Slot:RemoveCanPushListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function Slot:AddCanPickListener(listener) end --- ---@param listenerID ListenerID function Slot:RemoveCanPickListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function Slot:AddOnPushListener(listener) end --- ---@param listenerID ListenerID function Slot:RemoveOnPushListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function Slot:AddOnPickListener(listener) end --- ---@param listenerID ListenerID function Slot:RemoveOnPickListener(listenerID) end function Slot:SyncAll() end return Slot ================================================ FILE: apis/SlotCommandQueue.lua ================================================ ---@class SlotCommandQueue local SlotCommandQueue = {} return SlotCommandQueue ================================================ FILE: apis/SmartMode.lua ================================================ ---@class SmartMode_Value ---@class SmartMode ---@field None SmartMode_Value ---@field Digging SmartMode_Value ---@field Placing SmartMode_Value local SmartMode = {} return SmartMode ================================================ FILE: apis/SoundUtils.lua ================================================ ---@class SoundUtils local SoundUtils = {} ---PlaySound ---@overload fun(soundID:int) ---@param soundID int ---@param xi int ---@param yi int function SoundUtils.PlaySound(soundID, xi, yi) end ---PlaySoundGroup ---@overload fun(soundGroupID:int) ---@param soundGroupID int ---@param xi int ---@param yi int function SoundUtils.PlaySoundGroup(soundGroupID, xi, yi) end return SoundUtils ================================================ FILE: apis/SpriteEx.lua ================================================ -- Document -- SpriteEx Class: https://blueyoshi.gitbook.io/terracraft/en/mod/api/type#spriteex -- -- SpriteEx类: https://blueyoshi.gitbook.io/terracraft/cn/mod/api/type#spriteex -- -- Copyright (c) 2021. BlueYoshi(blueyoshi@foxmail.com) ---@class SpriteEx Sprite extension information, has the relevant parameters of drawing. (精灵绘制拓展信息,拥有决定绘制的相关参数) ---@field scaleRateX float @[ default `1.0` ] The horizontal zoom size when the sprite is drawn. (精灵绘制时的横向缩放尺寸) ---@field scaleRateY float @[ default `1.0` ] The vertical zoom size when the sprite is drawn. (精灵绘制时的纵向缩放尺寸) ---@field angle float @[ default `0.0` ] The rotation angle when the sprite is drawn. (精灵绘制时的旋转角度) ---@field rotateX float The center point X of the sprite's rotation. If the drawing object is an entity, the default is the center of the entity, otherwise the default is 0.0. (精灵的旋转中心点X。若绘制对象为实体,默认为实体中心,否则默认为0.0) ---@field rotateY float The center point Y of the sprite's rotation. If the drawing object is an entity, the default is the center of the entity, otherwise the default is 0.0. (精灵的旋转中心点Y。若绘制对象为实体,默认为实体中心,否则默认为0.0) ---@field flipHorizontal boolean @[ default `false` ] Whether to flip horizontally when the sprite is drawn. (精灵绘制时是否水平翻转) ---@field flipVertical boolean @[ default `false` ] Whether to flip vertically when the sprite is drawn. (精灵绘制时是否竖直翻转) local SpriteEx = {} --- Restore Defaults. --- --- 恢复默认值。 function SpriteEx:SetDefault() end return SpriteEx ================================================ FILE: apis/Type.lua ================================================ ---@class int:number ---@class double:number ---@class float:number ================================================ FILE: apis/Utils.lua ================================================ ---@class Utils Util Module (通用模块) ---@field netMode int ---@field E double ---@field LOG2E double ---@field LOG10E double ---@field PI double ---@field TWO_PI double ---@field PI_OVER_2 double ---@field PI_OVER_4 double local Utils = {} ---If n is greater than 0, return a random integer of [0, n), otherwise return 0. --- ---若n大于0,返回[0, n)的随机整数,否则返回0。 ---@param n int ---@return int function Utils.RandInt(n) end ---If len is greater than 0, return a random integer of [begin, begin + len), otherwise return begin. --- ---若len大于0,返回[begin, begin + len)的随机整数,否则返回begin。 ---@param begin int ---@param len int ---@return int function Utils.RandIntArea(begin, len) end --- --- ---若value大于0,返回[0, value)的随机浮点数,否则返回0。 ---@param value double ---@return double function Utils.RandDouble(value) end --- --- ---若len大于0,返回[begin, begin + len)的随机浮点数,否则返回begin。 ---@param begin double ---@param len double ---@return double function Utils.RandDoubleArea(begin, len) end --- --- ---返回(-value, value)的随机浮点数。 ---@param value double ---@return double function Utils.RandSym(value) end --- --- ---当n为正数时1/n概率返回true,否则始终返回false。 --- ---例1:Utils.RandTry(3)有1/3概率返回true。 --- ---例2:Utils.RandTry(2)有一半概率返回true。 ---@param n int ---@return boolean function Utils.RandTry(n) end --- --- ---返回实际横/纵坐标对应的格子横/纵坐标。注意每个格子为16像素,实际结果为除以16后向下取整。 ---@param a double ---@return int function Utils.Cell(a) end --- --- ---返回a与b求余的非负数结果。 --- ---例1:Utils.PositiveMod(5, 3)返回2。 --- ---例2:Utils.PositiveMod(-5, 3)返回1。 --- ---`int c = a % b;` --- ---`if (c < 0) c += b;` --- ---`return c;` ---@param a int ---@param b int ---@return int function Utils.PositiveMod(a, b) end --- --- ---若b非0,返回a向下取整整除b的结果,否则返回0。 --- ---例1:Utils.FloorDivide(10, 3)返回3。 --- ---例2:Utils.FloorDivide(-4, 3)返回-2。 --- ---`return a / b - ((a < 0 && a % b != 0) ? 1 : 0);` ---@param a int ---@param b int ---@return int function Utils.FloorDivide(a, b) end --- --- ---返回以period为周期、以begin为初相位的正弦波在相位phase的值。 --- ---`return sin(begin + 2 * PI * float(phase % period) / period);` ---@overload fun(phase:int,period:int):int ---@param phase int ---@param period int ---@param begin int @[ default `0` ] ---@return double function Utils.SinValue(phase, period, begin) end --- --- ---返回以period为周期、以begin为初相位的余弦波在相位phase的值。 --- ---`return cos(begin + 2 * PI * float(phase % period) / period);` ---@overload fun(phase:int,period:int):int ---@param phase int ---@param period int ---@param begin int @[ default `0` ] ---@return double function Utils.CosValue(phase, period, begin) end --- --- ---返回start值往target值方向移动step长度的结果,若到达target值,则返回target值。 --- ---例1:Utils.ToTargetValue(1, 10, 5)返回6。 --- ---例2:Utils.ToTargetValue(6, 10, 5)返回10。 ---@param start int ---@param target int ---@param step int ---@return int function Utils.ToTargetValue(start, target, step) end ---Returns the distance from point (x1, y1) to point (x2, y2). --- ---返回点(x1, y1)到点(x2, y2)的距离。 --- ---例:Utils.GetPointsDistance(1.0,0.0,4.0,4.0)返回5.0。 ---@param x1 double ---@param y1 double ---@param x2 double ---@param y2 double ---@return double function Utils.GetPointsDistance(x1, y1, x2, y2) end --- --- ---返回点(x, y)到原点(0, 0)的距离。 --- ---例:Utils.GetDistance(3.0, 4.0)返回5.0。 ---@param x double ---@param y double ---@return double function Utils.GetDistance(x, y) end --- --- ---返回点(x, y)到以点(x1, y1)和点(x2, y2)为两端点的线段的距离。 ---@param x double ---@param y double ---@param x1 double ---@param y1 double ---@param x2 double ---@param y2 double ---@return double function Utils.GetPointSegmentDistance(x, y, x1, y1, x2, y2) end --- --- ---返回向量(x, y)与横坐标的夹角。 --- ---例1:Utils.GetAngle(1, 1)返回π/4。 --- ---例2:Utils.GetAngle(0, 1)返回π/2。 ---@param x double ---@param y double ---@return double function Utils.GetAngle(x, y) end --- --- ---将角度按2π周期增加或减少,返回最终限定在区间(-π, π]内的结果。 --- ---@param angle double ---@return double function Utils.FixAngle(angle) end --- --- ---将极坐标转换为直角坐标,返回横坐标和纵坐标。 --- ---`x = length * cos(angle);` --- ---`y = length * sin(angle);` --- ---@param length double ---@param angle double ---@return double,double function Utils.GetXYFromPolar(length, angle) end --- --- ---将点(x, y)绕原点旋转指定角度,返回旋转后的横坐标和纵坐标。 --- ---`double dx = x, dy = y;` --- ---`x = dx * cos(angle) - dy * sin(angle);` --- ---`y = dx * sin(angle) + dy * cos(angle);` --- ---@param x double ---@param y double ---@param angle double ---@return double,double function Utils.RotateXY(x, y, angle) end --- --- ---将一个二维速度(speedX, speedY)以恒定速度(dec)降低,返回新的横速度和纵速度。 ---@param speedX double ---@param speedY double ---@param dec double ---@return double,double function Utils.SlowSpeed2D(speedX, speedY, dec) end --- --- ---将一个速度以恒定速度(dec)降低,返回新的速度。 ---@param speed double ---@param dec double ---@return double function Utils.SlowSpeed1D(speed, dec) end --- --- ---将一个二维速度(speedX, speedY)进行受力,返回新的横速度和纵速度。 ---@param speedX double ---@param speedY double ---@param force double ---@param forceAngle double ---@param maxSpeed double ---@return double,double function Utils.ForceSpeed2D(speedX, speedY, force, forceAngle, maxSpeed) end return Utils ================================================ FILE: apis/WorldData.lua ================================================ ---@class WorldData ---@field worldName string ---@field worldSeed int ---@field gameTime int ---@field dayTime int ---@field realDayTime double ---@field daySpeed double ---@field spawnXi int ---@field spawnYi int ---@field weatherTime int ---@field gameMode int ---@field windSpeed double ---@field windAcc double ---@field weatherRate double ---@field isOnWeather boolean ---@field noPvp boolean ---@field noBlowTiles boolean ---@field useLoginSystem boolean ---@field noAllowWrongFormatPlayerName boolean ---@field clientSideCharacters boolean local WorldData = {} ---@return WorldData function WorldData.new() end return WorldData ================================================ FILE: apis/WorldDataUtils.lua ================================================ ---@class WorldDataUtils local WorldDataUtils = {} ---Load ---@param worldName string ---@param worldData WorldData ---@return boolean function WorldDataUtils.Load(worldName, worldData) end ---Save ---@param worldData WorldData function WorldDataUtils.Save(worldData) end ---Remove ---@param worldName string function WorldDataUtils.Remove(worldName) end ---GenerateSeed ---@param seedString string ---@return int function WorldDataUtils.GenerateSeed(seedString) end return WorldDataUtils ================================================ FILE: apis/WorldGenArea.lua ================================================ ---@class WorldGenArea ---@field xi int ---@field yi int ---@field wi int ---@field hi int local WorldGenArea = {} ---new ---@overload fun():WorldGenArea ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@return WorldGenArea function WorldGenArea.new(xi, yi, wi, hi) end return WorldGenArea ================================================ FILE: apis/WorldGenChunkBuffer.lua ================================================ ---@class WorldGenChunkBufferElement ---@field biomeType int ---@field biomeID int ---@field isFrontPreset boolean ---@field isWallPreset boolean ---@field isLiquidPreset boolean ---@field isFrontSettled boolean ---@field isWallSettled boolean ---@field isLiquidSettled boolean ---@field isGrassCoverPreset boolean local WorldGenChunkBufferElement = {} ---@class WorldGenChunkBufferElementMask ---@field biomeType boolean ---@field biomeID boolean ---@field isFrontPreset boolean ---@field isWallPreset boolean ---@field isLiquidPreset boolean ---@field isFrontSettled boolean ---@field isWallSettled boolean ---@field isLiquidSettled boolean ---@field isGrassCoverPreset boolean local WorldGenChunkBufferElementMask = {} ---@class WorldGenChunkBuffer local WorldGenChunkBuffer = {} ---GetUnit ---@param xi int ---@param yi int ---@return WorldGenChunkBufferElement function WorldGenChunkBuffer:GetUnit(xi, yi) end ---GetSample ---@param id int ---@return WorldGenChunkBufferElement function WorldGenChunkBuffer:GetSample(id) end ---ClearSample ---@param id int function WorldGenChunkBuffer:ClearSample(id) end ---GetMask ---@param id int ---@return WorldGenChunkBufferElementMask function WorldGenChunkBuffer:GetMask(id) end ---ClearMask ---@param id int function WorldGenChunkBuffer:ClearMask(id) end ---ApplySampleByMask ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param sampleID int ---@param maskID int function WorldGenChunkBuffer:ApplySampleByMask(xi, yi, wi, hi, sampleID, maskID) end ---ApplySampleByMaskByCondition ---@overload fun(xi:int,yi:int,wi:int,hi:int,sampleID:int,maskID:int,conditionMaskID:int,conditionMaskID:int) ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param sampleID int ---@param maskID int ---@param conditionSampleID int ---@param conditionMaskID int ---@param logicOR boolean function WorldGenChunkBuffer:ApplySampleByMaskByCondition(xi, yi, wi, hi, sampleID, maskID, conditionSampleID, conditionMaskID, logicOR) end ---HasAreaSameSampleByMask ---@overload fun(xi:int,yi:int,wi:int,hi:int,sampleID:int,maskID:int) ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param sampleID int ---@param maskID int ---@param logicOR boolean function WorldGenChunkBuffer:HasAreaSameSampleByMask(xi, yi, wi, hi, sampleID, maskID, logicOR) end ---CreateAllPlaceableByBiomeType ---@overload fun(xi:int,yi:int,wi:int,hi:int,biomeType:int) ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param biomeType int ---@param boundaryArrayID int function WorldGenChunkBuffer:CreateAllPlaceableByBiomeType(xi, yi, wi, hi, biomeType, boundaryArrayID) end ---IsAreaHasSolid ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@return boolean function WorldGenChunkBuffer:IsAreaHasSolid(xi, yi, wi, hi) end ---AddBoundaryArray ---@param boundaryArray int[] ---@return int function WorldGenChunkBuffer:AddBoundaryArray(boundaryArray) end ---UpdateBoundaryArray ---@param boundaryArrayID int ---@param boundaryArray int[] function WorldGenChunkBuffer:UpdateBoundaryArray(boundaryArrayID, boundaryArray) end ---@return WorldGenCode function WorldGenChunkBuffer:GetCode() end ---RunCodeArea ---@param xi int ---@param yi int ---@param wi int ---@param hi int function WorldGenChunkBuffer:RunCodeArea(xi, yi, wi, hi) end ---SetBiomeArea ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param biomeType int ---@param biomeID int ---@param isApplyFront boolean ---@param isApplyWall boolean function WorldGenChunkBuffer:SetBiomeArea(xi, yi, wi, hi, biomeType, biomeID, isApplyFront, isApplyWall) end ---SetBiomeIDAreaByBiomeType ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param biomeType int ---@param biomeID int function WorldGenChunkBuffer:SetBiomeIDAreaByBiomeType(xi, yi, wi, hi, biomeType, biomeID) end ---SetBiomeIDFromMatrixByBiomeType ---@param biomeType int ---@param matrixTable int[] function WorldGenChunkBuffer:SetBiomeIDFromMatrixByBiomeType(biomeType, matrixTable) end function WorldGenChunkBuffer:PushAllSubBlocks() end ---SetTile ---@overload fun(xi:int,yi:int,tileID:int,tag:int) ---@param xi int ---@param yi int ---@param tileID int ---@param tag int ---@param isAllowSlope boolean function WorldGenChunkBuffer:SetTile(xi, yi, tileID, tag, isAllowSlope) end ---SetTileArea ---@overload fun(xi:int,yi:int,wi:int,hi:int,tileID:int,tag:int) ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param tileID int ---@param tag int ---@param isAllowSlope boolean function WorldGenChunkBuffer:SetTileArea(xi, yi, wi, hi, tileID, tag, isAllowSlope) end ---SetTileAreaByCondition ---@overload fun(xi:int,yi:int,wi:int,hi:int,tileID:int,tag:int,isAllowSlope:boolean,conditionSampleID:int,conditionMaskID:int) ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param tileID int ---@param tag int ---@param isAllowSlope boolean ---@param conditionSampleID int ---@param conditionMaskID int ---@param logicOR boolean function WorldGenChunkBuffer:SetTileAreaByCondition(xi, yi, wi, hi, tileID, tag, isAllowSlope, conditionSampleID, conditionMaskID, logicOR) end ---SetWall ---@overload fun(xi:int,yi:int,wallID:int) ---@param xi int ---@param yi int ---@param wallID int ---@param isAllowSlope boolean function WorldGenChunkBuffer:SetWall(xi, yi, wallID, isAllowSlope) end ---SetWallArea ---@overload fun(xi:int,yi:int,wi:int,hi:int,wallID:int) ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param wallID int ---@param isAllowSlope boolean function WorldGenChunkBuffer:SetWallArea(xi, yi, wi, hi, wallID, isAllowSlope) end ---SetWallAreaByCondition ---@overload fun(xi:int,yi:int,wi:int,hi:int,wallID:int,isAllowSlope:boolean,conditionSampleID:int,conditionMaskID:int) ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param wallID int ---@param isAllowSlope boolean ---@param conditionSampleID int ---@param conditionMaskID int ---@param logicOR boolean function WorldGenChunkBuffer:SetWallAreaByCondition(xi, yi, wi, hi, wallID, isAllowSlope, conditionSampleID, conditionMaskID, logicOR) end ---SetLiquid ---@param xi int ---@param yi int ---@param liquidID int ---@param amount int function WorldGenChunkBuffer:SetLiquid(xi, yi, liquidID, amount) end ---SetLiquidArea ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param liquidID int ---@param amount int function WorldGenChunkBuffer:SetLiquidArea(xi, yi, wi, hi, liquidID, amount) end ---SetLiquidAreaByCondition ---@overload fun(xi:int,yi:int,wi:int,hi:int,liquidID:int,amount:int,conditionSampleID:int,conditionMaskID:int) ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param liquidID int ---@param amount int ---@param conditionSampleID int ---@param conditionMaskID int ---@param logicOR boolean function WorldGenChunkBuffer:SetLiquidAreaByCondition(xi, yi, wi, hi, liquidID, amount, conditionSampleID, conditionMaskID, logicOR) end ---ClearFront ---@param xi int ---@param yi int function WorldGenChunkBuffer:ClearFront(xi, yi) end ---ClearFrontArea ---@param xi int ---@param yi int ---@param wi int ---@param hi int function WorldGenChunkBuffer:ClearFrontArea(xi, yi, wi, hi) end --- ---@param xi int ---@param yi int function WorldGenChunkBuffer:ClearWall(xi, yi) end --- ---@param xi int ---@param yi int ---@param wi int ---@param hi int function WorldGenChunkBuffer:ClearWallArea(xi, yi, wi, hi) end --- ---@param xi int ---@param yi int function WorldGenChunkBuffer:ClearFrontAndWall(xi, yi) end --- ---@param xi int ---@param yi int ---@param wi int ---@param hi int function WorldGenChunkBuffer:ClearFrontAndWallArea(xi, yi, wi, hi) end ---ClearLiquid ---@param xi int ---@param yi int function WorldGenChunkBuffer:ClearLiquid(xi, yi) end ---ClearLiquidArea ---@param xi int ---@param yi int ---@param wi int ---@param hi int function WorldGenChunkBuffer:ClearLiquidArea(xi, yi, wi, hi) end ---PerlinMakeCaveHorizontal ---@param xi int ---@param yi int ---@param size int ---@param height int ---@param scaleX double ---@param persistence double ---@param octaves int ---@param amplitude double ---@param scaleXTop double ---@param persistenceTop double ---@param octavesTop int ---@param amplitudeTop double ---@param scaleXBottom double ---@param persistenceBottom double ---@param octavesBottom int ---@param amplitudeBottom double function WorldGenChunkBuffer:PerlinMakeCaveHorizontal(xi, yi, size, height, scaleX, persistence, octaves, amplitude, scaleXTop, persistenceTop, octavesTop, amplitudeTop, scaleXBottom, persistenceBottom, octavesBottom, amplitudeBottom) end ---PerlinMakeCave ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param scaleX double ---@param scaleY double ---@param caveRateBegin double ---@param caveRateEnd double ---@param mapYiFadeIn int ---@param fadeInSize int ---@param mapYiFadeOut int ---@param fadeOutSize int function WorldGenChunkBuffer:PerlinMakeCave(xi, yi, wi, hi, scaleX, scaleY, caveRateBegin, caveRateEnd, mapYiFadeIn, fadeInSize, mapYiFadeOut, fadeOutSize) end ---MakeCaveRandomDirection ---@param xi int ---@param yi int function WorldGenChunkBuffer:MakeCaveRandomDirection(xi, yi) end ---GetRandomAreas ---@param randomKey int ---@param originalWorldGenArea WorldGenArea ---@param elementWidthMin int ---@param elementWidthMax int ---@param elementHeightMin int ---@param elementHeightMax int ---@param density double function WorldGenChunkBuffer:GetRandomAreas(randomKey, originalWorldGenArea, elementWidthMin, elementWidthMax, elementHeightMin, elementHeightMax, density) end ---AddBlockRandomOval ---@overload fun(blockID:int,xi:int,yi:int,wi:int,hi:int) ---@overload fun(blockID:int,xi:int,yi:int,wi:int,hi:int,replaceFront:boolean) ---@overload fun(blockID:int,xi:int,yi:int,wi:int,hi:int,replaceFront:boolean,replaceLiquid:boolean) ---@overload fun(blockID:int,xi:int,yi:int,wi:int,hi:int,replaceFront:boolean,replaceLiquid:boolean,placeFrontAir:boolean) ---@overload fun(blockID:int,xi:int,yi:int,wi:int,hi:int,replaceFront:boolean,replaceLiquid:boolean,placeFrontAir:boolean,replaceWall:boolean) ---@param blockID int ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@param replaceFront boolean ---@param replaceLiquid boolean ---@param placeFrontAir boolean ---@param replaceWall boolean ---@param placeWallAir boolean function WorldGenChunkBuffer:AddBlockRandomOval(blockID, xi, yi, wi, hi, replaceFront, replaceLiquid, placeFrontAir, replaceWall, placeWallAir) end ---GenerateLake ---@overload fun(xi:int, yi:int, liquidID:int) ---@param xi int ---@param yi int ---@param liquidID int ---@param maxAllowCount int ---@return boolean function WorldGenChunkBuffer:GenerateLake(xi, yi, liquidID, maxAllowCount) end ---写入所有元素。 --- ---(1)对于所有预设的前景,根据群系、主次方块信息加入方块,并标记已经放置前景。 ---(2)对于所有预设的后景,根据群系、主次方块信息加入方块,并标记已经放置后景。 ---(3)对于所有预设的流体,按流体ID加入流体,并标记已经放置流体。 function WorldGenChunkBuffer:SettleAllElementByBiomes() end ---GetAllFloors ---@param xi int ---@param yi int ---@param wi int ---@param hi int ---@return MapPos[] function WorldGenChunkBuffer:GetAllFloors(xi, yi, wi, hi) end ---GenerateTree ---@param xi int ---@param yi int ---@param treeBlockID int ---@return boolean function WorldGenChunkBuffer:GenerateTree(xi, yi, treeBlockID) end ---GenerateLargeMushroom ---@param xi int ---@param yi int ---@param capID int ---@param stemID int ---@return boolean function WorldGenChunkBuffer:GenerateLargeMushroom(xi, yi, capID, stemID) end ---CreateBuilding ---@overload fun(buildingID:int, xi:int, yi:int) ---@overload fun(buildingID:int, xi:int, yi:int, maxTryTimes:int) ---@overload fun(buildingID:int, xi:int, yi:int, limitXi:int, limitYi:int, limitWi:int, limitHi:int) ---@param buildingID int ---@param xi int ---@param yi int ---@param limitXi int ---@param limitYi int ---@param limitWi int ---@param limitHi int ---@param maxTryTimes int function WorldGenChunkBuffer:CreateBuilding(buildingID, xi, yi, limitXi, limitYi, limitWi, limitHi, maxTryTimes) end function WorldGenChunkBuffer:ApplyBuildings() end return WorldGenChunkBuffer ================================================ FILE: apis/WorldGenCode.lua ================================================ ---@class WorldGenCodeConfig local WorldGenCodeConfig = {} ---@class WorldGenCode local WorldGenCode = {} ---CompileCode ---@param rawCode string function WorldGenCode:CompileCode(rawCode) end ---@return WorldGenCodeConfig function WorldGenCode:GetConfig() end ---SetConfig ---@param config WorldGenCodeConfig function WorldGenCode:SetConfig(config) end return WorldGenCode ================================================ FILE: apis/WorldGenNoise.lua ================================================ ---@class WorldGenNoise local WorldGenNoise = {} ---SetData ---@param persistence double ---@param octaves int function WorldGenNoise:SetData(persistence, octaves) end ---Perlin2D, return (-1.0, 1.0) ---@param x double ---@param y double ---@return double function WorldGenNoise:Perlin2D(x, y) end ---Perlin1D, return (-1.0, 1.0) ---@param x double ---@return double function WorldGenNoise:Perlin1D(x) end ---GetDoubleFromInt1D, return (-1.0, 1.0) ---@param xi int ---@return double function WorldGenNoise:GetDoubleFromInt1D(xi) end ---GetDoubleFromInt2D, return (-1.0, 1.0) ---@param xi int ---@param yi int ---@return double function WorldGenNoise:GetDoubleFromInt2D(xi, yi) end ---GetByteFromInt2D, return [0, maxByte) ---@param xi int ---@param yi int ---@param maxByte int ---@return int function WorldGenNoise:GetByteFromInt2D(xi, yi, maxByte) end return WorldGenNoise ================================================ FILE: apis/engine_api/AnimationEvent.lua ================================================ ---@class AnimationEvent local AnimationEvent = {} --- ---@param listener table|function ---@return ListenerID function AnimationEvent:addListener(listener) end --- ---@param listenerID ListenerID function AnimationEvent:removeListener(listenerID) end return AnimationEvent ================================================ FILE: apis/engine_api/Animator2D.lua ================================================ ---@class Animator2D local Animator2D = {} ---setFloat ---@param parameterName string ---@param value number function Animator2D:setFloat(parameterName, value) end ---getFloat ---@param parameterName string ---@return number function Animator2D:getFloat(parameterName) end --- ---@param parameterName string ---@param value number function Animator2D:setInteger(parameterName, value) end --- ---@param parameterName string ---@return number function Animator2D:getInteger(parameterName) end --- ---@param parameterName string ---@param value boolean function Animator2D:setBool(parameterName, value) end --- ---@param parameterName string ---@return boolean function Animator2D:getBool(parameterName) end ---setTrigger ---@param parameterName string function Animator2D:setTrigger(parameterName) end ---createEventAtTimePoint ---@param clipName string ---@param timePoint number ---@return AnimationEvent function Animator2D:createEventAtTimePoint(clipName, timePoint) end ---@param clipName string ---@param timePoint number ---@return AnimationEvent function Animator2D:getEventAtTimePoint(clipName, timePoint) end ---@param clipName string ---@param timePoint number function Animator2D:removeEventAtTimePoint(clipName, timePoint) end ---setLayerTimeScale ---@param layerIndex number ---@param timeScale number function Animator2D:setLayerTimeScale(layerIndex, timeScale) end ---@param layerIndex number ---@return number function Animator2D:getLayerTimeScale(layerIndex) end return Animator2D ================================================ FILE: apis/engine_api/AnimatorData2D.lua ================================================ ---@class AnimatorData2D local AnimatorData2D = {} ---new ---@param dataTable table ---@return AnimatorData2D function AnimatorData2D.new(dataTable) end return AnimatorData2D ================================================ FILE: apis/engine_api/App.lua ================================================ ---@class App ---@field appName string ---@field companyName string ---@field dataPath string ---@field persistentDataPath string ---@field engineVersion string ---@field isMobile boolean ---@field isPC boolean local App = {} return App ================================================ FILE: apis/engine_api/Array.lua ================================================ ---@class Array ---@field count number local Array = {} return Array ================================================ FILE: apis/engine_api/AssetBundle.lua ================================================ ---@class AssetBundle local AssetBundle = {} --- ---@return AssetBundle function AssetBundle.new() end ---clone ---@param value AssetBundle ---@return AssetBundle function AssetBundle.clone(value) end --- ---@param abPath string ---@return string function AssetBundle:loadFromFileSystem(abPath) end --- ---@param abPath string function AssetBundle:saveToFileSystem(abPath) end --- ---@param filePath string ---@param data Bytes ---@param offset number ---@param size number function AssetBundle:addFileData(filePath, data, offset, size) end --- ---@param filePath string ---@return string function AssetBundle:getFileString(filePath) end --- ---@param filePath string ---@return Bytes function AssetBundle:getFileBytes(filePath) end function AssetBundle:clear() end function AssetBundle:freeMemory() end --- ---@param filePath string ---@return boolean function AssetBundle:isFileExist(filePath) end --- ---@param folderPath string ---@return boolean function AssetBundle:isFolderExist(folderPath) end --- ---@param filePath string ---@param isFullPath boolean ---@return table function AssetBundle:getAllSubFolders(filePath, isFullPath) end --- ---@param path string ---@param extension string ---@param resultNoExtension boolean ---@param getAbsPath boolean ---@param recursion boolean ---@return table function AssetBundle:getAllFiles(path, extension, resultNoExtension, getAbsPath, recursion) end return AssetBundle ================================================ FILE: apis/engine_api/AssetManager.lua ================================================ ---@class AssetManager local AssetManager = {} ---getLastWriteTime ---@param path string ---@return DateTime function AssetManager.getLastWriteTime(path) end ---readAsString ---@param path string ---@return string function AssetManager.readAsString(path) end ---readAsBytes ---@param path string ---@return Bytes function AssetManager.readAsBytes(path) end --- ---@param filePath string ---@param isFullPath boolean ---@return string[] function AssetManager.getAllSubFolders(filePath, isFullPath) end --- ---@param path string ---@param extension string ---@param resultNoExtension boolean ---@param getAbsPath boolean ---@param recursion boolean ---@return string[] function AssetManager.getAllFiles(path, extension, resultNoExtension, getAbsPath, recursion) end ---isPathExist ---@param path string ---@return boolean function AssetManager.isPathExist(path) end ---genPackFromSource ---@param sourceParentFolderPath string ---@param folderName string ---@param assetMappingPath string ---@return string function AssetManager.genPackFromSource(sourceParentFolderPath, folderName, assetMappingPath) end return AssetManager ================================================ FILE: apis/engine_api/AtlasInfos.lua ================================================ ---@class AtlasInfos local AtlasInfos = {} return AtlasInfos ================================================ FILE: apis/engine_api/AtlasLoader.lua ================================================ ---@class AtlasLoader local AtlasLoader = {} ---saveToFileSystem ---@param atlasInfos AtlasInfos ---@param folderPath string function AtlasLoader.saveToFileSystem(atlasInfos, folderPath) end ---saveToAssetBundle ---@param assetBundle AssetBundle ---@param atlasInfos AtlasInfos ---@param folderPath string function AtlasLoader.saveToAssetBundle(assetBundle, atlasInfos, folderPath) end ---loadFromFileSystem ---@param folderPath string ---@return AtlasInfos function AtlasLoader.loadFromFileSystem(folderPath) end ---loadFromAssetBundle ---@param assetBundle AssetBundle ---@param folderPath string ---@return AtlasInfos function AtlasLoader.loadFromAssetBundle(assetBundle, folderPath) end return AtlasLoader ================================================ FILE: apis/engine_api/Audio.lua ================================================ ---@class Audio ---@field musicVolume number local Audio = {} --- ---@param filePath string ---@return number function Audio.loadSoundEffectFromFileSystem(filePath) end --- ---@param assetBundle AssetBundle ---@param filePath string ---@return number function Audio.loadSoundEffectFromAssetBundle(assetBundle, filePath) end ---unloadSoundEffectByID ---@param soundID number function Audio.unloadSoundEffectByID(soundID) end --- ---@param bytes Bytes ---@param offset number ---@param size number ---@return number function Audio.loadSoundEffectFromMemory(bytes, offset, size) end --- ---@param filePath string ---@return number function Audio.loadMusicEffectFromFileSystem(filePath) end --- ---@param assetBundle AssetBundle ---@param filePath string ---@return number function Audio.loadMusicEffectFromAssetBundle(assetBundle, filePath) end --- ---@param bytes Bytes ---@param offset number ---@param size number ---@return number function Audio.loadMusicEffectFromMemory(bytes, offset, size) end ---unloadMusicEffectByID ---@param musicID number function Audio.unloadMusicEffectByID(musicID) end --- ---@overload fun(id:number) ---@overload fun(id:number, loops:number) ---@overload fun(id:number, loops:number, fadeInTime:number) ---@overload fun(id:number, loops:number, fadeInTime:number, beginTime:number) ---@param id number ---@param loops number ---@param fadeInTime number ---@param beginTime number function Audio.playMusic(id, loops, fadeInTime, beginTime) end ---stopMusic ---@param fadeOutTime number function Audio.stopMusic(fadeOutTime) end function Audio.pauseMusic() end function Audio.resumeMusic() end ---@return FadingState_Value function Audio.getMusicFadingState() end ---getMusicPlayingTimePoint ---@param musicID string ---@return string function Audio.getMusicPlayingTimePoint(musicID) end --- ---@param volume number function Audio.setMusicVolume(volume) end --- ---@param volume number function Audio.setAllSoundEffectVolume(volume) end function Audio.isMusicPaused() end function Audio.isMusicPlaying() end --- ---@param listener table|function ---@return ListenerID function Audio:addMusicFinishedListener(listener) end --- ---@param listenerID ListenerID function Audio:removeMusicFinishedListener(listenerID) end return Audio ================================================ FILE: apis/engine_api/ByteStream.lua ================================================ ---@class ByteStream ---@field empty boolean ---@field count number ---@field capacity number ---@field readableCount number local ByteStream = {} --- ---@overload fun():ByteStream ---@param capacity number ---@return ByteStream function ByteStream.new(capacity) end ---clone ---@param value ByteStream ---@return ByteStream function ByteStream.clone(value) end function ByteStream:clear() end function ByteStream:freeMemory() end ---@param value number function ByteStream:writeInt(value) end ---@return number function ByteStream:readInt() end ---@param value number function ByteStream:writeIntVarLen(value) end ---@return number function ByteStream:readIntVarLen() end ---@param value number function ByteStream:writeFloat(value) end ---@return number function ByteStream:readFloat() end ---@param value number function ByteStream:writeDouble(value) end ---@return number function ByteStream:readDouble() end ---@param value boolean function ByteStream:writeBoolean(value) end ---@return boolean function ByteStream:readBoolean() end ---@param value string function ByteStream:writeString(value) end ---@return string function ByteStream:readString() end return ByteStream ================================================ FILE: apis/engine_api/Bytes.lua ================================================ ---@class Bytes ---@field empty boolean ---@field count number ---@field capacity number local Bytes = {} --- ---@overload fun():Bytes ---@param capacity number ---@return Bytes function Bytes.new(capacity) end ---clone ---@param value Bytes ---@return Bytes function Bytes.clone(value) end --- ---@param value number ---@return number function Bytes:add(value) end --- ---@param index number ---@param value number function Bytes:insert(index, value) end function Bytes:clear() end function Bytes:freeMemory() end --- ---@overload fun(count:number) ---@param count number ---@param fill number function Bytes:setCount(count, fill) end --- ---@param capacity number function Bytes:setCapacity(capacity) end --- ---@param bytes Bytes function Bytes:swap(bytes) end --- ---@overload fun(bytes:Bytes) ---@param bytes Bytes ---@param offset number ---@param count number function Bytes:addBytes(bytes, offset, count) end --- ---@param startOverwriteOffset number ---@param sourceBytes Bytes ---@param sourceOffset number ---@param sourceCount number function Bytes:overwrite(startOverwriteOffset, sourceBytes, sourceOffset, sourceCount) end return Bytes ================================================ FILE: apis/engine_api/CameraComponentWrapper.lua ================================================ ---@class CameraComponentWrapper:ComponentWrapper ---@field projection CameraProjection_Value ---@field clippingPlaneNear number ---@field clippingPlaneFar number ---@field fov number ---@field viewportRect RectFloatEx ---@field targetDisplay number local CameraComponentWrapper = {} return CameraComponentWrapper ================================================ FILE: apis/engine_api/CameraProjection.lua ================================================ ---@class CameraProjection_Value ---@class CameraProjection ---@field Perspective CameraProjection_Value ---@field Orthographic CameraProjection_Value local CameraProjection = {} return CameraProjection ================================================ FILE: apis/engine_api/CanvasComponentWrapper.lua ================================================ ---@class CanvasComponentWrapper:ComponentWrapper ---@field uiRoot UICanvas ---@field displayMode CanvasDisplayMode ---@field targetDisplay number local CanvasComponentWrapper = {} return CanvasComponentWrapper ================================================ FILE: apis/engine_api/CanvasDisplayMode.lua ================================================ ---@class CanvasDisplayMode_Value ---@class CanvasDisplayMode ---@field ScreenSpaceOverlay CanvasDisplayMode_Value ---@field ScreenSpaceCamera CanvasDisplayMode_Value ---@field WorldSpace CanvasDisplayMode_Value local CanvasDisplayMode = {} return CanvasDisplayMode ================================================ FILE: apis/engine_api/ClipCollection2D.lua ================================================ ---@class ClipCollection2D local ClipCollection2D = {} ---new ---@param jointCollection2D JointCollection2D ---@return ClipCollection2D function ClipCollection2D.new(jointCollection2D) end ---addClip ---@param clipTable table function ClipCollection2D:addClip(clipTable) end return ClipCollection2D ================================================ FILE: apis/engine_api/Color.lua ================================================ ---@API ---@class Color:SerializableType 描述一个颜色。 ---@field red number 红色通道分量。取值为[0, 255]。 ---@field green number 绿色通道分量。取值为[0, 255]。 ---@field blue number 蓝色通道分量。取值为[0, 255]。 ---@field alpha number 透明度通道分量。取值为[0, 255]。 ---@field Red Color 返回红色对象。 ---@field Black Color 返回黑色对象。 ---@field Gray Color 返回灰色对象。 ---@field Green Color 返回绿色对象。 ---@field Blue Color 返回蓝色对象。 ---@field LightBlue Color 返回淡蓝色对象。 ---@field Yellow Color 返回黄色对象。 ---@field FrenchGray Color 返回淡灰色对象。 ---@field White Color 返回白色对象。 local Color = {} ---创建一个颜色对象。 ---@overload fun():Color ---@overload fun(red:number,green:number,blue:number):Color ---@param red number 红色通道分量。取值为[0, 255]。 ---@param green number 绿色通道分量。取值为[0, 255]。 ---@param blue number 蓝色通道分量。取值为[0, 255]。 ---@param alpha number 透明度通道分量。取值为[0, 255]。 ---@return Color 新的颜色对象。 function Color.new(red, green, blue, alpha) end ---@param value Color ---@return Color function Color.clone(value) end return Color ================================================ FILE: apis/engine_api/ComponentID.lua ================================================ ---@class ComponentID_Value:number local ComponentID_Value = {} ---@class ComponentID ---@field Transform ComponentID_Value ---@field Rigidbody ComponentID_Value local ComponentID = {} return ComponentID ================================================ FILE: apis/engine_api/ComponentWrapper.lua ================================================ ---@class ComponentWrapper local ComponentWrapper = {} function ComponentWrapper:init() end function ComponentWrapper:destroy() end return ComponentWrapper ================================================ FILE: apis/engine_api/DateTime.lua ================================================ ---@class DateTime local DateTime = {} return DateTime ================================================ FILE: apis/engine_api/FadingState.lua ================================================ ---@class FadingState_Value ---@class FadingState ---@field NoFading FadingState_Value ---@field FadingIn FadingState_Value ---@field FadingOut FadingState_Value local FadingState = {} return FadingState ================================================ FILE: apis/engine_api/File.lua ================================================ ---@class File local File = {} ---getLastWriteTime ---@param path string ---@return DateTime function File.getLastWriteTime(path) end --- ---@param filePath string ---@param isFullPath boolean ---@return string[] function File.getAllSubFolders(filePath, isFullPath) end --- ---@param path string ---@param extension string ---@param resultNoExtension boolean ---@param getAbsPath boolean ---@param recursion boolean ---@return string[] function File.getAllFiles(path, extension, resultNoExtension, getAbsPath, recursion) end ---saveString ---@param path string ---@param str string function File.saveString(path, str) end ---saveBytes ---@param path string ---@param bytes Bytes function File.saveBytes(path, bytes) end ---readAsString ---@param path string ---@return string function File.readAsString(path) end ---readAsBytes ---@param path string ---@return Bytes function File.readAsBytes(path) end ---isPathExist ---@param path string ---@return boolean function File.isPathExist(path) end ---openFolderWindow ---@param path string function File.openFolderWindow(path) end ---makeFolder ---@param path string function File.makeFolder(path) end return File ================================================ FILE: apis/engine_api/FileTimeType.lua ================================================ ---@class FileTimeType local FileTimeType = {} return FileTimeType ================================================ FILE: apis/engine_api/FontManager.lua ================================================ ---@class FontManager local FontManager = {} ---load ---@param filePath string ---@param fontName string ---@return number function FontManager.load(filePath, fontName) end return FontManager ================================================ FILE: apis/engine_api/FontSprite.lua ================================================ ---@class FontSprite local FontSprite = {} ---drawText ---@param text string ---@param pos Vector2 ---@param size Size ---@param textStyle TextStyle function FontSprite.drawText(text, pos, size, textStyle) end ---drawTextBuffer ---@param pos Vector2 ---@param textBuffer TextBuffer function FontSprite.drawTextBuffer(pos, textBuffer) end ---getBuffer ---@param text string ---@param size Size ---@param textStyle TextStyle ---@return TextBuffer function FontSprite.getBuffer(text, size, textStyle) end return FontSprite ================================================ FILE: apis/engine_api/GameObject.lua ================================================ ---@class GameObject ---@field transform TransformComponentWrapper ---@field camera CameraComponentWrapper ---@field meshFilter MeshFilterComponentWrapper ---@field meshRenderer MeshRendererComponentWrapper ---@field canvas CanvasComponentWrapper ---@field rigidbody Rigidbody ---@field children table local GameObject = {} --- ---@return GameObject function GameObject.instantiate(gameObject) end --- ---@param gameObject GameObject function GameObject.destroy(gameObject) end function GameObject.flush() end --- ---@param componentID ComponentID_Value function GameObject:addComponent(componentID) end --- ---@param componentID ComponentID_Value function GameObject:removeComponent(componentID) end --- ---@param gameObject GameObject function GameObject:addChild(gameObject) end return GameObject ================================================ FILE: apis/engine_api/GameWindow.lua ================================================ ---@class GameWindow ---@field caption string ---@field width number ---@field height number ---@field fullScreen boolean ---@field displayResolution Size local GameWindow = {} return GameWindow ================================================ FILE: apis/engine_api/GlobalHook.lua ================================================ ---@class GlobalHook local GlobalHook = {} --- ---@param hookName string ---@param listener table|function function GlobalHook.add(hookName, listener) end return GlobalHook ================================================ FILE: apis/engine_api/GraphicsDevice.lua ================================================ ---@class GraphicsDevice ---@field vendorName string ---@field rendererName string ---@field drawCalls number ---@field primitiveCount number local GraphicsDevice = {} ---clear ---@param color Color function GraphicsDevice.clear(color) end --- ---@overload fun(a:Vector2,b:Vector2,color:Color) ---@param a Vector2 ---@param b Vector2 ---@param color Color ---@param depth number function GraphicsDevice.drawLine2D(a, b, color, depth) end --- ---@overload fun(point:Vector2,color:Color) ---@param point Vector2 ---@param color Color ---@param depth number function GraphicsDevice.drawPoint2D(point, color, depth) end --- ---@overload fun(rect:RectFloat,color:Color) ---@param rect RectFloat ---@param color Color ---@param depth number function GraphicsDevice.drawRect2D(rect, color, depth) end --- ---@overload fun(rect:RectFloat,color:Color) ---@param rect RectFloat ---@param color Color ---@param depth number function GraphicsDevice.drawRectHollow2D(rect, color, depth) end return GraphicsDevice ================================================ FILE: apis/engine_api/HotKeyCombination.lua ================================================ ---@class HotKeyCombination local HotKeyCombination = {} --- ---@param listener table|function ---@return ListenerID function HotKeyCombination:addListener(listener) end --- ---@param listenerID ListenerID function HotKeyCombination:removeListener(listenerID) end return HotKeyCombination ================================================ FILE: apis/engine_api/Hotfix.lua ================================================ ---@class Hotfix local Hotfix = {} --- function Hotfix.updateNextTick() end return Hotfix ================================================ FILE: apis/engine_api/Image.lua ================================================ ---@class Image local Image = {} ---loadPngFromMemory ---@param bytes Bytes ---@param offset number ---@param size number ---@param flip boolean ---@return ImageInfo function Image.loadPngFromMemory(bytes, offset, size, flip) end ---loadPngFromFileSystem ---@param filePath string ---@param flip boolean ---@return ImageInfo function Image.loadPngFromFileSystem(filePath, flip) end ---loadPngFromAssetBundle ---@param assetBundle AssetBundle ---@param filePath string ---@param flip boolean ---@return ImageInfo function Image.loadPngFromAssetBundle(assetBundle, filePath, flip) end ---saveAsPngToMemory ---@param imageInfo ImageInfo ---@param bytes Bytes function Image.saveAsPngToMemory(imageInfo, bytes) end ---saveAsPngToFileSystem ---@param imageInfo ImageInfo ---@param filePath string function Image.saveAsPngToFileSystem(imageInfo, filePath) end ---saveAsPngToAssetBundle ---@param imageInfo ImageInfo ---@param assetBundle AssetBundle ---@param filePath string function Image.saveAsPngToAssetBundle(imageInfo, assetBundle, filePath) end return Image ================================================ FILE: apis/engine_api/ImageInfo.lua ================================================ ---@class ImageInfo ---@field width number ---@field height number ---@field channelCount number ---@field byteData Bytes local ImageInfo = {} --- ---@param width number ---@param height number ---@param channelCount number ---@return ImageInfo function ImageInfo.new(width, height, channelCount) end ---clone ---@param value ImageInfo ---@return ImageInfo function ImageInfo.clone(value) end return ImageInfo ================================================ FILE: apis/engine_api/Input.lua ================================================ ---@class Input ---@field mouse Mouse ---@field keyboard Keyboard ---@field joystick JoystickDevice[] local Input = {} return Input ================================================ FILE: apis/engine_api/IntegratedClient.lua ================================================ ---@class IntegratedClient : IntegratedEnv ---@field main IntegratedClient local IntegratedClient = {} --- ---@param listener table|function ---@return ListenerID function IntegratedClient:addOnRenderListener(listener) end --- ---@param listenerID ListenerID function IntegratedClient:removeOnRenderListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function IntegratedClient:addOnWindowResizeListener(listener) end --- ---@param listenerID ListenerID function IntegratedClient:removeOnWindowResizeListener(listenerID) end return IntegratedClient ================================================ FILE: apis/engine_api/IntegratedEnv.lua ================================================ ---@class IntegratedEnv ---@field fps number ---@field gameSpeed number ---@field isMaxFPS boolean ---@field registry Registry local IntegratedEnv = {} --- ---@param listener table|function ---@return ListenerID function IntegratedEnv:addOnStartListener(listener) end --- ---@param listenerID ListenerID function IntegratedEnv:removeOnStartListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function IntegratedEnv:addOnUpdateListener(listener) end --- ---@param listenerID ListenerID function IntegratedEnv:removeOnUpdateListener(listenerID) end --- ---@overload fun():ScheduleID ---@param intervalTicks number ---@return ScheduleID function IntegratedEnv:createSchedule(intervalTicks) end ---getSchedule ---@param scheduleID ScheduleID ---@return Schedule function IntegratedEnv:getSchedule(scheduleID) end --- ---@param scheduleID ScheduleID function IntegratedEnv:removeSchedule(scheduleID) end return IntegratedEnv ================================================ FILE: apis/engine_api/Joint2D.lua ================================================ ---@class Joint2D ---@field transform Transform2D ---@field size Size ---@field angle number ---@field visible boolean local Joint2D = {} ---new ---@param name string ---@param originalPos Vector2 ---@param size Size ---@return Joint2D function Joint2D.new(name, originalPos, size) end ---addChild ---@overload fun(pos:Vector2,skeletonNode:Joint2D) ---@param pos Vector2 ---@param skeletonNode Joint2D ---@param overlapping boolean function Joint2D:addChild(pos, skeletonNode, overlapping) end ---getChild ---@param name string ---@return Joint2D function Joint2D:getChild(name) end ---@return ObbDouble function Joint2D:getWorldObb() end ---setTexture ---@param textureName string ---@param textureLocation TextureLocation ---@param positionOffset Vector2 ---@param sourceRect Rect function Joint2D:setTexture(textureName, textureLocation, positionOffset, sourceRect) end return Joint2D ================================================ FILE: apis/engine_api/JointBody2D.lua ================================================ ---@class JointBody2D ---@field joints JointCollection2D ---@field animator Animator2D local JointBody2D = {} ---new ---@param jointCollection2D JointCollection2D ---@return JointBody2D function JointBody2D.new(jointCollection2D) end ---@return JointBody2D function JointBody2D:clone() end ---update ---@overload fun() ---@param withAnimation boolean function JointBody2D:update(withAnimation) end ---setAnimator ---@param clipCollection2D ClipCollection2D ---@param animatorData2D Animator2D function JointBody2D:setAnimator(clipCollection2D, animatorData2D) end ---solveIK ---@overload fun(nodeEndName:string,nodeStartName:string,targetPos:Vector2):boolean ---@param nodeStartName string ---@param nodeEndName string ---@param nodeEnd Joint2D ---@param nodeStart Joint2D ---@param targetPos Vector2 ---@return boolean function JointBody2D:solveIK(nodeEnd, nodeStart, targetPos) end return JointBody2D ================================================ FILE: apis/engine_api/JointCollection2D.lua ================================================ ---@class JointCollection2D ---@field root Joint2D ---@field position Vector2 ---@field rotation number ---@field scale Vector2 ---@field flip boolean local JointCollection2D = {} ---new ---@return JointCollection2D function JointCollection2D.new() end ---getJoint ---@param name string ---@return Joint2D function JointCollection2D:getJoint(name) end ---render ---@overload fun() ---@param camera CameraComponentWrapper function JointCollection2D:render(camera) end return JointCollection2D ================================================ FILE: apis/engine_api/Joystick.lua ================================================ ---@class Joystick ---@type JoystickDevice[] ---@field isSupported boolean local Joystick = {} return Joystick ================================================ FILE: apis/engine_api/JoystickDevice.lua ================================================ ---@class JoystickDevice ---@field isConnected boolean ---@field axisCount number local JoystickDevice = {} ---getAxis ---@param index number ---@return number function JoystickDevice:getAxis(index) end return JoystickDevice ================================================ FILE: apis/engine_api/JsonUtil.lua ================================================ ---@API ---@class JsonUtil Json通用类。 local JsonUtil = {} ---将一个lua表序列化为json字符串。 ---@param t table ---@return string function JsonUtil.toJson(t) end ---将一个json字符串反序列化为lua表。 ---@param json string ---@return table function JsonUtil.fromJson(json) end return JsonUtil ================================================ FILE: apis/engine_api/KeyTrigger.lua ================================================ ---@class KeyTrigger local KeyTrigger = {} --- ---@param listener table|function ---@return ListenerID function KeyTrigger:addListener(listener) end --- ---@param listenerID ListenerID function KeyTrigger:removeListener(listenerID) end return KeyTrigger ================================================ FILE: apis/engine_api/Keyboard.lua ================================================ ---@class Keyboard local Keyboard = {} ---isKeyPressed ---@param key Keys_Value ---@return boolean function Keyboard:isKeyPressed(key) end ---isKeyReleased ---@param key Keys_Value ---@return boolean function Keyboard:isKeyReleased(key) end ---getHotKeys ---@overload fun(key1:Keys_Value):HotKeyCombination ---@overload fun(key1:Keys_Value,key2:Keys_Value):HotKeyCombination ---@overload fun(key1:Keys_Value,key2:Keys_Value,key3:Keys_Value):HotKeyCombination ---@param key1 Keys_Value ---@param key2 Keys_Value ---@param key3 Keys_Value ---@return HotKeyCombination function Keyboard:getHotKeys(key1, key2, key3) end --- ---@param key Keys_Value ---@return KeyTrigger function Keyboard:getPressDownTrigger(key) end --- ---@param key Keys_Value ---@return KeyTrigger function Keyboard:getPressUpTrigger(key) end return Keyboard ================================================ FILE: apis/engine_api/Keys.lua ================================================ ---@API ---@class Keys_Value 描述一个键盘键值。 local Keys_Value = {} ---@class Keys 键盘键值枚举类。 ---@field None Keys_Value ---@field Back Keys_Value ---@field Tab Keys_Value ---@field Enter Keys_Value ---@field CapsLock Keys_Value ---@field Escape Keys_Value ---@field Space Keys_Value ---@field PageUp Keys_Value ---@field PageDown Keys_Value ---@field End Keys_Value ---@field Home Keys_Value ---@field Left Keys_Value ---@field Up Keys_Value ---@field Right Keys_Value ---@field Down Keys_Value ---@field Select Keys_Value ---@field Print Keys_Value ---@field Execute Keys_Value ---@field PrintScreen Keys_Value ---@field Insert Keys_Value ---@field Delete Keys_Value ---@field Help Keys_Value ---@field D0 Keys_Value ---@field D1 Keys_Value ---@field D2 Keys_Value ---@field D3 Keys_Value ---@field D4 Keys_Value ---@field D5 Keys_Value ---@field D6 Keys_Value ---@field D7 Keys_Value ---@field D8 Keys_Value ---@field D9 Keys_Value ---@field A Keys_Value ---@field B Keys_Value ---@field C Keys_Value ---@field D Keys_Value ---@field E Keys_Value ---@field F Keys_Value ---@field G Keys_Value ---@field H Keys_Value ---@field I Keys_Value ---@field J Keys_Value ---@field K Keys_Value ---@field L Keys_Value ---@field M Keys_Value ---@field N Keys_Value ---@field O Keys_Value ---@field P Keys_Value ---@field Q Keys_Value ---@field R Keys_Value ---@field S Keys_Value ---@field T Keys_Value ---@field U Keys_Value ---@field V Keys_Value ---@field W Keys_Value ---@field X Keys_Value ---@field Y Keys_Value ---@field Z Keys_Value ---@field LeftWindows Keys_Value ---@field RightWindows Keys_Value ---@field Apps Keys_Value ---@field Sleep Keys_Value ---@field NumPad0 Keys_Value ---@field NumPad1 Keys_Value ---@field NumPad2 Keys_Value ---@field NumPad3 Keys_Value ---@field NumPad4 Keys_Value ---@field NumPad5 Keys_Value ---@field NumPad6 Keys_Value ---@field NumPad7 Keys_Value ---@field NumPad8 Keys_Value ---@field NumPad9 Keys_Value ---@field Multiply Keys_Value ---@field Add Keys_Value ---@field Separator Keys_Value ---@field Subtract Keys_Value ---@field Decimal Keys_Value ---@field Divide Keys_Value ---@field F1 Keys_Value ---@field F2 Keys_Value ---@field F3 Keys_Value ---@field F4 Keys_Value ---@field F5 Keys_Value ---@field F6 Keys_Value ---@field F7 Keys_Value ---@field F8 Keys_Value ---@field F9 Keys_Value ---@field F10 Keys_Value ---@field F11 Keys_Value ---@field F12 Keys_Value ---@field F13 Keys_Value ---@field F14 Keys_Value ---@field F15 Keys_Value ---@field F16 Keys_Value ---@field F17 Keys_Value ---@field F18 Keys_Value ---@field F19 Keys_Value ---@field F20 Keys_Value ---@field F21 Keys_Value ---@field F22 Keys_Value ---@field F23 Keys_Value ---@field F24 Keys_Value ---@field NumLock Keys_Value ---@field Scroll Keys_Value ---@field LeftShift Keys_Value ---@field RightShift Keys_Value ---@field LeftControl Keys_Value ---@field RightControl Keys_Value ---@field LeftAlt Keys_Value ---@field RightAlt Keys_Value ---@field BrowserBack Keys_Value ---@field BrowserForward Keys_Value ---@field BrowserRefresh Keys_Value ---@field BrowserStop Keys_Value ---@field BrowserSearch Keys_Value ---@field BrowserFavorites Keys_Value ---@field BrowserHome Keys_Value ---@field VolumeMute Keys_Value ---@field VolumeDown Keys_Value ---@field VolumeUp Keys_Value ---@field MediaNextTrack Keys_Value ---@field MediaPreviousTrack Keys_Value ---@field MediaStop Keys_Value ---@field MediaPlayPause Keys_Value ---@field LaunchMail Keys_Value ---@field SelectMedia Keys_Value ---@field LaunchApplication1 Keys_Value ---@field LaunchApplication2 Keys_Value ---@field OemSemicolon Keys_Value ---@field OemPlus Keys_Value ---@field OemComma Keys_Value ---@field OemMinus Keys_Value ---@field OemPeriod Keys_Value ---@field OemQuestion Keys_Value ---@field OemTilde Keys_Value ---@field OemOpenBrackets Keys_Value ---@field OemPipe Keys_Value ---@field OemCloseBrackets Keys_Value ---@field OemQuotes Keys_Value ---@field Oem8 Keys_Value ---@field OemBackslash Keys_Value ---@field ProcessKey Keys_Value ---@field Attn Keys_Value ---@field Crsel Keys_Value ---@field Exsel Keys_Value ---@field EraseEof Keys_Value ---@field Play Keys_Value ---@field Zoom Keys_Value ---@field Pa1 Keys_Value ---@field OemClear Keys_Value ---@field ChatPadGreen Keys_Value ---@field ChatPadOrange Keys_Value ---@field Pause Keys_Value ---@field ImeConvert Keys_Value ---@field ImeNoConvert Keys_Value ---@field Kana Keys_Value ---@field Kanji Keys_Value ---@field OemAuto Keys_Value ---@field OemCopy Keys_Value ---@field OemEnlW Keys_Value local Keys = {} return Keys ================================================ FILE: apis/engine_api/ListenerID.lua ================================================ ---@class ListenerID local ListenerID = {} return ListenerID ================================================ FILE: apis/engine_api/Log.lua ================================================ ---@API ---@class Log 日志类。 local Log = {} ---输出一条信息日志。 ---@param msg string function Log.info(msg) end ---输出一条警告日志。 ---@param msg string function Log.warn(msg) end ---输出一条崩溃日志。 ---@param msg string function Log.fatal(msg) end ---输出一条错误日志。 ---@param msg string function Log.error(msg) end ---输出一条调试日志。 ---@param msg string function Log.debug(msg) end return Log ================================================ FILE: apis/engine_api/MathHelper.lua ================================================ ---@class MathHelper ---@field pi number local MathHelper = {} ---degreeToRadian ---@param angle number ---@return number function MathHelper.degreeToRadian(angle) end ---radianToDegree ---@param angle number ---@return number function MathHelper.radianToDegree(angle) end return MathHelper ================================================ FILE: apis/engine_api/Matrix.lua ================================================ ---@API ---@class Matrix 描述一个4x4矩阵。 ---@field m11 number ---@field m12 number ---@field m13 number ---@field m14 number ---@field m21 number ---@field m22 number ---@field m23 number ---@field m24 number ---@field m31 number ---@field m32 number ---@field m33 number ---@field m34 number ---@field m41 number ---@field m42 number ---@field m43 number ---@field m44 number ---@field up Vector3 上向量{M21, M22, M23}。 ---@field down Vector3 下向量{-M21, -M22, -M23}。 ---@field left Vector3 左向量{-M11, -M12, -M13}。 ---@field right Vector3 右向量{M11, M12, M13}。 ---@field forward Vector3 前向量{-M31, -M32, -M33}。 ---@field backward Vector3 前向量{-M31, -M32, -M33}。 ---@field translation Vector3 存储坐标{M41, M42, M43}。 ---@field identity Matrix 返回单位矩阵。 local Matrix = {} --- ---@overload fun():Matrix ---@overload fun(row1:Vector4,row2:Vector4,row3:Vector4,row4:Vector4):Matrix ---@param m11 number ---@param m12 number ---@param m13 number ---@param m14 number ---@param m21 number ---@param m22 number ---@param m23 number ---@param m24 number ---@param m31 number ---@param m32 number ---@param m33 number ---@param m34 number ---@param m41 number ---@param m42 number ---@param m43 number ---@param m44 number ---@return Matrix function Matrix.new(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44) end ---@param value Matrix ---@return Matrix function Matrix.clone(value) end ---转置矩阵,即行列交换。 ---@return Matrix function Matrix:transpose() end ---返回包含指定矩阵中值的线性插值矩阵。 ---@param matrix Matrix 原始矩阵。 ---@param amount number 插值。 ---@return Matrix function Matrix:lerp(matrix, amount) end ---矩阵逆变换。 ---@return Matrix function Matrix:invert() end ---求矩阵行列式。 ---@return number function Matrix:determinant() end --- ---@param position Vector2 ---@return Vector2 function Matrix:transformVector2(position) end --- ---@param position Vector3 ---@return Vector3 function Matrix:transformVector3(position) end --- ---@param vector4 Vector4 ---@return Vector4 function Matrix:transformVector4(vector4) end --- ---@param vector3 Vector3 ---@return Vector4 function Matrix:transformVector4(vector3) end --- ---@param vector2 Vector2 ---@return Vector4 function Matrix:transformVector4(vector2) end ---构造一个View矩阵。 ---@param cameraPosition Vector3 摄像机坐标。 ---@param cameraTarget Vector3 摄像机目标向量。 ---@param cameraUpVector Vector3 摄像机上边缘方向。 ---@return Matrix function Matrix.createLookAt(cameraPosition, cameraTarget, cameraUpVector) end ---构造一个透视投影矩阵。 ---@param fieldOfView number y轴方向上的视场角度(弧度制)。 ---@param aspectRatio number 视景体的宽度与高度之比。 ---@param nearPlaneDistance number 沿z轴方向的两截面之间距离的近处。 ---@param farPlaneDistance number 沿z轴方向的两截面之间距离的远处。 ---@return Matrix function Matrix.createPerspectiveFOV(fieldOfView, aspectRatio, nearPlaneDistance, farPlaneDistance) end ---构造一个正视投影矩阵。 ---@param width number 视图宽度。 ---@param height number 视图高度。 ---@param zNearPlane number 近平面深度。 ---@param zFarPlane number 远平面深度 ---@return Matrix function Matrix.createOrthographicRH(width, height, zNearPlane, zFarPlane) end ---构造一个正视投影矩阵。 ---@param left number 投影区域最小x坐标。 ---@param right number 投影区域最大x坐标。 ---@param bottom number 投影区域最大y坐标。 ---@param top number 投影区域最小y坐标。 ---@param zNearPlane number 近平面深度。 ---@param zFarPlane number 远平面深度。 ---@return Matrix function Matrix.createOrthographicRH(left, right, bottom, top, zNearPlane, zFarPlane) end ---构造一个正视投影矩阵。 ---@param width number 视图宽度。 ---@param height number 视图高度。 ---@param zNearPlane number 近平面深度。 ---@param zFarPlane number 远平面深度。 ---@return Matrix function Matrix.createOrthographicLH(width, height, zNearPlane, zFarPlane) end ---构造一个正视投影矩阵。 ---@param left number 投影区域最小x坐标。 ---@param right number 投影区域最大x坐标。 ---@param bottom number 投影区域最大y坐标。 ---@param top number 投影区域最小y坐标。 ---@param zNearPlane number 近平面深度。 ---@param zFarPlane number 远平面深度。 ---@return Matrix function Matrix.createOrthographicLH(left, right, bottom, top, zNearPlane, zFarPlane) end ---构造一个绕X轴旋转的矩阵。 ---@param radians number 旋转弧度。 ---@return Matrix function Matrix.createRotationX(radians) end ---构造一个绕Y轴旋转的矩阵。 ---@param radians number 旋转弧度。 ---@return Matrix function Matrix.createRotationY(radians) end ---构造一个绕Z轴旋转的矩阵。 ---@param radians number 旋转弧度。 ---@return Matrix function Matrix.createRotationZ(radians) end ---构造一个放缩矩阵。 ---@param scale number XYZ轴的放缩大小。 ---@return Matrix function Matrix.createScale(scale) end ---构造一个放缩矩阵。 ---@param scaleX number X轴的放缩大小。 ---@param scaleY number Y轴的放缩大小。 ---@param scaleZ number Z轴的放缩大小。 ---@return Matrix function Matrix.createScale(scaleX, scaleY, scaleZ) end ---构造一个放缩矩阵。 ---@param scales Vector3 XYZ轴的放缩向量。 ---@return Matrix function Matrix.createScale(scales) end return Matrix ================================================ FILE: apis/engine_api/MeshFilterComponentWrapper.lua ================================================ ---@class MeshFilterComponentWrapper:ComponentWrapper local MeshFilterComponentWrapper = {} return MeshFilterComponentWrapper ================================================ FILE: apis/engine_api/MeshRendererComponentWrapper.lua ================================================ ---@class MeshRendererComponentWrapper:ComponentWrapper local MeshRendererComponentWrapper = {} return MeshRendererComponentWrapper ================================================ FILE: apis/engine_api/Mouse.lua ================================================ ---@class Mouse ---@field position Vector2 ---@field normalizedPosition Vector2 ---@field isLeftButtonPressed boolean ---@field isRightButtonPressed boolean ---@field isMiddleButtonPressed boolean ---@field isLeftButtonInstantDown boolean ---@field isRightButtonInstantDown boolean ---@field isMiddleButtonInstantDown boolean ---@field isLeftButtonInstantUp boolean ---@field isRightButtonInstantUp boolean ---@field isMiddleButtonInstantUp boolean ---@field isLeftButtonDoubleClick boolean ---@field isRightButtonDoubleClick boolean ---@field isMiddleButtonDoubleClick boolean local Mouse = {} --- ---@param listener table|function ---@return ListenerID function Mouse:addScrollListener(listener) end --- ---@param listenerID ListenerID function Mouse:removeScrollListener(listenerID) end ---setCursorVisible ---@param visible boolean function Mouse:setCursorVisible(visible) end return Mouse ================================================ FILE: apis/engine_api/NetMode.lua ================================================ ---@API ---@class NetMode 网络模式类。 ---@field current NetMode 获取当前线程的网络模式。 ---@field Client NetMode 客户端模式。 ---@field Server NetMode 服务端模式。 ---@field Normal NetMode 通用模式。 local NetMode = {} return NetMode ================================================ FILE: apis/engine_api/ObbDouble.lua ================================================ ---@API ---@class ObbDouble:SerializableType 描述一个旋转矩形对象。 ---@field centerX number 矩形中心点横坐标。 ---@field centerY number 矩形中心点纵坐标。 ---@field width number 矩形宽度。 ---@field height number 矩形高度。 ---@field angle number 矩形旋转角度。 local ObbDouble = {} ---创建一个旋转矩形对象。 ---@param centerX number 矩形中心点横坐标。 ---@param centerY number 矩形中心点纵坐标。 ---@param width number 矩形宽度。 ---@param height number 矩形高度。 ---@param angle number 矩形旋转角度。 ---@return ObbDouble 新的旋转矩形对象。 function ObbDouble.new(centerX, centerY, width, height, angle) end ---判断当前旋转矩形是否与另一个旋转矩形重叠。 ---@param otherObb ObbDouble ---@return boolean function ObbDouble:isOverlapping(otherObb) end ---判断指定点是否在当前旋转矩形区域内。 ---@param vector2 Vector2 ---@return boolean function ObbDouble:isPointIn(vector2) end ---获取矩形空间内的点在矩形空间外的实际坐标。 ---@param xInSource number 矩形空间内的点X。 ---@param yInSource number 矩形空间内的点Y。 ---@return number,number function ObbDouble:convertFromSourceRectSpace(xInSource, yInSource) end return ObbDouble ================================================ FILE: apis/engine_api/Path.lua ================================================ ---@API ---@class Path 标准化路径处理类。本项目对于文件路径,认为形如如下的路径都是标准化的。文件夹:Folder、Folder/Folder;文件:File.ext、Folder/File.ext。 local Path = {} ---修正路径为标准化路径。 ---@param path string 原始路径。 ---@return string 标准化路径。 function Path.fix(path) end ---连接路径。 ---@overload fun(path1:string,path2:string):string ---@overload fun(path1:string,path2:string,path3:string):string ---@param path1 string ---@param path2 string ---@param path3 string ---@param path4 string ---@return string 标准化路径。 function Path.join(path1, path2, path3, path4) end ---获取后缀名称。例:"abc/test.png",返回".png"。 ---@param path string ---@return string function Path.getExtension(path) end ---获取文件名。例:"abc/test.png",返回"test.png"。 ---@param path string ---@return string function Path.getFileName(path) end ---获取不带后缀的文件名。例:"abc/test.png",返回"test"。 ---@param path string ---@return string function Path.getFileNameWithoutExtension(path) end ---获取相对路径。例:"folder","folder/folder2/test.txt",返回"folder2/test.txt"。 ---@param relativeTo string ---@param path string ---@return string function Path.getRelativePath(relativeTo, path) end ---判断是否是相对路径。例: --- ---(1)"folder","folder/folder2/test.txt",返回true。 --- ---(2)"folder_abc","folder/folder2/test.txt",返回false。 --- ---(3)"folder","folder_abc/folder2/test.txt",返回false。 ---@param relativeTo string ---@param path string ---@return boolean function Path.isRelativePath(relativeTo, path) end ---获取上级目录。例:"abc/def/test.txt"返回"abc/def"。 ---@param path string ---@return string function Path.getParentDirectory(path) end return Path ================================================ FILE: apis/engine_api/Quaternion.lua ================================================ ---@API ---@class Quaternion:Vector4 描述一个四元数。 ---@field identity Quaternion 返回归一化四元数。 ---@field eulerAngles Vector3 返回或设置欧拉旋转轴。 ---@field matrix Matrix 返回或设置其矩阵形式。 local Quaternion = {} ---返回两个四元数之间的角度。 ---@param lhs Quaternion ---@param rhs Quaternion ---@return number function Quaternion.angle(lhs, rhs) end ---由欧拉角创建一个四元数。 ---@param yaw number ---@param pitch number ---@param roll number ---@return Quaternion function Quaternion.euler(yaw, pitch, roll) end ---由欧拉角创建一个四元数。 ---@param eulerAngles Vector3 ---@return Quaternion function Quaternion.euler(eulerAngles) end ---创建一个绕着指定轴旋转指定角度的旋转四元数。 ---@param angle number ---@param axis Vector3 ---@return Quaternion function Quaternion.angleAxis(angle, axis) end ---获得旋转轴和旋转角度。 ---@return number,Vector3 function Quaternion:toAngleAxis() end ---在四元数a和b之间进行球形插值。 ---@param a Quaternion ---@param b Quaternion ---@param t number 插值因子[0, 1]。 ---@return Quaternion function Quaternion.slerp(a, b, t) end ---在四元数a和b之间进行插值。 ---@param a Quaternion ---@param b Quaternion ---@param t number 插值因子[0, 1]。 ---@return Quaternion function Quaternion.lerp(a, b, t) end ---创建一个从角度fromDirection到角度toDirection的旋转四元数。 ---@param fromDirection Vector3 ---@param toDirection Vector3 ---@return Quaternion function Quaternion.rotationFromTo(fromDirection, toDirection) end return Quaternion ================================================ FILE: apis/engine_api/Random.lua ================================================ ---@class Random local Random = {} ---next ---@param n number ---@return number function Random:next(n) end ---@return number function Random:nextByte() end ---nextTry ---@param n number ---@return boolean function Random:nextTry(n) end ---nextArea ---@param begin number ---@param len number ---@return number function Random:nextArea(begin, len) end ---nextFloat ---@param value number ---@return number function Random:nextFloat(value) end ---nextFloatArea ---@param begin number ---@param len number ---@return number function Random:nextFloatArea(begin, len) end ---nextSym ---@param value number ---@return number function Random:nextSym(value) end return Random ================================================ FILE: apis/engine_api/Rect.lua ================================================ ---@API ---@class Rect:SerializableType 描述一个矩形区域,坐标精度为int,尺寸精度为int。 ---@field x number 矩形左上角横坐标。 ---@field y number 矩形左上角纵坐标。 ---@field width number 矩形宽度。 ---@field height number 矩形高度。 ---@field rightX number 矩形右边缘横坐标。 ---@field bottomY number 矩形下边缘纵坐标。 ---@field centerX number 矩形中心横坐标。 ---@field centerY number 矩形中心纵坐标。 local Rect = {} ---创建一个矩形区域对象。 ---@param x number ---@param y number ---@param width number ---@param height number ---@return Rect 新的矩形区域对象。 function Rect.new(x, y, width, height) end return Rect ================================================ FILE: apis/engine_api/RectFloat.lua ================================================ ---@API ---@class RectFloat:SerializableType 描述一个矩形区域,坐标精度为float,尺寸精度为int。 ---@field x number 矩形左上角横坐标。 ---@field y number 矩形左上角纵坐标。 ---@field width number 矩形宽度。 ---@field height number 矩形高度。 ---@field rightX number 矩形右边缘横坐标。 ---@field bottomY number 矩形下边缘纵坐标。 ---@field centerX number 矩形中心横坐标。 ---@field centerY number 矩形中心纵坐标。 local RectFloat = {} ---创建一个矩形区域对象。 ---@param x number ---@param y number ---@param width number ---@param height number ---@return RectFloat 新的矩形区域对象。 function RectFloat.new(x, y, width, height) end return RectFloat ================================================ FILE: apis/engine_api/RectFloatEx.lua ================================================ ---@API ---@class RectFloatEx:SerializableType 描述一个矩形区域,坐标精度为float,尺寸精度为float。 ---@field x number 矩形左上角横坐标。 ---@field y number 矩形左上角纵坐标。 ---@field width number 矩形宽度。 ---@field height number 矩形高度。 ---@field rightX number 矩形右边缘横坐标。 ---@field bottomY number 矩形下边缘纵坐标。 ---@field centerX number 矩形中心横坐标。 ---@field centerY number 矩形中心纵坐标。 local RectFloatEx = {} ---创建一个矩形区域对象。 ---@param x number ---@param y number ---@param width number ---@param height number ---@return RectFloatEx 新的矩形区域对象。 function RectFloatEx.new(x, y, width, height) end return RectFloatEx ================================================ FILE: apis/engine_api/Registry.lua ================================================ ---@class Registry local Registry = {} ---add ---@param name string ---@param any any function Registry:add(name, any) end ---remove ---@param name string function Registry:remove(name) end ---get ---@param name string ---@return any function Registry:get(name) end return Registry ================================================ FILE: apis/engine_api/Rigidbody.lua ================================================ ---@class Rigidbody ---@field velocity Vector3 ---@field acceleration Vector3 local Rigidbody = {} return Rigidbody ================================================ FILE: apis/engine_api/Schedule.lua ================================================ ---@class Schedule local Schedule = {} --- ---@param listener table|function ---@return ListenerID function Schedule:addListener(listener) end --- ---@param listenerID ListenerID function Schedule:removeListener(listenerID) end return Schedule ================================================ FILE: apis/engine_api/ScheduleID.lua ================================================ ---@class ScheduleID local ScheduleID = {} return ScheduleID ================================================ FILE: apis/engine_api/SerializableType.lua ================================================ ---@API ---@class SerializableType 可序列化类型。 local SerializableType = {} ---从json字符串中,反序列化得到数据。 ---@param json string json字符串。 function SerializableType:fromJson(json) end ---将当前数据序列化得到json字符串。 ---@return string json字符串。 function SerializableType:toJson() end return SerializableType ================================================ FILE: apis/engine_api/Size.lua ================================================ ---@API ---@class Size:SerializableType 描述一个尺寸。 ---@field width number 宽度。 ---@field height number 高度。 local Size = {} ---创建一个尺寸对象。 ---@overload fun():Size ---@param width number 宽度。 ---@param height number 宽度。 ---@return Size 新的尺寸对象。 function Size.new(width, height) end ---克隆一个尺寸对象。 ---@param value Size 原尺寸对象。 ---@return Size 新的尺寸对象。 function Size.clone(value) end return Size ================================================ FILE: apis/engine_api/SliderDirection.lua ================================================ ---@class SliderDirection_Value ---@class SliderDirection ---@field LeftRight SliderDirection_Value ---@field RightLeft SliderDirection_Value ---@field TopBottom SliderDirection_Value ---@field BottomTop SliderDirection_Value local SliderDirection = {} return SliderDirection ================================================ FILE: apis/engine_api/Sprite.lua ================================================ ---@API ---@class Sprite 精灵渲染类。 local Sprite = {} ---开始一批精灵渲染。 function Sprite.beginBatch() end ---结束一批精灵渲染。 function Sprite.endBatch() end ---将当前缓存的所有精灵,立即绘制到帧缓存上。 function Sprite.flush() end ---绘制一个精灵。 ---@overload fun(textureLocation:TextureLocation,pos:Vector2,sourceOffset:Rect,color:Color) ---@overload fun(textureLocation:TextureLocation,pos:Vector2,sourceOffset:Rect,color:Color,depth:number) ---@param textureLocation TextureLocation 待绘制的纹理。 ---@param pos Vector2 绘制在帧缓存上的坐标。 ---@param sourceRect Rect 绘制纹理的剪裁区域。 ---@param color Color 绘制精灵的颜色。 ---@param exData SpriteExData 精灵绘制拓展信息。 ---@param depth number 绘制到帧缓存上的深度。 function Sprite.draw(textureLocation, pos, sourceRect, color, exData, depth) end return Sprite ================================================ FILE: apis/engine_api/SpriteExData.lua ================================================ ---@API ---@class SpriteExData 描述精灵绘制拓展信息。 ---@field scaleRateX number 精灵绘制时横向放大比例。 ---@field scaleRateY number 精灵绘制时纵向放大比例。 ---@field originX number 精灵绘制原点横坐标。 ---@field originY number 精灵绘制原点纵坐标。 ---@field scaleRate Vector2 精灵绘制时放大比例。 ---@field origin Vector2 精灵绘制原点坐标。 ---@field angle number 精灵绘制的旋转角度。 ---@field flipHorizontal boolean 精灵绘制时是否水平翻转。 ---@field flipVertical boolean 精灵绘制时是否竖直翻转。 local SpriteExData = {} ---创建一个精灵绘制拓展信息对象。 ---@return SpriteExData 新的精灵绘制拓展信息对象。 function SpriteExData.new() end return SpriteExData ================================================ FILE: apis/engine_api/TextAlignment.lua ================================================ ---@class TextAlignment_Value ---@class TextAlignment ---@field Left TextAlignment_Value ---@field Right TextAlignment_Value ---@field HCenter TextAlignment_Value ---@field Top TextAlignment_Value ---@field Bottom TextAlignment_Value ---@field VCenter TextAlignment_Value local TextAlignment = {} return TextAlignment ================================================ FILE: apis/engine_api/TextBuffer.lua ================================================ ---@class TextBuffer ---@field style TextStyle ---@field actualArea RectFloat local TextBuffer = {} return TextBuffer ================================================ FILE: apis/engine_api/TextEditLineType.lua ================================================ ---@class TextEditLineType_Value ---@class TextEditLineType ---@field SingleLine TextAlignment_Value ---@field MultiLineSubmit TextAlignment_Value ---@field MultiLineNextLine TextAlignment_Value local TextEditLineType = {} return TextEditLineType ================================================ FILE: apis/engine_api/TextHorizontalOverflow.lua ================================================ ---@class TextHorizontalOverflow_Value ---@class TextHorizontalOverflow ---@field Wrap TextHorizontalOverflow_Value ---@field Overflow TextHorizontalOverflow_Value local TextHorizontalOverflow = {} return TextHorizontalOverflow ================================================ FILE: apis/engine_api/TextStyle.lua ================================================ ---@class TextStyle ---@field fontName string ---@field fontSize number ---@field color Color ---@field isRichText boolean ---@field horizontalAlignment TextAlignment ---@field verticalAlignment TextAlignment ---@field horizontalOverflow TextHorizontalOverflow_Value ---@field verticalOverflow TextVerticalOverflow_Value local TextStyle = {} return TextStyle ================================================ FILE: apis/engine_api/TextVerticalOverflow.lua ================================================ ---@class TextVerticalOverflow_Value ---@class TextVerticalOverflow ---@field Truncate TextVerticalOverflow_Value ---@field Overflow TextVerticalOverflow_Value local TextVerticalOverflow = {} return TextVerticalOverflow ================================================ FILE: apis/engine_api/Texture.lua ================================================ ---@class Texture ---@field width number ---@field height number ---@field texelWidth number ---@field texelHeight number ---@field mipmapLevel number local Texture = {} return Texture ================================================ FILE: apis/engine_api/TextureLocation.lua ================================================ ---@API ---@class TextureLocation 描述一个纹理索引。 ---@field isSingleTexture boolean 当前纹理索引是否不是来自合图。 ---@field isAtlasArea boolean 当前纹理索引是否来自合图。 ---@field spriteZoomInTimes number 当纹理索引用于精灵渲染时,表示渲染时纹理放大倍数。 ---@field valid boolean 纹理是否有效。 local TextureLocation = {} ---创建一个纹理索引对象。 ---@param format number ---@param id number ---@return TextureLocation 新的纹理索引对象。 function TextureLocation.new(format, id) end ---克隆一个纹理索引对象。 ---@param value TextureLocation 原始纹理索引对象。 ---@return TextureLocation 新的纹理索引对象。 function TextureLocation.clone(value) end return TextureLocation ================================================ FILE: apis/engine_api/TextureManager.lua ================================================ ---@class TextureManager local TextureManager = {} ---load ---@param filePath string ---@return TextureLocation function TextureManager.load(filePath) end ---getSourceRect ---@field textureLocation TextureLocation ---@return Rect function TextureManager.getSourceRect(textureLocation) end return TextureManager ================================================ FILE: apis/engine_api/TexturePacker.lua ================================================ ---@class TexturePacker local TexturePacker = {} ---genAtlasFromFileSystem ---@overload fun(folderPath:string,subPaths:string[],ignorePaths:string[],atlasName:string):AtlasInfos ---@param folderPath string ---@param subPaths string[] ---@param ignorePaths string[] ---@param atlasName string ---@param maxSize number ---@return AtlasInfos function TexturePacker.genAtlasFromFileSystem(folderPath, subPaths, ignorePaths, atlasName, maxSize) end ---genAtlasFromAssetBundle ---@overload fun(assetBundle:AssetBundle,folderPath:string,subPaths:string[],ignorePaths:string[],atlasName:string):AtlasInfos ---@param assetBundle AssetBundle ---@param folderPath string ---@param subPaths string[] ---@param ignorePaths string[] ---@param atlasName string ---@param maxSize number ---@return AtlasInfos function TexturePacker.genAtlasFromAssetBundle(assetBundle, folderPath, subPaths, ignorePaths, atlasName, maxSize) end return TexturePacker ================================================ FILE: apis/engine_api/Time.lua ================================================ ---@class Time ---@field deltaTime number ---@field smoothDeltaTime number ---@field frameCount number ---@field realtimeSinceStartup number local Time = {} return Time ================================================ FILE: apis/engine_api/TimeDiff.lua ================================================ ---@class TimeDiff local TimeDiff = {} ---new ---@return TimeDiff function TimeDiff.new() end ---diff ---@return number function TimeDiff:diff() end return TimeDiff ================================================ FILE: apis/engine_api/Touch.lua ================================================ ---@class Touch ---@field position Vector2 ---@field normalizedPosition Vector2 ---@field id number local Touch = {} return Touch ================================================ FILE: apis/engine_api/Transform.lua ================================================ ---@class Transform ---@field position Vector3 ---@field rotation Quaternion ---@field scale Vector3 ---@field origin Vector3 ---@field eulerAngles Vector3 ---@field matrix Matrix local Transform = {} ---new ---@overload fun():Transform ---@overload fun(position:Vector3):Transform ---@overload fun(position:Vector3,rotation:Quaternion):Transform ---@param position Vector3 ---@param rotation Quaternion ---@param scale Vector3 ---@return Transform function Transform.new(position, rotation, scale) end return Transform ================================================ FILE: apis/engine_api/Transform2D.lua ================================================ ---@class Transform2D ---@field position Vector2 ---@field rotation number ---@field scale Vector2 ---@field origin Vector2 ---@field matrix Matrix ---@field worldMatrix Matrix local Transform2D = {} ---new ---@overload fun():Transform2D ---@overload fun(position:Vector2):Transform2D ---@overload fun(position:Vector2,rotation:number):Transform2D ---@param position Vector2 ---@param rotation number ---@param scale Vector2 ---@return Transform2D function Transform2D.new(position, rotation, scale) end return Transform2D ================================================ FILE: apis/engine_api/TransformComponentWrapper.lua ================================================ ---@class TransformComponentWrapper:ComponentWrapper ---@field position Vector3 ---@field rotation Quaternion ---@field scale Vector3 ---@field eulerAngles Vector3 ---@field localMatrix Matrix ---@field localToWorldMatrix Matrix ---@field worldToLocalMatrix Matrix local TransformComponentWrapper = {} return TransformComponentWrapper ================================================ FILE: apis/engine_api/UIButton.lua ================================================ ---@class UIButton:UINode ---@field targetSprite UISprite ---@field highlightedSprite UISprite ---@field pressedSprite UISprite ---@field selectedSprite UISprite ---@field disabledSprite UISprite ---@field selected boolean local UIButton = {} ---new ---@overload fun(name:string):UIButton ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@return UIButton function UIButton.new(name, x, y, width, height) end --- ---@param value UIButton ---@return UIButton function UIButton.clone(value) end ---case ---@param uiNode UINode ---@return UIButton function UIButton.cast(uiNode) end return UIButton ================================================ FILE: apis/engine_api/UICanvas.lua ================================================ ---@class UICanvas:UINode local UICanvas = {} ---new ---@overload fun(name:string):UICanvas ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@return UICanvas function UICanvas.new(name, x, y, width, height) end --- ---@param value UICanvas ---@return UICanvas function UICanvas.clone(value) end ---case ---@param uiNode UINode ---@return UICanvas function UICanvas.cast(uiNode) end function UICanvas:update() end function UICanvas:render() end ---screenPointToCanvasPoint ---@param screenPosition Vector2 ---@return Vector2 function UICanvas:screenPointToCanvasPoint(screenPosition) end ---canvasPointToScreenPoint ---@param canvasPosition Vector2 ---@return Vector2 function UICanvas:canvasPointToScreenPoint(canvasPosition) end return UICanvas ================================================ FILE: apis/engine_api/UIImage.lua ================================================ ---@class UIImage:UINode ---@field sprite UISprite local UIImage = {} ---new ---@overload fun(name:string):UIImage ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@return UIImage function UIImage.new(name, x, y, width, height) end --- ---@param value UIImage ---@return UIImage function UIImage.clone(value) end ---case ---@param uiNode UINode ---@return UIImage function UIImage.cast(uiNode) end return UIImage ================================================ FILE: apis/engine_api/UIInputField.lua ================================================ ---@class UIInputField:UINode ---@field horizontalAlignment TextAlignment_Value ---@field verticalAlignment TextAlignment_Value ---@field text string ---@field fontName string ---@field fontSize number ---@field color Color ---@field lineType TextEditLineType_Value local UIInputField = {} ---new ---@overload fun(name:string):UIInputField ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@return UIInputField function UIInputField.new(name, x, y, width, height) end --- ---@param value UIInputField ---@return UIInputField function UIInputField.clone(value) end ---case ---@param uiNode UINode ---@return UIInputField function UIInputField.cast(uiNode) end --- ---@param listener table|function ---@return ListenerID function UIInputField:addTextChangedListener(listener) end --- ---@param listenerID ListenerID function UIInputField:removeTextChangedListener(listenerID) end return UIInputField ================================================ FILE: apis/engine_api/UIJoystick.lua ================================================ ---@class UIJoystick:UINode ---@field frontSprite UISprite ---@field backSprite UISprite ---@field activeDistanceRate number ---@field controlRadius number ---@field controlledDistance number ---@field controlledDistanceRate number ---@field controlledAngle number ---@field controlledCenter Vector2 local UIJoystick = {} ---new ---@overload fun(name:string):UIJoystick ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@return UIJoystick function UIJoystick.new(name, x, y, width, height) end --- ---@param value UIJoystick ---@return UIJoystick function UIJoystick.clone(value) end ---case ---@param uiNode UINode ---@return UIJoystick function UIJoystick.cast(uiNode) end ---setControl ---@overload fun(v:Vector2) ---@param x number ---@param y number function UIJoystick:setControl(x, y) end ---@return boolean,boolean,boolean,boolean function UIJoystick:getControlledFourDirection() end return UIJoystick ================================================ FILE: apis/engine_api/UINode.lua ================================================ ---@API ---@class UINode 基本的UI节点,是所有类型UI节点的基类。 ---@field name string 节点名字。 ---@field anchorPoint Vector2 组件锚点。 ---@field anchorPointX number 锚点横坐标。 ---@field anchorPointY number 锚点纵坐标。 ---@field position Vector2 节点在父节点空间的坐标。 ---@field positionInCanvas Vector2 节点在画布空间的坐标。 ---@field positionX number 节点在父节点空间的横坐标。 ---@field positionY number 节点在父节点空间的纵坐标。 ---@field size Size 节点尺寸。 ---@field width number 节点宽度。 ---@field height number 节点高度。 ---@field visible boolean 节点是否可见。 ---@field leftMargin number 节点到父节点的左侧边距。 ---@field rightMargin number 节点到父节点的右侧边距。 ---@field topMargin number 节点到父节点的上侧边距。 ---@field bottomMargin number 节点到父节点的下侧边距。 ---@field leftMarginEnabled boolean 是否启用节点到父节点的左侧边距。 ---@field rightMarginEnabled boolean 是否启用节点到父节点的右侧边距。 ---@field topMarginEnabled boolean 是否启用节点到父节点的上侧边距。 ---@field bottomMarginEnabled boolean 是否启用节点到父节点的下侧边距。 ---@field autoStretchWidth boolean 是否根据左右侧边距自动拉伸适配宽度,若为false,则为根据左右侧边距水平居中。 ---@field autoStretchHeight boolean 是否根据上下侧边距自动拉伸适配高度,若为false,则为根据上下侧边距竖直居中。 ---@field touchable boolean 节点是否可被触碰。 ---@field tag number 节点附加值。 ---@field childTag number 节点作为子节点时的附加值。 ---@field isContainer boolean 节点是否作为裁切容器。 ---@field allowDoubleClick boolean 节点是否允许进行双击。 ---@field textBatchRendering boolean ---@field enableRenderTarget boolean 节点是否开启RenderTarget纹理缓存,开启后仅在内部节点更新时重绘纹理缓存。 ---@field isTouching boolean 当前节点是否被触碰中。 local UINode = {} ---new ---@return UINode function UINode.new() end ---clone ---@return UINode function UINode:clone() end ---@return boolean function UINode:valid() end ---setAnchorPoint ---@param x number ---@param y number function UINode:setAnchorPoint(x, y) end ---setPosition ---@param x number ---@param y number function UINode:setPosition(x, y) end ---setLocation ---@param x number ---@param y number ---@param width number ---@param height number function UINode:setLocation(x, y, width, height) end ---setSize ---@param width number ---@param height number function UINode:setSize(width, height) end ---addChild ---@overload fun(node:UINode) ---@param node UINode ---@param childTag number function UINode:addChild(node, childTag) end ---removeChild ---@param node UINode function UINode:removeChild(node) end function UINode:removeAllChildren() end ---applyMargin ---@param applyAllChildren boolean function UINode:applyMargin(applyAllChildren) end ---setLeftMargin ---@param offset number ---@param enabled boolean function UINode:setLeftMargin(offset, enabled) end ---setRightMargin ---@param offset number ---@param enabled boolean function UINode:setRightMargin(offset, enabled) end ---setTopMargin ---@param offset number ---@param enabled boolean function UINode:setTopMargin(offset, enabled) end ---setBottomMargin ---@param offset number ---@param enabled boolean function UINode:setBottomMargin(offset, enabled) end ---setMarginEnabled ---@param left boolean ---@param top boolean ---@param right boolean ---@param bottom boolean function UINode:setMarginEnabled(left, top, right, bottom) end ---setAutoStretch ---@param widthEnabled boolean ---@param heightEnabled boolean function UINode:setAutoStretch(widthEnabled, heightEnabled) end ---getChildByTag ---@param childTag number ---@return UINode function UINode:getChildByTag(childTag) end ---getChild ---@param name string ---@return UINode function UINode:getChild(name) end --- ---@param listener table|function ---@return ListenerID function UINode:addTouchDownListener(listener) end --- ---@param listenerID ListenerID function UINode:removeTouchDownListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function UINode:addTouchDoubleDownListener(listener) end --- ---@param listenerID ListenerID function UINode:removeTouchDoubleDownListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function UINode:addTouchMoveListener(listener) end --- ---@param listenerID ListenerID function UINode:removeTouchMoveListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function UINode:addTouchPointedMoveListener(listener) end --- ---@param listenerID ListenerID function UINode:removeTouchPointedMoveListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function UINode:addTouchUpListener(listener) end --- ---@param listenerID ListenerID function UINode:removeTouchUpListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function UINode:addTouchUpAfterMoveListener(listener) end --- ---@param listenerID ListenerID function UINode:removeTouchUpAfterMoveListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function UINode:addTouchPointedUpListener(listener) end --- ---@param listenerID ListenerID function UINode:removeTouchPointedUpListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function UINode:addMousePointedListener(listener) end --- ---@param listenerID ListenerID function UINode:removeMousePointedListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function UINode:addMousePointedEnterListener(listener) end --- ---@param listenerID ListenerID function UINode:removeMousePointedEnterListener(listenerID) end --- ---@param listener table|function ---@return ListenerID function UINode:addMousePointedLeaveListener(listener) end --- ---@param listenerID ListenerID function UINode:removeMousePointedLeaveListener(listenerID) end ---getPreDrawLayer ---@param layer number ---@return UINodeDrawLayer function UINode:getPreDrawLayer(layer) end ---getPostDrawLayer ---@param layer number ---@return UINodeDrawLayer function UINode:getPostDrawLayer(layer) end ---@return number function UINode:getChildrenCount() end ---getChildByIndex ---@param index number ---@return UINode function UINode:getChildByIndex(index) end ---getPointedNode ---@overload fun(canvasPosition:Vector2):UINode ---@param canvasPosition Vector2 ---@param isTouching boolean ---@return UINode function UINode:getPointedNode(canvasPosition, isTouching) end function UINode:flushRender() end return UINode ================================================ FILE: apis/engine_api/UINodeDrawLayer.lua ================================================ ---@class UINodeDrawLayer local UINodeDrawLayer = {} --- ---@param listener table|function ---@return ListenerID function UINodeDrawLayer:addListener(listener) end --- ---@param listenerID ListenerID function UINodeDrawLayer:removeListener(listenerID) end return UINodeDrawLayer ================================================ FILE: apis/engine_api/UIPanel.lua ================================================ ---@class UIPanel:UINode ---@field sprite UISprite local UIPanel = {} ---new ---@overload fun(name:string):UIPanel ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@return UIPanel function UIPanel.new(name, x, y, width, height) end --- ---@param value UIPanel ---@return UIPanel function UIPanel.clone(value) end ---case ---@param uiNode UINode ---@return UIPanel function UIPanel.cast(uiNode) end return UIPanel ================================================ FILE: apis/engine_api/UIScrollView.lua ================================================ ---@class UIScrollView:UINode ---@field sprite UISprite ---@field viewSize Size ---@field isScrollVertical boolean ---@field isScrollHorizontal boolean ---@field isScrollable boolean ---@field isScrolling boolean local UIScrollView = {} ---new ---@overload fun(name:string):UIScrollView ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@return UIScrollView function UIScrollView.new(name, x, y, width, height) end --- ---@param value UIScrollView ---@return UIScrollView function UIScrollView.clone(value) end ---case ---@param uiNode UINode ---@return UIScrollView function UIScrollView.cast(uiNode) end function UIScrollView:ScrollToTop() end function UIScrollView:ScrollToBottom() end function UIScrollView:ScrollToLeft() end function UIScrollView:ScrollToRight() end function UIScrollView:StopScrolling() end return UIScrollView ================================================ FILE: apis/engine_api/UISerializable.lua ================================================ ---@class UISerializable local UISerializable = {} ---ToDesignString ---@param uiNode UINode ---@return string function UISerializable.toDesignString(uiNode) end ---LoadDesignString ---@param designString string ---@return UINode function UISerializable.loadDesignString(designString) end ---ToBinary ---@param uiNode UINode ---@return Bytes function UISerializable.toBinary(uiNode) end ---LoadBinary ---@param bytes Bytes ---@param offset number ---@param size number ---@return UINode function UISerializable.loadBinary(bytes, offset, size) end return UISerializable ================================================ FILE: apis/engine_api/UISlices9.lua ================================================ ---@class UISlices9:SerializableType ---@field left number ---@field right number ---@field top number ---@field bottom number local UISlices9 = {} ---new ---@overload fun():UISlices9 ---@param left number ---@param top number ---@param right number ---@param bottom number ---@return UISlices9 function UISlices9.new(left, top, right, bottom) end return UISlices9 ================================================ FILE: apis/engine_api/UISlider.lua ================================================ ---@class UISlider:UINode ---@field barSprite UISprite ---@field activeBarSprite UISprite ---@field sliderSprite UISprite ---@field sliderSize Size ---@field maxValue number ---@field minValue number ---@field value number ---@field valueStep number ---@field rate number ---@field sliderDirection SliderDirection_Value local UISlider = {} ---new ---@overload fun(name:string):UISlider ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@return UISlider function UISlider.new(name, x, y, width, height) end --- ---@param value UISlider ---@return UISlider function UISlider.clone(value) end ---case ---@param uiNode UINode ---@return UISlider function UISlider.cast(uiNode) end --- ---@param listener table|function ---@return ListenerID function UISlider:addValueChangedListener(listener) end --- ---@param listenerID ListenerID function UISlider:removeValueChangedListener(listenerID) end return UISlider ================================================ FILE: apis/engine_api/UISprite.lua ================================================ ---@class UISprite:SerializableType ---@field textureName string ---@field textureLocation TextureLocation ---@field slices9 UISlices9 ---@field color Color ---@field style UISpriteStyle_Value ---@field positionOffset Vector2 local UISprite = {} ---new ---@overload fun():UISprite ---@param textureName string ---@return UISprite function UISprite.new(textureName) end ---clone ---@param value UISprite ---@return UISprite function UISprite.clone(value) end return UISprite ================================================ FILE: apis/engine_api/UISpriteStyle.lua ================================================ ---@class UISpriteStyle_Value ---@class UISpriteStyle ---@field Simple UISpriteStyle_Value ---@field Tiled UISpriteStyle_Value ---@field Filled UISpriteStyle_Value ---@field Slices9 UISpriteStyle_Value local UISpriteStyle = {} return UISpriteStyle ================================================ FILE: apis/engine_api/UISwitch.lua ================================================ ---@class UISwitch:UINode ---@field onBackgroundSprite UISprite ---@field offBackgroundSprite UISprite ---@field onSliderSprite UISprite ---@field offSliderSprite UISprite ---@field selected boolean ---@field fadeTime number ---@field sliderSize Size local UISwitch = {} ---new ---@overload fun(name:string):UISwitch ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@return UISwitch function UISwitch.new(name, x, y, width, height) end --- ---@param value UISwitch ---@return UISwitch function UISwitch.clone(value) end ---case ---@param uiNode UINode ---@return UISwitch function UISwitch.cast(uiNode) end ---setSelected ---@overload fun(selected:boolean) ---@param selected boolean ---@param withAnimation boolean function UISwitch:setSelected(selected, withAnimation) end --- ---@param listener table|function ---@return ListenerID function UISwitch:addSelectChangedListener(listener) end --- ---@param listenerID ListenerID function UISwitch:removeSelectChangedListener(listenerID) end return UISwitch ================================================ FILE: apis/engine_api/UIText.lua ================================================ ---@class UIText:UINode ---@field horizontalAlignment TextAlignment_Value ---@field verticalAlignment TextAlignment_Value ---@field verticalOverflow TextHorizontalOverflow_Value ---@field horizontalOverflow TextVerticalOverflow_Value ---@field text string ---@field fontName string ---@field fontSize number ---@field color Color ---@field autoAdaptSize boolean ---@field displayTextSize Size ---@field preferredSize Size ---@field preferredWidth number ---@field preferredHeight number ---@field isRichText boolean ---@field outlineSize number ---@field outlineColor Color local UIText = {} ---new ---@overload fun(name:string):UIText ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@return UIText function UIText.new(name, x, y, width, height) end --- ---@param value UIText ---@return UIText function UIText.clone(value) end ---case ---@param uiNode UINode ---@return UIText function UIText.cast(uiNode) end --- ---@param listener table|function ---@return ListenerID function UIText:addTextChangedListener(listener) end --- ---@param listenerID ListenerID function UIText:removeTextChangedListener(listenerID) end return UIText ================================================ FILE: apis/engine_api/UITexturePool.lua ================================================ ---@class UITexturePool local UITexturePool = {} ---register ---@param name string ---@param textureLocation TextureLocation function UITexturePool.register(name, textureLocation) end ---unregister ---@param name string function UITexturePool.unregister(name) end ---registerFromFileSystem ---@param name string ---@param filePath string function UITexturePool.registerFromFileSystem(name, filePath) end return UITexturePool ================================================ FILE: apis/engine_api/Vector2.lua ================================================ ---@API ---@class Vector2:SerializableType 描述一个2维向量。 ---@field x number ---@field y number ---@field length number 向量长度。 ---@field lengthSquared number 向量长度的平方。 ---@field angle number 向量到原点的角度。 ---@field zero Vector2 返回零向量。 ---@field one Vector2 返回全1向量。 ---@field unitX Vector2 返回X轴单位向量。 ---@field unitY Vector2 返回Y轴单位向量。 local Vector2 = {} ---@overload fun():Vector2 ---@param x number ---@param y number ---@return Vector2 function Vector2.new(x, y) end ---@param value Vector2 ---@return Vector2 function Vector2.clone(value) end ---获取向量到另一个向量的角度。 ---@param other Vector2 ---@return number function Vector2:getAngleTo(other) end ---获取另一个向量到当前向量的角度。 ---@param other Vector2 ---@return number function Vector2:getAngleFrom(other) end ---向量单位化。 ---@param value Vector2 ---@return Vector2 function Vector2.normalize(value) end ---获取两个向量的最大值向量。 ---@param value1 Vector2 ---@param value2 Vector2 ---@return Vector2 function Vector2.max(value1, value2) end ---获取两个向量的最小值向量。 ---@param value1 Vector2 ---@param value2 Vector2 ---@return Vector2 function Vector2.min(value1, value2) end ---将每个维度向下取整。 ---@param value Vector2 ---@return Vector2 function Vector2.floor(value) end ---将每个维度向上取整。 ---@param value Vector2 ---@return Vector2 function Vector2.ceil(value) end ---限制向量到给定范围。 ---@param value Vector2 ---@param min Vector2 ---@param max Vector2 ---@return Vector2 function Vector2.clamp(value, min, max) end ---获取向量之间的距离。 ---@param value1 Vector2 ---@param value2 Vector2 ---@return number function Vector2.getDistance(value1, value2) end ---获取向量之间的距离平方。 ---@param value1 Vector2 ---@param value2 Vector2 ---@return number function Vector2.getDistanceSquared(value1, value2) end ---将两个向量点乘,即每个维度乘积之和。 ---@param value1 Vector2 ---@param value2 Vector2 ---@return number function Vector2.dot(value1, value2) end return Vector2 ================================================ FILE: apis/engine_api/Vector3.lua ================================================ ---@API ---@class Vector3:SerializableType 描述一个3维向量。 ---@field x number ---@field y number ---@field z number ---@field length number 向量长度。 ---@field lengthSquared number 向量长度的平方。 ---@field zero Vector3 返回零向量。 ---@field one Vector3 返回全1向量。 ---@field unitX Vector3 返回X轴单位向量。 ---@field unitY Vector3 返回Y轴单位向量。 ---@field unitZ Vector3 返回Z轴单位向量。 ---@field up Vector3 ---@field down Vector3 ---@field left Vector3 ---@field right Vector3 ---@field forward Vector3 ---@field back Vector3 local Vector3 = {} ---@overload fun():Vector3 ---@overload fun(value:Vector2,z:number):Vector3 ---@param x number ---@param y number ---@param z number ---@return Vector3 function Vector3.new(x, y, z) end ---@param value Vector3 ---@return Vector3 function Vector3.clone(value) end ---向量单位化。 ---@param value Vector3 ---@return Vector3 function Vector3.normalize(value) end ---获取两个向量的最大值向量。 ---@param value1 Vector3 ---@param value2 Vector3 ---@return Vector3 function Vector3.max(value1, value2) end ---获取两个向量的最小值向量。 ---@param value1 Vector3 ---@param value2 Vector3 ---@return Vector3 function Vector3.min(value1, value2) end ---将每个维度向下取整。 ---@param value Vector3 ---@return Vector3 function Vector3.floor(value) end ---将每个维度向上取整。 ---@param value Vector3 ---@return Vector3 function Vector3.ceil(value) end ---限制向量到给定范围。 ---@param value Vector3 ---@param min Vector3 ---@param max Vector3 ---@return Vector3 function Vector3.clamp(value, min, max) end --- ---@param value1 Vector3 ---@param value2 Vector3 ---@return number function Vector3.getDistance(value1, value2) end ---获取向量之间的距离。 ---@param value1 Vector3 ---@param value2 Vector3 ---@return number function Vector3.getDistanceSquared(value1, value2) end ---将两个向量点乘,即每个维度乘积之和。 ---@param value1 Vector3 ---@param value2 Vector3 ---@return number function Vector3.dot(value1, value2) end ---返回两个向量的叉积。 ---@param value1 Vector3 ---@param value2 Vector3 ---@return Vector3 function Vector3.cross(value1, value2) end return Vector3 ================================================ FILE: apis/engine_api/Vector4.lua ================================================ ---@API ---@class Vector4:SerializableType 描述一个4维向量。 ---@field x number ---@field y number ---@field z number ---@field w number ---@field length number 向量长度。 ---@field lengthSquared number 向量长度的平方。 ---@field zero Vector4 返回零向量。 ---@field one Vector4 返回全1向量。 ---@field unitX Vector4 返回X轴单位向量。 ---@field unitY Vector4 返回Y轴单位向量。 ---@field unitZ Vector4 返回Z轴单位向量。 ---@field unitW Vector4 返回W轴单位向量。 local Vector4 = {} ---@overload fun():Vector4 ---@overload fun(value:Vector2,z:number,w:number):Vector4 ---@overload fun(value:Vector3,w:number):Vector4 ---@param x number ---@param y number ---@param z number ---@param w number ---@return Vector4 function Vector4.new(x, y, z, w) end ---@param value Vector4 ---@return Vector4 function Vector4.clone(value) end ---向量单位化。 ---@param value Vector4 ---@return Vector4 function Vector4.normalize(value) end ---获取两个向量的最大值向量。 ---@param value1 Vector4 ---@param value2 Vector4 ---@return Vector4 function Vector4.max(value1, value2) end ---获取两个向量的最小值向量。 ---@param value1 Vector4 ---@param value2 Vector4 ---@return Vector4 function Vector4.min(value1, value2) end ---将每个维度向下取整。 ---@param value Vector4 ---@return Vector4 function Vector4.floor(value) end ---将每个维度向上取整。 ---@param value Vector4 ---@return Vector4 function Vector4.ceil(value) end ---限制向量到给定范围。 ---@param value Vector4 ---@param min Vector4 ---@param max Vector4 ---@return Vector4 function Vector4.clamp(value, min, max) end ---获取向量之间的距离。 ---@param value1 Vector4 ---@param value2 Vector4 ---@return number function Vector4.getDistance(value1, value2) end ---获取向量之间的距离平方。 ---@param value1 Vector4 ---@param value2 Vector4 ---@return number function Vector4.getDistanceSquared(value1, value2) end ---将两个向量点乘,即每个维度乘积之和。 ---@param value1 Vector4 ---@param value2 Vector4 ---@return number function Vector4.dot(value1, value2) end return Vector4 ================================================ FILE: apis/engine_api/cls.lua ================================================ ---@class cls ---@field super cls local cls = {} ---class ---@param classname string ---@param super cls ---@return cls function class(classname, super) end function cls:__init(...) end return cls ================================================ FILE: apis/engine_api/utf8string.lua ================================================ ---https://github.com/blitmap/lua-utf8-simple ---@class utf8string local utf8string = {} ---maps f over s's utf8 characters f can accept args: (visual_index, utf8_character, byte_index) --- --- i is the character/letter index within the string --- --- c is the utf8 character (string of 1 or more bytes) --- --- b is the byte index within the string --- ---`for i, c, b in utf8string.chars('Αγαπώ τηγανίτες') do` --- ---` print(i, c, b)` --- ---`end` --- ---@overload fun(s:string):number, string, number ---@param s string ---@param no_subs boolean ---@return number, string, number function utf8string.chars(s, no_subs) end ---returns: (number) the number of utf8 characters in s (not the byte length) ---@param s string ---@return number function utf8string.len(s) end ---like string.sub() but i, j are utf8 strings --- ---a utf8-safe string.sub() ---@param s string ---@param i number ---@param j number ---@return string function utf8string.sub(s, i, j) end ---strip non-ascii characters from a utf8 string ---@param s string ---@return nil|string function utf8string.strip(s) end ---reverse a utf8 string ---@param s string ---@return string function utf8string.reverse(s) end ---replace all utf8 chars with mapping ---@param s string ---@return string function utf8string.replace(s, map) end return utf8string ================================================ FILE: atlas_config.json ================================================ [ { "name": "ui", "path": "ui_res", "size": 512 }, { "name": "trees", "path": "trees", "size": 2048 }, { "name": "skins", "path": "skins", "size": 1024 }, { "name": "buffs", "path": "buffs", "size": 256 }, { "name": "effects", "path": "effects", "size": 256, "excludes": [ "gore_([a-zA-Z0-9_]+).png" ] }, { "name": "gores", "path": "effects", "size": 256, "includes": [ "gore_([a-zA-Z0-9_]+).png" ] }, { "name": "npcs", "path": "npcs", "size": 1024 }, { "name": "projectiles", "path": "projectiles", "size": 256 }, { "name": "items", "path": "items", "size": 512, "excludes": [ "hat([0-9]+|).png", "body([0-9]+|).png", "leg([0-9]+|).png" ] }, { "name": "skins", "path": "items", "size": 1024, "includes": [ "hat([0-9]+|).png", "body([0-9]+|).png", "leg([0-9]+|).png" ] }, { "name": "furnitures", "path": "blocks/furnitures", "size": 512, "excludes": [ "[a-zA-Z0-9_]+_icon.png" ] }, { "name": "items", "path": "blocks/furnitures", "size": 512, "includes": [ "[a-zA-Z0-9_]+_icon.png" ] }, { "name": "tiles", "path": "blocks/tiles", "size": 1024, "excludes": [ "[a-zA-Z0-9_]+_icon.png" ] }, { "name": "items", "path": "blocks/tiles", "size": 512, "includes": [ "[a-zA-Z0-9_]+_icon.png" ] } ] ================================================ FILE: biome_types/Nether.json ================================================ { "Nether": { } } ================================================ FILE: biome_types/Radiation.json ================================================ { "Radiation": { } } ================================================ FILE: biome_types/Space.json ================================================ { "Space": { } } ================================================ FILE: biome_types/Surface.json ================================================ { "Surface": { "isSurface": true, "hasWallGen": true, "isWallFullGen": true } } ================================================ FILE: biome_types/TwilightForest.json ================================================ { "TwilightForest": { } } ================================================ FILE: biome_types/Underground.json ================================================ { "Underground": { "hasWallGen": true, "isWallFullGen": false } } ================================================ FILE: biomes/nethers/nether.json ================================================ { "nether": { "biomeType": "Nether", "parallaxes": { "deepRate": 0.9, "base": [ { "id": "lava_pile_hanging", "parallel": 4.0, "level": 2588 }, { "id": "lava_rock_hanging", "parallel": 2.0, "level": 2578 }, { "id": "lava_layer_hanging", "parallel": 1.25, "level": 2538 }, { "id": "lava_pile", "parallel": 2.5, "level": 2642 }, { "id": "lava_rock", "parallel": 2.0, "level": 2650 }, { "id": "lava_pile", "parallel": 1.75, "level": 2654 }, { "id": "lava_lake", "parallel": 1.5, "level": 2674 }, { "id": "lava_layer", "parallel": 1.25, "level": 2676 } ], "underground": "lava_wall", "linked": "lava_wall_link" }, "musics": { "underground": [ "mcnether1" ] }, "composition": { "main": { "id": "netherrack" }, "subs": [ { "id": "soul_sand" }, { "id": "glowstone" }, { "id": "magma_block" } ] }, "oreGroupName": "default", "grass": 1, "treeInfo": { "styles": [ "log_volcano_oak" ], "density": 0.25 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 4, "weight": 20 } ], "hangingWeight": 100, "hangingPlaceables": [] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_glowing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 10 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 2 }, { "itemId": "fire_bullet", "min": 1, "max": 6, "weight": 3 } ], "spawn": { "mobSpeed": 140, "maxMobSpawn": 10, "mobs": [ { "id": "magma_elf", "weight": 5 }, { "id": "magma_slime", "weight": 4 }, { "id": "zombie_pigman", "weight": 12 }, { "id": "ghast", "weight": 1 }, { "id": "blaze", "weight": 2 }, { "id": "wither_skeleton", "weight": 2 } ] }, "buildingInfo": [ { "buildingId": "nether_fortress", "density": 3.0 } ] } } ================================================ FILE: biomes/surfaces/badland.json ================================================ { "badland": { "biomeType": "Surface", "dayLight": 1.0, "skyColor": { "midDayTopColor": [ 98, 170, 192 ], "midDayBottomColor": [ 210, 226, 236 ], "midNightTopColor": [ 5, 8, 32 ], "midNightBottomColor": [ 20, 30, 68 ], "transATopColor": [ 98, 170, 192 ], "transABottomColor": [ 217, 198, 10 ], "transBTopColor": [ 44, 33, 10 ], "transBBottomColor": [ 155, 32, 10 ], "transCTopColor": [ 5, 8, 32 ], "transCBottomColor": [ 115, 32, 10 ] }, "subBiomes": { "subs": [ { "biome": "jungle", "minSize": 400, "maxSize": 500, "minX": 300, "maxX": 700 }, { "biome": "forest", "minSize": 400, "maxSize": 500, "minX": 300, "maxX": 700 }, { "biome": "tainted_land", "minSize": 400, "maxSize": 500, "minX": 300, "maxX": 700 }, { "biome": "ocean", "minSize": 200, "maxSize": 300, "minX": 300, "maxX": 700 }, { "biome": "flesh", "minSize": 200, "maxSize": 300, "minX": 300, "maxX": 700 }, { "biome": "mushroom_fields", "minSize": 400, "maxSize": 500, "minX": 300, "maxX": 700 } ] }, "terrains": { "terrains": [ { "id": "MountainTerrain", "times": 3.0, "size": 160, "height": 24 }, { "id": "BasinTerrain", "times": 3.0, "size": 50, "height": 12 }, { "id": "HillTerrain", "times": 5.0, "size": 200, "height": 10 }, { "id": "HillTerrain", "times": 6.0, "size": 100, "height": 8 }, { "id": "HillTerrain", "times": 4.0, "size": 80, "height": 4 }, { "id": "PlateauTerrain", "times": 3.0, "size": 100, "height": 10 } ], "specialTerrains": [ { "id": "Chasm", "times": 0.5, "size": 20, "height": 30 }, { "id": "SurfaceCave", "times": 1.0, "size": 60, "height": 0 }, { "id": "SurfaceCave", "times": 3.0, "size": 40, "height": 0 }, { "id": "SurfaceCave", "times": 7.0, "size": 30, "height": 0 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 0.9, "base": [ { "id": "waste_hill", "parallel": 8.0, "level": 360 }, { "id": "waste_hill3", "parallel": 6.0, "level": 364 }, { "id": "waste_hill2", "parallel": 4.0, "level": 370 }, { "id": "waste_back", "parallel": 3.0, "level": 376 }, { "id": "waste_back2", "parallel": 2.0, "level": 390 } ], "underground": "red_sand_wall", "linked": "red_sand_wall_link" }, "musics": { "daySurface": [ "day2", "day3", "day4", "day5", "mcday1", "mcday2", "mcday3", "mcday4" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "rain", "composition": { "main": { "id": "red_sand_stone" }, "subs": [ { "id": "red_sand" }, { "id": "red_sand" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_bare_oak" ], "density": 0.28 }, "grass": 0, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 10 }, { "id": "rock_waste", "weight": 20 }, { "id": "small_tree_waste", "weight": 30 }, { "id": "stone_decos_waste", "weight": 20 }, { "id": "sapling_cactus", "weight": 30 } ], "underWeight": 100, "undergroundPlaceables": [ { "id": "pot", "tag": 0, "weight": 10 }, { "id": "rock_waste", "weight": 10 }, { "id": "glowing_mushroom", "weight": 1 }, { "id": "stalactite_waste", "weight": 30 }, { "id": "stalactite_small_waste", "weight": 30 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_waste", "weight": 40 }, { "id": "stalactite_hanging_small_waste", "weight": 40 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_awkward", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_fire_resistance", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 10 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 8 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 6 } ], "daySpawn": { "mobSpeed": 500, "maxMobSpawn": 5, "mobs": [ { "id": "large_waste_slime", "weight": 5 }, { "id": "large_waste_block_slime", "weight": 3 }, { "id": "waste_block_slime", "weight": 4 }, { "id": "waste_mummy", "weight": 5 }, { "id": "waste_ghost", "weight": 4 }, { "id": "creeper", "weight": 2 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 300, "maxAnimalSpawn": 5, "animals": [] }, "nightSpawn": { "mobSpeed": 450, "maxMobSpawn": 6, "mobs": [ { "id": "large_waste_slime", "weight": 5 }, { "id": "large_waste_block_slime", "weight": 3 }, { "id": "waste_mummy", "weight": 5 }, { "id": "waste_ghost", "weight": 4 }, { "id": "zombie", "weight": 10 }, { "id": "husk", "weight": 10 }, { "id": "arrow_zombie", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 4 }, { "id": "creeper", "weight": 3 }, { "id": "flower_creeper", "weight": 1 }, { "id": "phantom", "weight": 2 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [ { "id": "waste_mummy", "weight": 5 }, { "id": "waste_ghost", "weight": 4 }, { "id": "zombie", "weight": 5 }, { "id": "bald_zombie", "weight": 8 }, { "id": "spider", "weight": 18 }, { "id": "skeleton", "weight": 3 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 2 }, { "id": "enderman", "weight": 3 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ ], "environmentBlocks": { "total": 1000, "blocks": [ { "id": "red_sand", "weight": 1 }, { "id": "red_sand_stone", "weight": 1 } ] } } } ================================================ FILE: biomes/surfaces/desert.json ================================================ { "desert": { "biomeType": "Surface", "dayLight": 1.0, "skyColor": { "midDayTopColor": [ 98, 170, 192 ], "midDayBottomColor": [ 210, 226, 236 ], "midNightTopColor": [ 5, 8, 32 ], "midNightBottomColor": [ 20, 30, 68 ], "transATopColor": [ 98, 170, 192 ], "transABottomColor": [ 217, 198, 10 ], "transBTopColor": [ 44, 33, 10 ], "transBBottomColor": [ 155, 32, 10 ], "transCTopColor": [ 5, 8, 32 ], "transCBottomColor": [ 115, 32, 10 ] }, "subBiomes": { "subs": [ { "biome": "jungle", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 400 }, { "biome": "jungle", "minSize": 300, "maxSize": 500, "minX": 600, "maxX": 800 }, { "biome": "tainted_land", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 400 }, { "biome": "tainted_land", "minSize": 300, "maxSize": 500, "minX": 600, "maxX": 800 }, { "biome": "flesh", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 400 }, { "biome": "flesh", "minSize": 300, "maxSize": 500, "minX": 600, "maxX": 800 }, { "biome": "volcano", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 400 }, { "biome": "volcano", "minSize": 300, "maxSize": 500, "minX": 600, "maxX": 800 } ] }, "terrains": { "terrains": [ { "id": "MountainTerrain", "times": 4.0, "size": 160, "height": 16 }, { "id": "BasinTerrain", "times": 3.0, "size": 50, "height": 20 }, { "id": "HillTerrain", "times": 5.0, "size": 60, "height": 7 }, { "id": "HillTerrain", "times": 5.0, "size": 100, "height": 8 }, { "id": "PlateauTerrain", "times": 3.0, "size": 100, "height": 12 } ], "specialTerrains": [ { "id": "Chasm", "times": 0.5, "size": 20, "height": 30 }, { "id": "SurfaceCave", "times": 2.0, "size": 60, "height": 0 }, { "id": "SurfaceCave", "times": 2.0, "size": 40, "height": 0 }, { "id": "SurfaceCave", "times": 8.0, "size": 20, "height": 0 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 1.0, "base": [ { "id": "desert_hill_new_2", "parallel": 6.0, "level": 371 }, { "id": "desert_hill_new", "parallel": 4.0, "level": 377 }, { "id": "desert_2", "parallel": 3.0, "level": 387 } ], "underground": "sand_wall", "linked": "sand_wall_link" }, "musics": { "daySurface": [ "day2", "day3", "day4", "day5", "mcday1", "mcday2", "mcday3", "mcday4" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "overcast", "composition": { "main": { "id": "sandstone" }, "subs": [ { "id": "sand" }, { "id": "cobblestone" } ] }, "oreGroupName": "default", "liquidInfo": {}, "treeInfo": { "styles": [ "log_cactus" ], "density": 0.28 }, "grass": 0, "distributions": { "airWeight": 300, "surfacePlaceables": [ { "id": "pot", "tag": 2, "weight": 10 }, { "id": "small_tree_desert", "weight": 20 }, { "id": "sapling_cactus", "weight": 30 } ], "underWeight": 200, "undergroundPlaceables": [ { "id": "pot", "tag": 2, "weight": 10 }, { "id": "small_tree_desert", "weight": 10 }, { "id": "rock", "weight": 10 }, { "id": "stone_pillar_desert", "weight": 10 }, { "id": "stalactite_desert", "weight": 20 }, { "id": "stalactite_small_desert", "weight": 20 }, { "id": "glowing_mushroom", "weight": 1 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_desert", "weight": 20 }, { "id": "stalactite_hanging_small_desert", "weight": 20 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 3, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_awkward", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_fire_resistance", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_glowing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 5, "weight": 15 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 8 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 8 }, { "itemId": "fire_bullet", "min": 1, "max": 4, "weight": 8 } ], "daySpawn": { "mobSpeed": 500, "maxMobSpawn": 5, "mobs": [ { "id": "desert_slime", "weight": 5 }, { "id": "large_desert_slime", "weight": 4 }, { "id": "eagle", "weight": 3 }, { "id": "mummy", "weight": 4 }, { "id": "creeper", "weight": 2 }, { "id": "husk", "weight": 3 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 300, "maxAnimalSpawn": 5, "animals": [] }, "nightSpawn": { "mobSpeed": 450, "maxMobSpawn": 6, "mobs": [ { "id": "large_desert_slime", "weight": 10 }, { "id": "eagle", "weight": 6 }, { "id": "mummy", "weight": 24 }, { "id": "zombie", "weight": 20 }, { "id": "husk", "weight": 20 }, { "id": "arrow_zombie", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 4 }, { "id": "creeper", "weight": 3 }, { "id": "flower_creeper", "weight": 1 }, { "id": "phantom", "weight": 2 }, { "id": "enderman", "weight": 4 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [ { "id": "large_desert_slime", "weight": 10 }, { "id": "mummy", "weight": 24 }, { "id": "zombie", "weight": 5 }, { "id": "husk", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "spider", "weight": 18 }, { "id": "bat", "weight": 5 }, { "id": "skeleton", "weight": 3 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 3 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ { "buildingId": "pyramid", "density": 1.0, "fixSurfaceLine": true, "genBeginXi": 50, "genEndXi": 1000 }, { "buildingId": "desert_house", "density": 2.0, "fixSurfaceLine": true, "genBeginXi": 50, "genEndXi": 1000 } ], "environmentBlocks": { "total": 1000, "blocks": [ { "id": "sandstone", "weight": 1 }, { "id": "sand", "weight": 1 }, { "id": "sandstone_smooth", "weight": 1 } ] } } } ================================================ FILE: biomes/surfaces/flesh.json ================================================ { "flesh": { "biomeType": "Surface", "dayLight": 0.75, "skyColor": { "midDayTopColor": [ 130, 22, 22 ], "midDayBottomColor": [ 150, 44, 44 ], "midNightTopColor": [ 32, 8, 8 ], "midNightBottomColor": [ 64, 16, 16 ], "transATopColor": [ 100, 18, 18 ], "transABottomColor": [ 100, 33, 33 ], "transBTopColor": [ 60, 16, 16 ], "transBBottomColor": [ 80, 24, 24 ], "transCTopColor": [ 32, 8, 8 ], "transCBottomColor": [ 72, 20, 20 ] }, "subBiomes": { "subs": [ { "biome": "jungle", "minSize": 200, "maxSize": 400, "minX": 400, "maxX": 600 }, { "biome": "tainted_land", "minSize": 300, "maxSize": 500, "minX": 400, "maxX": 600 }, { "biome": "volcano", "minSize": 200, "maxSize": 400, "minX": 400, "maxX": 600 } ] }, "terrains": { "terrains": [ { "id": "MountainTerrain", "times": 2.0, "size": 160, "height": 24 }, { "id": "BasinTerrain", "times": 3.0, "size": 50, "height": 8 }, { "id": "HillTerrain", "times": 3.0, "size": 200, "height": 10 }, { "id": "PlateauTerrain", "times": 3.0, "size": 100, "height": 10 } ], "specialTerrains": [ { "id": "Chasm", "times": 0.5, "size": 20, "height": 30 }, { "id": "SurfaceCave", "times": 1.0, "size": 60, "height": 0 }, { "id": "SurfaceCave", "times": 2.0, "size": 40, "height": 0 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 1.0, "base": [ { "id": "flesh_hill", "parallel": 8.0, "level": 360 }, { "id": "flesh_hill3", "parallel": 7.0, "level": 364 }, { "id": "flesh_hill2", "parallel": 6.5, "level": 368 }, { "id": "flesh_back", "parallel": 6.0, "level": 377 }, { "id": "flesh_fossil2", "parallel": 5.0, "level": 368 }, { "id": "flesh_back2", "parallel": 4.0, "level": 382 }, { "id": "flesh_fossil", "parallel": 3.0, "level": 373 }, { "id": "flesh_bush", "parallel": 2.0, "level": 393 } ], "underground": "flesh_wall", "linked": "flesh_wall_link" }, "musics": { "daySurface": [ "day2", "day3", "day4", "day5", "mcday1", "mcday2", "mcday3", "mcday4" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "rain", "composition": { "main": { "id": "flesh_dirt" }, "subs": [ { "id": "flesh_stone" }, { "id": "flesh_gut" }, { "id": "flesh_gut" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_dark_oak" ], "density": 0.18 }, "grass": 1, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 4, "weight": 40 }, { "id": "eyeball_grass", "weight": 40 }, { "id": "large_eyeball_grass", "weight": 40 }, { "id": "flesh_tentacle", "weight": 80 }, { "id": "blood_grass", "weight": 200 } ], "underWeight": 100, "undergroundPlaceables": [ { "id": "pot", "tag": 4, "weight": 40 }, { "id": "eyeball_grass", "weight": 40 }, { "id": "large_eyeball_grass", "weight": 40 }, { "id": "flesh_tentacle", "weight": 80 }, { "id": "blood_grass", "weight": 200 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "flesh_tentacle_hanging", "weight": 80 }, { "id": "eyeball_vine", "weight": 40 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_awkward", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_fire_resistance", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_swiftness", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 10 }, { "itemId": "blood_arrow", "min": 3, "max": 10, "weight": 8 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 2 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 2 }, { "itemId": "grenade", "min": 1, "max": 2, "weight": 3 } ], "daySpawn": { "mobSpeed": 200, "maxMobSpawn": 5, "mobs": [ { "id": "blood_eye", "weight": 10 }, { "id": "blood_slime", "weight": 8 }, { "id": "blood_bat", "weight": 4 }, { "id": "blood_skeleton", "weight": 4 }, { "id": "creeper", "weight": 1 }, { "id": "vampire_miner", "weight": 10 } ], "animalSpeed": 240, "maxAnimalSpawn": 5, "animals": [] }, "nightSpawn": { "mobSpeed": 250, "maxMobSpawn": 6, "mobs": [ { "id": "blood_eye", "weight": 14 }, { "id": "vampire_miner", "weight": 10 }, { "id": "blood_slime", "weight": 5 }, { "id": "blood_bat", "weight": 4 }, { "id": "blood_skeleton", "weight": 4 }, { "id": "zombie", "weight": 6 }, { "id": "arrow_zombie", "weight": 6 }, { "id": "bald_zombie", "weight": 5 }, { "id": "villager_zombie", "weight": 4 }, { "id": "skeleton", "weight": 4 }, { "id": "creeper", "weight": 3 }, { "id": "flower_creeper", "weight": 1 }, { "id": "phantom", "weight": 2 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [ { "id": "blood_eye", "weight": 4 }, { "id": "blood_slime", "weight": 14 }, { "id": "blood_bat", "weight": 4 }, { "id": "blood_skeleton", "weight": 4 }, { "id": "zombie", "weight": 5 }, { "id": "bald_zombie", "weight": 8 }, { "id": "spider", "weight": 18 }, { "id": "bat", "weight": 5 }, { "id": "skeleton", "weight": 3 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ ], "environmentBlocks": { "total": 1000, "blocks": [ { "id": "flesh_dirt", "weight": 1 }, { "id": "flesh_stone", "weight": 1 }, { "id": "flesh_gut", "weight": 1 } ] } } } ================================================ FILE: biomes/surfaces/forest.json ================================================ { "forest": { "biomeType": "Surface", "dayLight": 1.0, "subBiomes": { "subs": [ { "biome": "desert", "minSize": 160, "maxSize": 220, "minX": 100, "maxX": 200 }, { "biome": "badland", "minSize": 160, "maxSize": 200, "minX": 700, "maxX": 900 }, { "biome": "ocean", "minSize": 160, "maxSize": 260, "minX": 100, "maxX": 200 }, { "biome": "ocean", "minSize": 160, "maxSize": 260, "minX": 700, "maxX": 900 } ] }, "skyColor": { "midDayTopColor": [ 98, 170, 192 ], "midDayBottomColor": [ 210, 226, 236 ], "midNightTopColor": [ 5, 8, 32 ], "midNightBottomColor": [ 20, 30, 68 ], "transATopColor": [ 98, 170, 192 ], "transABottomColor": [ 217, 198, 10 ], "transBTopColor": [ 44, 33, 10 ], "transBBottomColor": [ 155, 32, 10 ], "transCTopColor": [ 5, 8, 32 ], "transCBottomColor": [ 115, 32, 10 ] }, "terrains": { "terrains": [ { "id": "MountainTerrain", "times": 3.0, "size": 200, "height": 20 }, { "id": "BasinTerrain", "times": 2.0, "size": 50, "height": 8 }, { "id": "HillTerrain", "times": 1.0, "size": 300, "height": 10 } ], "specialTerrains": [ { "id": "Chasm", "times": 0.5, "size": 20, "height": 30 }, { "id": "Lake", "times": 0.5, "size": 60, "height": 10 }, { "id": "Lake", "times": 1.0, "size": 40, "height": 10 }, { "id": "SurfaceCave", "times": 1.0, "size": 80, "height": 0 }, { "id": "SurfaceCave", "times": 3.0, "size": 60, "height": 0 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 1.0, "base": [ { "id": "snowy_hill", "parallel": 8.0, "level": 360 }, { "id": "snowy_hill2", "parallel": 6.0, "level": 364 }, { "id": "stone_hill", "parallel": 4.0, "level": 372 }, { "id": "large_grass_small_tree", "parallel": 3.5, "level": 363 }, { "id": "large_grass_medium_tree", "parallel": 3.0, "level": 368 }, { "id": "large_grass_tree", "parallel": 2.0, "level": 372 }, { "id": "large_bush", "parallel": 1.5, "level": 394 } ], "underground": "mud_wall", "linked": "mud_wall_link" }, "musics": { "daySurface": [ "day1", "day2", "day3", "day4", "day5", "mcday1", "mcday2", "mcday3", "mcday4" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "rain", "composition": { "main": { "id": "dirt" }, "subs": [ { "id": "cobblestone" }, { "id": "clay" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_oak", "log_birch" ], "density": 0.18 }, "plantInfo": { "makeSugarcane": true }, "grass": 1, "distributions": { "airWeight": 200, "surfacePlaceables": [ { "id": "grass", "weight": 100 }, { "id": "dandelion", "weight": 10 }, { "id": "allium", "weight": 10 }, { "id": "sunflower", "weight": 20 }, { "id": "brown_mushroom", "weight": 20 }, { "id": "red_mushroom", "weight": 20 }, { "id": "large_brown_mushroom", "weight": 5 }, { "id": "large_red_mushroom", "weight": 10 }, { "id": "lilac", "weight": 5 }, { "id": "red_tulip", "weight": 5 }, { "id": "white_tulip", "weight": 5 }, { "id": "orange_tulip", "weight": 5 }, { "id": "pink_tulip", "weight": 5 }, { "id": "small_tree_normal", "weight": 30 }, { "id": "stone_decos_normal", "weight": 15 }, { "id": "stone_decos_mossy", "weight": 15 }, { "id": "rock", "weight": 10 }, { "id": "bush", "weight": 20 } ], "underWeight": 100, "undergroundPlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "small_tree_normal", "weight": 3 }, { "id": "rock", "weight": 5 }, { "id": "large_brown_mushroom", "weight": 4 }, { "id": "large_red_mushroom", "weight": 3 } ], "hangingWeight": 40, "hangingPlaceables": [ { "id": "vine", "weight": 15 }, { "id": "stalactite_hanging_stone", "weight": 5 }, { "id": "stalactite_hanging_small_stone", "weight": 5 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 4, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_glowing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 2, "max": 6, "weight": 10 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 5 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 6 }, { "itemId": "fire_bullet", "min": 1, "max": 4, "weight": 4 } ], "daySpawn": { "mobSpeed": 640, "maxMobSpawn": 5, "mobs": [ { "id": "green_slime", "weight": 10 }, { "id": "large_green_slime", "weight": 5 }, { "id": "yellow_slime", "weight": 6 }, { "id": "blue_slime", "weight": 2 }, { "id": "purple_slime", "weight": 1 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 300, "maxAnimalSpawn": 5, "animals": [ { "id": "chicken", "weight": 10 }, { "id": "cow", "weight": 10 }, { "id": "white_rabbit", "weight": 10 }, { "id": "squid", "weight": 30 }, { "id": "light_blue_butterfly", "weight": 4 }, { "id": "red_butterfly", "weight": 4 }, { "id": "yellow_butterfly", "weight": 4 } ] }, "nightSpawn": { "mobSpeed": 460, "maxMobSpawn": 6, "mobs": [ { "id": "zombie", "weight": 20 }, { "id": "spider", "weight": 8 }, { "id": "arrow_zombie", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 4 }, { "id": "creeper", "weight": 3 }, { "id": "flower_creeper", "weight": 1 }, { "id": "phantom", "weight": 2 }, { "id": "fly_eye", "weight": 2 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 }, { "id": "black_rabbit", "weight": 3 } ] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [ { "id": "large_black_slime", "weight": 10 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "bat", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 3 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "mini_house", "density": 0.5, "isSpecificNoGen": true, "specificChunkXi": 0, "specificChunkYi": 0, "fixSurfaceLine": true, "genBeginXi": 400, "genEndXi": 600 } ] } } ================================================ FILE: biomes/surfaces/jungle.json ================================================ { "jungle": { "biomeType": "Surface", "dayLight": 1.0, "skyColor": { "midDayTopColor": [ 98, 170, 192 ], "midDayBottomColor": [ 210, 226, 236 ], "midNightTopColor": [ 5, 8, 32 ], "midNightBottomColor": [ 20, 30, 68 ], "transATopColor": [ 98, 170, 192 ], "transABottomColor": [ 217, 198, 10 ], "transBTopColor": [ 44, 33, 10 ], "transBBottomColor": [ 155, 32, 10 ], "transCTopColor": [ 5, 8, 32 ], "transCBottomColor": [ 115, 32, 10 ] }, "subBiomes": { "subs": [ { "biome": "snow_land", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 800 }, { "biome": "tainted_land", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 800 }, { "biome": "flesh", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 800 }, { "biome": "volcano", "minSize": 200, "maxSize": 300, "minX": 200, "maxX": 800 }, { "biome": "ocean", "minSize": 200, "maxSize": 300, "minX": 200, "maxX": 800 }, { "biome": "mushroom_fields", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 800 } ] }, "terrains": { "terrains": [ { "id": "MountainTerrain", "times": 6.0, "size": 200, "height": 5 }, { "id": "BasinTerrain", "times": 4.0, "size": 150, "height": 8 }, { "id": "HillTerrain", "times": 2.0, "size": 200, "height": 15 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 1.0, "base": [ { "id": "snowy_hill", "parallel": 8.0, "level": 358 }, { "id": "snowy_hill2", "parallel": 7.0, "level": 362 }, { "id": "dirty_hill", "parallel": 6.0, "level": 362 }, { "id": "jungle_bush", "parallel": 5.0, "level": 376 }, { "id": "stone_hill", "parallel": 4.0, "level": 377 }, { "id": "jungle_bush", "parallel": 3.0, "level": 380 }, { "id": "jungle_bush", "parallel": 2.0, "level": 386 }, { "id": "jungle_bush", "parallel": 1.5, "level": 396 } ], "underground": "mud_wall", "linked": "mud_wall_link" }, "musics": { "daySurface": [ "day1", "day2", "day3", "day4", "day5", "mcday1", "mcday2", "mcday3", "mcday4" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "rain", "composition": { "main": { "id": "coarse_dirt" }, "subs": [ { "id": "cobblestone" }, { "id": "dirt" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_jungle", "log_acacia" ], "density": 0.88 }, "plantInfo": { "makeSugarcane": true }, "grass": 1, "distributions": { "airWeight": 50, "surfacePlaceables": [ { "id": "grass", "weight": 50 }, { "id": "azure_bluet", "weight": 10 }, { "id": "blue_orchid", "weight": 10 }, { "id": "fern", "weight": 10 }, { "id": "glowing_mushroom", "weight": 10 }, { "id": "allium", "weight": 10 }, { "id": "peony", "weight": 10 }, { "id": "large_brown_mushroom", "weight": 5 }, { "id": "large_red_mushroom", "weight": 10 }, { "id": "rose_bush", "weight": 5 }, { "id": "red_tulip", "weight": 5 }, { "id": "white_tulip", "weight": 5 }, { "id": "orange_tulip", "weight": 5 }, { "id": "pink_tulip", "weight": 5 }, { "id": "small_tree_normal", "weight": 30 }, { "id": "stone_decos_normal", "weight": 15 }, { "id": "stone_decos_mossy", "weight": 15 }, { "id": "rock", "weight": 10 }, { "id": "bush", "weight": 20 }, { "id": "watermelon", "weight": 10 }, { "id": "pumpkin", "weight": 10 } ], "underWeight": 50, "undergroundPlaceables": [ { "id": "grass", "weight": 30 }, { "id": "pot", "tag": 0, "weight": 40 }, { "id": "small_tree_normal", "weight": 3 }, { "id": "rock", "weight": 5 }, { "id": "large_brown_mushroom", "weight": 4 }, { "id": "large_red_mushroom", "weight": 3 }, { "id": "pumpkin", "weight": 2 }, { "id": "watermelon", "weight": 2 }, { "id": "glowing_mushroom", "weight": 1 } ], "hangingWeight": 40, "hangingPlaceables": [ { "id": "vine", "weight": 50 }, { "id": "stalactite_hanging_stone", "weight": 5 }, { "id": "stalactite_hanging_small_stone", "weight": 5 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_glowing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 10 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "fire_bullet", "min": 3, "max": 6, "weight": 10 } ], "daySpawn": { "mobSpeed": 500, "maxMobSpawn": 5, "mobs": [ { "id": "green_slime", "weight": 5 }, { "id": "yellow_slime", "weight": 4 }, { "id": "blue_slime", "weight": 4 }, { "id": "purple_slime", "weight": 4 }, { "id": "block_slime", "weight": 2 }, { "id": "large_block_slime", "weight": 1 }, { "id": "spider", "weight": 1 }, { "id": "jungle_bat", "weight": 2 }, { "id": "large_jungle_bat", "weight": 1 }, { "id": "enderman", "weight": 4 } ], "animalSpeed": 300, "maxAnimalSpawn": 5, "animals": [ { "id": "chicken", "weight": 3 }, { "id": "cow", "weight": 2 }, { "id": "pig", "weight": 3 }, { "id": "wolf", "weight": 1 }, { "id": "cat", "weight": 1 }, { "id": "white_rabbit", "weight": 1 }, { "id": "black_rabbit", "weight": 1 }, { "id": "brown_rabbit", "weight": 1 }, { "id": "yellow_rabbit", "weight": 1 }, { "id": "squid", "weight": 8 }, { "id": "pufferfish", "weight": 4 }, { "id": "light_blue_butterfly", "weight": 1 }, { "id": "red_butterfly", "weight": 1 }, { "id": "yellow_butterfly", "weight": 1 } ] }, "nightSpawn": { "mobSpeed": 400, "maxMobSpawn": 7, "mobs": [ { "id": "large_jungle_bat", "weight": 5 }, { "id": "man_eater", "weight": 4 }, { "id": "zombie", "weight": 20 }, { "id": "arrow_zombie", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 4 }, { "id": "creeper", "weight": 1 }, { "id": "flower_creeper", "weight": 2 }, { "id": "phantom", "weight": 2 }, { "id": "bat", "weight": 3 }, { "id": "spider", "weight": 3 }, { "id": "doge_zombie", "weight": 2 }, { "id": "enderman", "weight": 3 } ], "animalSpeed": 400, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 8 }, { "id": "pufferfish", "weight": 4 } ] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [ { "id": "jungle_bat", "weight": 10 }, { "id": "large_jungle_bat", "weight": 6 }, { "id": "man_eater", "weight": 6 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "jungle_temple", "density": 0.70, "fixSurfaceLine": true, "genBeginXi": 100, "genEndXi": 900 } ], "environmentBlocks": { "total": 300, "blocks": [ { "id": "coarse_dirt", "weight": 1 } ] } } } ================================================ FILE: biomes/surfaces/mushroom_fields.json ================================================ { "mushroom_fields": { "biomeType": "Surface", "dayLight": 1.0, "skyColor": { "midDayTopColor": [ 98, 170, 192 ], "midDayBottomColor": [ 210, 226, 236 ], "midNightTopColor": [ 5, 8, 32 ], "midNightBottomColor": [ 20, 30, 68 ], "transATopColor": [ 98, 170, 192 ], "transABottomColor": [ 217, 198, 10 ], "transBTopColor": [ 44, 33, 10 ], "transBBottomColor": [ 155, 32, 10 ], "transCTopColor": [ 5, 8, 32 ], "transCBottomColor": [ 115, 32, 10 ] }, "subBiomes": { "subs": [ { "biome": "jungle", "minSize": 300, "maxSize": 400, "minX": 400, "maxX": 600 }, { "biome": "forest", "minSize": 300, "maxSize": 400, "minX": 400, "maxX": 600 }, { "biome": "desert", "minSize": 300, "maxSize": 400, "minX": 400, "maxX": 600 }, { "biome": "snow_land", "minSize": 400, "maxSize": 500, "minX": 400, "maxX": 600 }, { "biome": "ocean", "minSize": 100, "maxSize": 200, "minX": 400, "maxX": 600 } ] }, "terrains": { "terrains": [ { "id": "MountainTerrain", "times": 3.0, "size": 200, "height": 20 }, { "id": "BasinTerrain", "times": 1.0, "size": 50, "height": 12 }, { "id": "HillTerrain", "times": 4.0, "size": 300, "height": 12 } ], "specialTerrains": [ { "id": "Chasm", "times": 0.5, "size": 20, "height": 30 }, { "id": "Lake", "times": 0.5, "size": 60, "height": 10 }, { "id": "Lake", "times": 1.0, "size": 40, "height": 10 }, { "id": "SurfaceCave", "times": 1.0, "size": 80, "height": 0 }, { "id": "SurfaceCave", "times": 2.0, "size": 60, "height": 0 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 1.0, "base": [ { "id": "dirty_hill", "parallel": 8.0, "level": 375 }, { "id": "large_mushrooms", "parallel": 6.0, "level": 368 }, { "id": "mushroom_grass", "parallel": 4.0, "level": 383 }, { "id": "large_mushrooms2", "parallel": 3.0, "level": 380 }, { "id": "mushroom_grass", "parallel": 2.0, "level": 392 } ], "underground": "mud_wall", "linked": "mud_wall_link" }, "musics": { "daySurface": [ "day1", "day2", "day3", "day4", "day5", "mcday1", "mcday2", "mcday3", "mcday4" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "rain", "composition": { "main": { "id": "mycelium" }, "subs": [ { "id": "cobblestone" }, { "id": "brown_mushroom_block" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [], "density": 0.18 }, "mushroomInfo": { "styles": [ "brown_mushroom_block", "red_mushroom_block" ], "density": 0.6 }, "grass": 1, "distributions": { "airWeight": 50, "surfacePlaceables": [ { "id": "brown_mushroom", "weight": 20 }, { "id": "red_mushroom", "weight": 20 }, { "id": "large_brown_mushroom", "weight": 5 }, { "id": "large_red_mushroom", "weight": 10 } ], "underWeight": 100, "undergroundPlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "brown_mushroom", "weight": 20 }, { "id": "red_mushroom", "weight": 20 }, { "id": "large_brown_mushroom", "weight": 4 }, { "id": "large_red_mushroom", "weight": 3 } ], "hangingWeight": 40, "hangingPlaceables": [] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 8 }, { "itemId": "grenade", "min": 1, "max": 2, "weight": 3 } ], "daySpawn": { "mobSpeed": 500, "maxMobSpawn": 5, "mobs": [], "animalSpeed": 300, "maxAnimalSpawn": 5, "animals": [ { "id": "brown_mushroom_cow", "weight": 10 }, { "id": "red_mushroom_cow", "weight": 10 } ] }, "nightSpawn": { "mobSpeed": 460, "maxMobSpawn": 6, "mobs": [], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "brown_mushroom_cow", "weight": 10 }, { "id": "red_mushroom_cow", "weight": 10 } ] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "brown_mushroom_cow", "weight": 10 }, { "id": "red_mushroom_cow", "weight": 10 } ] }, "buildingInfo": [ ], "environmentBlocks": { "total": 1000, "blocks": [ { "id": "mycelium", "weight": 1 } ] } } } ================================================ FILE: biomes/surfaces/ocean.json ================================================ { "ocean": { "biomeType": "Surface", "dayLight": 1.0, "skyColor": { "midDayTopColor": [ 98, 170, 192 ], "midDayBottomColor": [ 210, 226, 236 ], "midNightTopColor": [ 5, 8, 32 ], "midNightBottomColor": [ 20, 30, 68 ], "transATopColor": [ 98, 170, 192 ], "transABottomColor": [ 217, 198, 10 ], "transBTopColor": [ 44, 33, 10 ], "transBBottomColor": [ 155, 32, 10 ], "transCTopColor": [ 5, 8, 32 ], "transCBottomColor": [ 115, 32, 10 ] }, "terrains": { "terrains": [], "specialTerrains": [], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 1.0, "base": [], "underground": "stone_wall", "linked": "stone_wall_link" }, "musics": { "daySurface": [ "day1", "day2", "day3", "day4", "day5", "mcday1", "mcday2", "mcday3", "mcday4" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "rain", "composition": { "main": { "id": "prismarine_mud" }, "subs": [ { "id": "sand" }, { "id": "cobblestone" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_palm" ], "density": 0.08 }, "plantInfo": { "makeKelp": true, "makeSugarcane": true }, "grass": 0, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "sea_shell", "weight": 40 } ], "underWeight": 100, "undergroundPlaceables": [ { "id": "pot", "tag": 0, "weight": 20 }, { "id": "sea_grass", "weight": 20 }, { "id": "coral", "weight": 20 }, { "id": "sea_shell", "weight": 20 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 10 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "nautilus_shell", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 8 }, { "itemId": "lighting_arrow", "min": 3, "max": 6, "weight": 6 } ], "daySpawn": { "mobSpeed": 400, "maxMobSpawn": 5, "mobs": [ { "id": "green_slime", "weight": 2 }, { "id": "large_green_slime", "weight": 1 }, { "id": "guardian", "weight": 5 }, { "id": "drowned", "weight": 1 }, { "id": "creeper", "weight": 1 } ], "animalSpeed": 200, "maxAnimalSpawn": 5, "animals": [ { "id": "pufferfish", "weight": 5 }, { "id": "dolphin", "weight": 5 }, { "id": "squid", "weight": 5 }, { "id": "turtle", "weight": 5 } ] }, "nightSpawn": { "mobSpeed": 300, "maxMobSpawn": 7, "mobs": [ { "id": "drowned", "weight": 3 }, { "id": "zombie", "weight": 20 }, { "id": "spider", "weight": 8 }, { "id": "arrow_zombie", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 4 }, { "id": "creeper", "weight": 3 }, { "id": "flower_creeper", "weight": 1 }, { "id": "phantom", "weight": 2 } ], "animalSpeed": 200, "maxAnimalSpawn": 5, "animals": [ { "id": "pufferfish", "weight": 5 }, { "id": "dolphin", "weight": 5 }, { "id": "squid", "weight": 5 }, { "id": "turtle", "weight": 5 } ] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ { "buildingId": "monument_ocean", "density": 0.8, "genBeginXi": 400, "genEndXi": 600, "genBeginYi": 470, "genEndYi": 500 } ], "environmentBlocks": { "total": 1000, "blocks": [ { "id": "prismarine_mud", "weight": 4 } ] } } } ================================================ FILE: biomes/surfaces/snow_land.json ================================================ { "snow_land": { "biomeType": "Surface", "dayLight": 1.0, "skyColor": { "midDayTopColor": [ 98, 170, 192 ], "midDayBottomColor": [ 210, 226, 236 ], "midNightTopColor": [ 5, 8, 32 ], "midNightBottomColor": [ 20, 30, 68 ], "transATopColor": [ 98, 170, 192 ], "transABottomColor": [ 217, 198, 10 ], "transBTopColor": [ 44, 33, 10 ], "transBBottomColor": [ 155, 32, 10 ], "transCTopColor": [ 5, 8, 32 ], "transCBottomColor": [ 115, 32, 10 ] }, "subBiomes": { "subs": [ { "biome": "tainted_land", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 400 }, { "biome": "tainted_land", "minSize": 300, "maxSize": 500, "minX": 600, "maxX": 800 }, { "biome": "jungle", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 400 }, { "biome": "jungle", "minSize": 300, "maxSize": 500, "minX": 600, "maxX": 800 } ] }, "terrains": { "terrains": [ { "id": "PlateauTerrain", "times": 1.0, "size": 300, "height": 10 }, { "id": "MountainTerrain", "times": 3.0, "size": 120, "height": 24 }, { "id": "BasinTerrain", "times": 2.0, "size": 66, "height": 8 }, { "id": "HillTerrain", "times": 1.0, "size": 200, "height": 10 }, { "id": "HillTerrain", "times": 3.0, "size": 160, "height": 12 } ], "specialTerrains": [ { "id": "Chasm", "times": 2.0, "size": 20, "height": 30 }, { "id": "IceLake", "times": 5.0, "size": 80, "height": 10 }, { "id": "IceLake", "times": 1.0, "size": 100, "height": 24 }, { "id": "SurfaceCave", "times": 1.0, "size": 50, "height": 0 }, { "id": "SurfaceCave", "times": 3.0, "size": 40, "height": 0 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 0.95, "base": [ { "id": "snow_back", "parallel": 8.0, "level": 361 }, { "id": "snow_hill", "parallel": 7.0, "level": 374 }, { "id": "snow_dune", "parallel": 5.0, "level": 387 }, { "id": "snow_trees3", "parallel": 4.0, "level": 390 }, { "id": "snow_trees2", "parallel": 3.0, "level": 393 }, { "id": "snow_trees", "parallel": 2.0, "level": 399 } ], "underground": "ice_wall", "linked": "ice_wall_link" }, "musics": { "daySurface": [ "mcday4", "mcday5", "mcday6" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "snow", "composition": { "main": { "id": "snow" }, "subs": [ { "id": "ice_cobblestone" }, { "id": "ice" }, { "id": "ice_packed" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_spruce" ], "density": 0.22 }, "grass": 1, "distributions": { "airWeight": 400, "surfacePlaceables": [ { "id": "pot", "tag": 1, "weight": 5 }, { "id": "small_tree_snowy", "weight": 30 }, { "id": "stone_decos_ice", "weight": 15 }, { "id": "stone_pillar_ice", "weight": 15 } ], "underWeight": 60, "undergroundPlaceables": [ { "id": "pot", "tag": 1, "weight": 20 }, { "id": "small_tree_snowy", "weight": 30 }, { "id": "stalactite_ice", "weight": 5 }, { "id": "stalactite_small_ice", "weight": 5 }, { "id": "stone_decos_ice", "weight": 15 }, { "id": "stone_pillar_ice", "weight": 15 } ], "hangingWeight": 20, "hangingPlaceables": [ { "id": "stalactite_hanging_ice", "weight": 5 }, { "id": "stalactite_hanging_small_ice", "weight": 5 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 15 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "lighting_arrow", "min": 2, "max": 3, "weight": 4 }, { "itemId": "ice_arrow", "min": 2, "max": 3, "weight": 5 }, { "itemId": "grenade", "min": 1, "max": 2, "weight": 3 } ], "daySpawn": { "mobSpeed": 550, "maxMobSpawn": 5, "mobs": [ { "id": "ice_elf", "weight": 2 }, { "id": "snow_slime", "weight": 4 }, { "id": "ice_slime", "weight": 4 }, { "id": "large_ice_slime", "weight": 4 }, { "id": "blue_slime", "weight": 3 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 450, "maxAnimalSpawn": 5, "animals": [ { "id": "white_rabbit", "weight": 6 } ] }, "nightSpawn": { "mobSpeed": 460, "maxMobSpawn": 7, "mobs": [ { "id": "ice_elf", "weight": 2 }, { "id": "snow_slime", "weight": 4 }, { "id": "ice_slime", "weight": 4 }, { "id": "large_ice_slime", "weight": 4 }, { "id": "zombie", "weight": 10 }, { "id": "arrow_zombie", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 4 }, { "id": "creeper", "weight": 3 }, { "id": "phantom", "weight": 2 }, { "id": "shulker", "weight": 1 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "white_rabbit", "weight": 3 } ] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [ { "id": "ice_elf", "weight": 5 }, { "id": "large_ice_slime", "weight": 10 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "aurora_palace", "density": 1.5, "fixSurfaceLine": true, "genBeginXi": 500, "genEndXi": 700 } ], "environmentBlocks": { "total": 1000, "blocks": [ { "id": "snow", "weight": 1 }, { "id": "ice_cobblestone", "weight": 1 }, { "id": "ice", "weight": 1 }, { "id": "ice_packed", "weight": 1 }, { "id": "aurora_block", "weight": 4 } ] } } } ================================================ FILE: biomes/surfaces/soft_snow_land.json ================================================ { "soft_snow_land": { "biomeType": "Surface", "dayLight": 1.0, "skyColor": { "midDayTopColor": [ 98, 170, 192 ], "midDayBottomColor": [ 210, 226, 236 ], "midNightTopColor": [ 5, 8, 32 ], "midNightBottomColor": [ 20, 30, 68 ], "transATopColor": [ 98, 170, 192 ], "transABottomColor": [ 217, 198, 10 ], "transBTopColor": [ 44, 33, 10 ], "transBBottomColor": [ 155, 32, 10 ], "transCTopColor": [ 5, 8, 32 ], "transCBottomColor": [ 115, 32, 10 ] }, "subBiomes": { "subs": [] }, "terrains": { "terrains": [ { "id": "PlateauTerrain", "times": 1.0, "size": 300, "height": 10 }, { "id": "MountainTerrain", "times": 3.0, "size": 120, "height": 24 }, { "id": "BasinTerrain", "times": 2.0, "size": 66, "height": 8 }, { "id": "HillTerrain", "times": 1.0, "size": 200, "height": 10 }, { "id": "HillTerrain", "times": 3.0, "size": 160, "height": 12 } ], "specialTerrains": [ { "id": "Chasm", "times": 2.0, "size": 20, "height": 30 }, { "id": "IceLake", "times": 5.0, "size": 80, "height": 10 }, { "id": "IceLake", "times": 1.0, "size": 100, "height": 24 }, { "id": "SurfaceCave", "times": 1.0, "size": 50, "height": 0 }, { "id": "SurfaceCave", "times": 3.0, "size": 40, "height": 0 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 0.95, "base": [ { "id": "snow_hill", "parallel": 7.0, "level": 366 }, { "id": "snow_mountain", "parallel": 6.0, "level": 361 }, { "id": "snow_dune", "parallel": 5.0, "level": 377 }, { "id": "snow_trees_new2", "parallel": 3.0, "level": 373 }, { "id": "snow_trees_new", "parallel": 2.0, "level": 379 } ], "underground": "ice_wall", "linked": "ice_wall_link" }, "musics": { "daySurface": [ "mcday4", "mcday5", "mcday6" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "snow", "composition": { "main": { "id": "snow_soft" }, "subs": [ { "id": "ice_cobblestone" }, { "id": "ice" }, { "id": "ice_packed" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_spruce" ], "density": 0.92 }, "grass": 1, "distributions": { "airWeight": 400, "surfacePlaceables": [ { "id": "pot", "tag": 1, "weight": 5 }, { "id": "small_tree_snowy", "weight": 30 }, { "id": "stone_decos_ice", "weight": 15 }, { "id": "stone_pillar_ice", "weight": 15 } ], "underWeight": 60, "undergroundPlaceables": [ { "id": "pot", "tag": 1, "weight": 20 }, { "id": "small_tree_snowy", "weight": 30 }, { "id": "stalactite_ice", "weight": 5 }, { "id": "stalactite_small_ice", "weight": 5 }, { "id": "stone_decos_ice", "weight": 15 }, { "id": "stone_pillar_ice", "weight": 15 } ], "hangingWeight": 20, "hangingPlaceables": [ { "id": "stalactite_hanging_ice", "weight": 5 }, { "id": "stalactite_hanging_small_ice", "weight": 5 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 15 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "lighting_arrow", "min": 2, "max": 3, "weight": 4 }, { "itemId": "ice_arrow", "min": 2, "max": 3, "weight": 5 }, { "itemId": "grenade", "min": 1, "max": 2, "weight": 3 } ], "daySpawn": { "mobSpeed": 550, "maxMobSpawn": 5, "mobs": [ { "id": "ice_elf", "weight": 2 }, { "id": "snow_slime", "weight": 4 }, { "id": "ice_slime", "weight": 4 }, { "id": "large_ice_slime", "weight": 4 }, { "id": "blue_slime", "weight": 3 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 450, "maxAnimalSpawn": 5, "animals": [ { "id": "white_rabbit", "weight": 6 } ] }, "nightSpawn": { "mobSpeed": 460, "maxMobSpawn": 7, "mobs": [ { "id": "ice_elf", "weight": 2 }, { "id": "snow_slime", "weight": 4 }, { "id": "ice_slime", "weight": 4 }, { "id": "large_ice_slime", "weight": 4 }, { "id": "zombie", "weight": 10 }, { "id": "arrow_zombie", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 4 }, { "id": "creeper", "weight": 3 }, { "id": "phantom", "weight": 2 }, { "id": "shulker", "weight": 1 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "white_rabbit", "weight": 3 } ] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [ { "id": "ice_elf", "weight": 5 }, { "id": "large_ice_slime", "weight": 10 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "aurora_palace", "density": 1.5, "fixSurfaceLine": true, "genBeginXi": 500, "genEndXi": 700 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "snow_soft", "weight": 1 }, { "id": "ice_cobblestone", "weight": 1 }, { "id": "ice", "weight": 1 }, { "id": "ice_packed", "weight": 1 }, { "id": "aurora_block", "weight": 4 } ] } } } ================================================ FILE: biomes/surfaces/super_volcano.json ================================================ { "super_volcano": { "biomeType": "Surface", "dayLight": 0.5, "skyColor": { "midDayTopColor": [ 100, 22, 22 ], "midDayBottomColor": [ 166, 44, 44 ], "midNightTopColor": [ 32, 8, 8 ], "midNightBottomColor": [ 64, 16, 16 ], "transATopColor": [ 60, 22, 22 ], "transABottomColor": [ 60, 33, 33 ], "transBTopColor": [ 50, 16, 16 ], "transBBottomColor": [ 50, 24, 24 ], "transCTopColor": [ 30, 8, 8 ], "transCBottomColor": [ 30, 20, 20 ] }, "subBiomes": { "subs": [] }, "terrains": { "terrains": [ { "id": "MountainTerrain", "times": 2.0, "size": 160, "height": 24 }, { "id": "BasinTerrain", "times": 3.0, "size": 50, "height": 8 }, { "id": "HillTerrain", "times": 3.0, "size": 200, "height": 10 }, { "id": "PlateauTerrain", "times": 3.0, "size": 100, "height": 10 } ], "specialTerrains": [ { "id": "Chasm", "times": 0.5, "size": 20, "height": 30 }, { "id": "SurfaceCave", "times": 1.0, "size": 60, "height": 0 }, { "id": "SurfaceCave", "times": 2.0, "size": 40, "height": 0 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 0.95, "base": [ { "id": "volcano_hill", "parallel": 4.0, "level": 368 }, { "id": "volcano_back", "parallel": 3.0, "level": 378 }, { "id": "volcano_back2", "parallel": 2.5, "level": 388 } ], "underground": "lava_wall", "linked": "lava_wall_link" }, "musics": { "daySurface": [ "day2", "day3", "day4", "day5", "mcday1", "mcday2", "mcday3", "mcday4" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "volcano_snow", "composition": { "main": { "id": "volcano_burn_stone" }, "subs": [ { "id": "volcano_dirt" }, { "id": "magma_block" }, { "id": "magma_block" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "lava", "maxAllowCount": 1000 }, "treeInfo": { "styles": [ "log_volcano_oak" ], "density": 0.75 }, "grass": 0, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "eyeball_grass", "weight": 40 }, { "id": "large_eyeball_grass", "weight": 40 }, { "id": "blood_grass", "weight": 200 } ], "underWeight": 100, "undergroundPlaceables": [], "hangingWeight": 100, "hangingPlaceables": [] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_awkward", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_fire_resistance", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 10 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 8 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 8 }, { "itemId": "grenade", "min": 1, "max": 3, "weight": 6 } ], "daySpawn": { "mobSpeed": 500, "maxMobSpawn": 5, "mobs": [ { "id": "magma_elf", "weight": 5 }, { "id": "zombie_pigman", "weight": 5 }, { "id": "magma_slime", "weight": 5 }, { "id": "magma_birdo", "weight": 4 }, { "id": "meteor", "weight": 4 }, { "id": "creeper", "weight": 1 } ], "animalSpeed": 300, "maxAnimalSpawn": 5, "animals": [] }, "nightSpawn": { "mobSpeed": 450, "maxMobSpawn": 6, "mobs": [ { "id": "magma_elf", "weight": 5 }, { "id": "zombie_pigman", "weight": 5 }, { "id": "magma_slime", "weight": 5 }, { "id": "magma_birdo", "weight": 4 }, { "id": "meteor", "weight": 4 }, { "id": "zombie", "weight": 5 }, { "id": "arrow_zombie", "weight": 4 }, { "id": "bald_zombie", "weight": 4 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 4 }, { "id": "creeper", "weight": 3 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [ { "id": "magma_elf", "weight": 5 }, { "id": "zombie_pigman", "weight": 5 }, { "id": "magma_slime", "weight": 5 }, { "id": "meteor", "weight": 4 }, { "id": "zombie", "weight": 5 }, { "id": "husk", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "spider", "weight": 18 }, { "id": "skeleton", "weight": 3 }, { "id": "flower_creeper", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ ], "environmentBlocks": { "total": 400, "blocks": [ { "id": "volcano_burn_stone", "weight": 10 }, { "id": "volcano_dirt", "weight": 10 }, { "id": "magma_block", "weight": 10 } ] } } } ================================================ FILE: biomes/surfaces/tainted_land.json ================================================ { "tainted_land": { "biomeType": "Surface", "dayLight": 0.75, "skyColor": { "midDayTopColor": [ 60, 70, 180 ], "midDayBottomColor": [ 90, 100, 220 ], "midNightTopColor": [ 5, 8, 32 ], "midNightBottomColor": [ 20, 30, 68 ], "transATopColor": [ 50, 60, 160 ], "transABottomColor": [ 70, 80, 170 ], "transBTopColor": [ 40, 50, 100 ], "transBBottomColor": [ 60, 70, 140 ], "transCTopColor": [ 20, 30, 60 ], "transCBottomColor": [ 40, 50, 100 ] }, "subBiomes": { "subs": [ ] }, "terrains": { "terrains": [ { "id": "MountainTerrain", "times": 5.0, "size": 100, "height": 10 }, { "id": "BasinTerrain", "times": 3.0, "size": 50, "height": 5 }, { "id": "HillTerrain", "times": 4.0, "size": 200, "height": 10 } ], "specialTerrains": [ { "id": "SurfaceCave", "times": 4.0, "size": 80, "height": 0 }, { "id": "SurfaceCave", "times": 8.0, "size": 40, "height": 0 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 0.95, "base": [ { "id": "tainted_hill2", "parallel": 3.0, "level": 358 }, { "id": "tainted_hill", "parallel": 2.6, "level": 362 }, { "id": "tainted_bush", "parallel": 2.0, "level": 384 }, { "id": "tainted_bush_strick", "parallel": 1.75, "level": 384 }, { "id": "tainted_rock", "parallel": 1.25, "level": 402 } ], "underground": "tainted_wall", "linked": "tainted_wall_link" }, "musics": { "daySurface": [ "day2", "day3", "day4", "day5", "mcday1", "mcday2", "mcday3", "mcday4" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "rain", "composition": { "main": { "id": "tainted_dirt" }, "subs": [ { "id": "tainted_stone" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_tainted" ], "density": 0.7 }, "grass": 1, "distributions": { "airWeight": 50, "surfacePlaceables": [ { "id": "tainted_grass", "weight": 50 }, { "id": "pot", "tag": 3, "weight": 10 }, { "id": "small_tree_tainted", "weight": 10 }, { "id": "large_poison_mushroom", "weight": 10 }, { "id": "poison_mushroom", "weight": 10 }, { "id": "stone_decos_tainted", "weight": 10 }, { "id": "stone_pillar_tainted", "weight": 10 } ], "underWeight": 50, "undergroundPlaceables": [ { "id": "pot", "tag": 3, "weight": 10 }, { "id": "large_poison_mushroom", "weight": 10 }, { "id": "poison_mushroom", "weight": 10 }, { "id": "stone_decos_tainted", "weight": 10 }, { "id": "stone_pillar_tainted", "weight": 10 }, { "id": "stalactite_tainted", "weight": 10 }, { "id": "stalactite_small_tainted", "weight": 10 }, { "id": "stab_tainted", "weight": 10 } ], "hangingWeight": 60, "hangingPlaceables": [ { "id": "tainted_vine", "weight": 40 }, { "id": "stalactite_hanging_tainted", "weight": 10 }, { "id": "stalactite_hanging_small_tainted", "weight": 10 }, { "id": "stab_hanging_tainted", "weight": 4 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_harming", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_weakness", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_slow_falling", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 10 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 8 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 6 }, { "itemId": "grenade", "min": 1, "max": 2, "weight": 3 } ], "daySpawn": { "mobSpeed": 200, "maxMobSpawn": 5, "mobs": [ { "id": "tainted_slime", "weight": 10 }, { "id": "large_tainted_slime", "weight": 5 }, { "id": "enderman", "weight": 12 }, { "id": "tainted_creeper", "weight": 5 }, { "id": "flower_creeper", "weight": 2 }, { "id": "tainted_skeleton", "weight": 2 } ], "animalSpeed": 300, "maxAnimalSpawn": 5, "animals": [] }, "nightSpawn": { "mobSpeed": 200, "maxMobSpawn": 10, "mobs": [ { "id": "tainted_skeleton", "weight": 6 }, { "id": "large_tainted_slime", "weight": 5 }, { "id": "zombie", "weight": 10 }, { "id": "tainted_slime", "weight": 20 }, { "id": "enderman", "weight": 8 }, { "id": "evoker", "weight": 3 }, { "id": "purple_slime", "weight": 4 }, { "id": "arrow_zombie", "weight": 8 }, { "id": "skeleton", "weight": 4 }, { "id": "flower_creeper", "weight": 3 }, { "id": "phantom", "weight": 8 } ], "animalSpeed": 400, "maxAnimalSpawn": 5, "animals": [] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [ { "id": "tainted_slime", "weight": 10 }, { "id": "enderman", "weight": 8 }, { "id": "evoker", "weight": 3 }, { "id": "purple_slime", "weight": 4 }, { "id": "phantom", "weight": 5 }, { "id": "tainted_skeleton", "weight": 5 }, { "id": "tainted_creeper", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "end_outpost", "density": 1.0, "fixSurfaceLine": true, "genBeginXi": 100, "genEndXi": 900 } ], "environmentBlocks": { "total": 1000, "blocks": [ { "id": "tainted_dirt", "weight": 1 }, { "id": "tainted_stone", "weight": 1 } ] } } } ================================================ FILE: biomes/surfaces/volcano.json ================================================ { "volcano": { "biomeType": "Surface", "dayLight": 0.5, "skyColor": { "midDayTopColor": [ 100, 22, 22 ], "midDayBottomColor": [ 166, 44, 44 ], "midNightTopColor": [ 32, 8, 8 ], "midNightBottomColor": [ 64, 16, 16 ], "transATopColor": [ 100, 22, 22 ], "transABottomColor": [ 100, 33, 33 ], "transBTopColor": [ 60, 16, 16 ], "transBBottomColor": [ 80, 24, 24 ], "transCTopColor": [ 32, 8, 8 ], "transCBottomColor": [ 72, 20, 20 ] }, "subBiomes": { "subs": [ { "biome": "jungle", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 800 }, { "biome": "tainted_land", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 800 }, { "biome": "flesh", "minSize": 300, "maxSize": 500, "minX": 200, "maxX": 800 } ] }, "terrains": { "terrains": [ { "id": "MountainTerrain", "times": 2.0, "size": 160, "height": 24 }, { "id": "BasinTerrain", "times": 3.0, "size": 50, "height": 8 }, { "id": "HillTerrain", "times": 7.0, "size": 200, "height": 14 }, { "id": "PlateauTerrain", "times": 3.0, "size": 100, "height": 10 } ], "specialTerrains": [ { "id": "Chasm", "times": 0.5, "size": 20, "height": 30 }, { "id": "SurfaceCave", "times": 1.0, "size": 60, "height": 0 }, { "id": "SurfaceCave", "times": 2.0, "size": 40, "height": 0 }, { "id": "SurfaceCave", "times": 5.0, "size": 20, "height": 0 }, { "id": "LavaLake", "times": 4, "size": 60, "height": 10 }, { "id": "LavaLake", "times": 8.0, "size": 40, "height": 10 } ], "transition": "LinerTransition", "transitionTag": 2 }, "parallaxes": { "deepRate": 0.95, "base": [ { "id": "volcano_back", "parallel": 8.0, "level": 366 }, { "id": "volcano_back2", "parallel": 6.0, "level": 380 }, { "id": "volcano_back3", "parallel": 4.0, "level": 394 } ], "underground": "lava_wall", "linked": "lava_wall_link" }, "musics": { "daySurface": [ "day2", "day3", "day4", "day5", "mcday1", "mcday2", "mcday3", "mcday4" ], "nightSurface": [ "night1", "night2", "night3", "night4" ] }, "weather": "volcano_snow", "composition": { "main": { "id": "volcano_dirt" }, "subs": [ { "id": "volcano_stone" }, { "id": "magma_block" }, { "id": "magma_block" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "lava", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_volcano_oak" ], "density": 0.25 }, "grass": 0, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "eyeball_grass", "weight": 40 }, { "id": "large_eyeball_grass", "weight": 40 }, { "id": "blood_grass", "weight": 200 } ], "underWeight": 100, "undergroundPlaceables": [], "hangingWeight": 100, "hangingPlaceables": [] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_awkward", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_fire_resistance", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 10 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 8 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 8 }, { "itemId": "grenade", "min": 1, "max": 3, "weight": 6 } ], "daySpawn": { "mobSpeed": 500, "maxMobSpawn": 5, "mobs": [ { "id": "magma_elf", "weight": 5 }, { "id": "zombie_pigman", "weight": 5 }, { "id": "magma_slime", "weight": 5 }, { "id": "magma_birdo", "weight": 4 }, { "id": "meteor", "weight": 4 }, { "id": "creeper", "weight": 1 } ], "animalSpeed": 300, "maxAnimalSpawn": 5, "animals": [] }, "nightSpawn": { "mobSpeed": 450, "maxMobSpawn": 6, "mobs": [ { "id": "magma_elf", "weight": 5 }, { "id": "zombie_pigman", "weight": 5 }, { "id": "magma_slime", "weight": 5 }, { "id": "magma_birdo", "weight": 4 }, { "id": "meteor", "weight": 4 }, { "id": "zombie", "weight": 5 }, { "id": "arrow_zombie", "weight": 4 }, { "id": "bald_zombie", "weight": 4 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 4 }, { "id": "creeper", "weight": 3 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "underSpawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [ { "id": "magma_elf", "weight": 5 }, { "id": "zombie_pigman", "weight": 5 }, { "id": "magma_slime", "weight": 5 }, { "id": "meteor", "weight": 4 }, { "id": "zombie", "weight": 5 }, { "id": "husk", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "spider", "weight": 18 }, { "id": "skeleton", "weight": 3 }, { "id": "flower_creeper", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ ], "environmentBlocks": { "total": 1000, "blocks": [ ] } } } ================================================ FILE: biomes/undergrounds/andesite_cave.json ================================================ { "andesite_cave": { "biomeType": "Underground", "scale": 0.6, "wallParallaxe": "stone_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "andesite" }, "subs": [ { "id": "cobblestone" } ] }, "wall": { "id": "andesite", "full": true }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stalactite_andesite", "weight": 15 }, { "id": "stalactite_small_andesite", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "rock", "weight": 4 }, { "id": "stone_decos_normal", "weight": 12 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 }, { "id": "stalactite_hanging_andesite", "weight": 30 }, { "id": "stalactite_hanging_small_andesite", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 300, "maxMobSpawn": 6, "mobs": [ { "id": "zombie", "weight": 20 }, { "id": "angry_skeleton", "weight": 12 }, { "id": "black_skeleton", "weight": 12 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "bat", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ { "buildingId": "fossils", "density": 6.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "andesite", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/blue_cave.json ================================================ { "blue_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "pile_cave_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "cobblestone" }, "subs": [ { "id": "dirt" }, { "id": "gravel" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "rock", "weight": 4 }, { "id": "stone_decos_normal", "weight": 12 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 250, "maxMobSpawn": 6, "mobs": [ { "id": "large_black_slime", "weight": 12 }, { "id": "boney_skeleton", "weight": 12 }, { "id": "black_skeleton", "weight": 12 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "bat", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "mineshaft", "density": 1.0 }, { "buildingId": "under_spruce_cabin", "density": 1.0 }, { "buildingId": "under_oak_cabin", "density": 2.0 }, { "buildingId": "under_dark_oak_cabin", "density": 3.0 }, { "buildingId": "under_jungle_cabin", "density": 3.0 }, { "buildingId": "fossils", "density": 8.0 } ] } } ================================================ FILE: biomes/undergrounds/blue_mushroom_cave.json ================================================ { "blue_mushroom_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "mushroom_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "blue_mushroom_dirt" }, "subs": [ { "id": "blue_mushroom_stem" } ] }, "wall": { "id": "blue_mushroom_dirt", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_blue_mushroom" ], "density": 0.99 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "large_blue_mushroom", "weight": 50 }, { "id": "blue_mushroom", "weight": 100 } ], "hangingWeight": 100, "hangingPlaceables": [] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 200, "maxMobSpawn": 6, "mobs": [ { "id": "large_bat", "weight": 10 }, { "id": "large_spider", "weight": 10 }, { "id": "grim_reaper", "weight": 4 }, { "id": "mad_skeleton", "weight": 6 }, { "id": "skeleton_blue_armed", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "undead_miner", "weight": 2 }, { "id": "boney_skeleton", "weight": 1 }, { "id": "bat", "weight": 1 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 300, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 }, { "id": "brown_mushroom_cow", "weight": 10 }, { "id": "red_mushroom_cow", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "fossils", "density": 6.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "blue_mushroom_dirt", "weight": 1 }, { "id": "blue_mushroom_stem", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/deep_ice_cave.json ================================================ { "deep_ice_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "pile_ice_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "ice_cobblestone_hard" }, "subs": [ { "id": "snow_soft" }, { "id": "ice" }, { "id": "ice_packed" } ] }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 1, "weight": 5 }, { "id": "small_tree_snowy", "weight": 30 }, { "id": "stone_decos_ice", "weight": 15 }, { "id": "stone_pillar_ice", "weight": 15 }, { "id": "stalactite_ice", "weight": 5 }, { "id": "stalactite_small_ice", "weight": 5 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_ice", "weight": 30 }, { "id": "stalactite_hanging_small_ice", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 100, "maxMobSpawn": 12, "mobs": [ { "id": "crystal_monster", "weight": 22 }, { "id": "ice_elf", "weight": 10 }, { "id": "zombie", "weight": 8 }, { "id": "large_ice_slime", "weight": 6 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "boney_skeleton", "weight": 1 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "fossils", "density": 2.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "ice_cobblestone_hard", "weight": 1 }, { "id": "snow_soft", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/deep_magma_cave.json ================================================ { "deep_magma_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "long_lava_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "volcano_cobblestone" }, "subs": [ { "id": "soul_sand" }, { "id": "magma_block" }, { "id": "lava_block_pile" } ] }, "wall": { "id": "lava_block_pile", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "lava", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 4, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "rock", "weight": 4 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 240, "maxMobSpawn": 6, "mobs": [ { "id": "magma_elf", "weight": 10 }, { "id": "magma_birdo", "weight": 6 }, { "id": "meteor", "weight": 4 }, { "id": "zombie", "weight": 6 }, { "id": "large_black_slime", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "angry_skeleton", "weight": 2 }, { "id": "boney_skeleton", "weight": 1 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ { "buildingId": "fossils", "density": 6.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "volcano_cobblestone", "weight": 1 }, { "id": "lava_block_pile", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/desert_cave.json ================================================ { "desert_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "sand_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "sandstone" }, "subs": [ { "id": "cobblestone" }, { "id": "sand" }, { "id": "gravel" } ] }, "wall": { "id": "sandstone", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 2, "weight": 40 }, { "id": "stalactite_desert", "weight": 15 }, { "id": "stalactite_small_desert", "weight": 10 }, { "id": "stone_pillar_desert", "weight": 4 }, { "id": "rock", "weight": 4 }, { "id": "small_tree_desert", "weight": 10 }, { "id": "glowing_mushroom", "weight": 1 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_desert", "weight": 30 }, { "id": "stalactite_hanging_small_desert", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_swiftness", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 300, "maxMobSpawn": 6, "mobs": [ { "id": "large_desert_slime", "weight": 10 }, { "id": "mummy", "weight": 24 }, { "id": "husk", "weight": 20 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 2 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "under_desert_cabin", "density": 8.0 }, { "buildingId": "fossils", "density": 10.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "sand", "weight": 1 }, { "id": "sandstone", "weight": 1 }, { "id": "sandstone_smooth", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/diorite_cave.json ================================================ { "diorite_cave": { "biomeType": "Underground", "scale": 0.6, "wallParallaxe": "stone_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "diorite" }, "subs": [ { "id": "gravel" } ] }, "wall": { "id": "diorite", "full": true }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stalactite_diorite", "weight": 15 }, { "id": "stalactite_small_diorite", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "rock", "weight": 4 }, { "id": "stone_decos_normal", "weight": 12 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 }, { "id": "stalactite_hanging_diorite", "weight": 30 }, { "id": "stalactite_hanging_small_diorite", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 300, "maxMobSpawn": 6, "mobs": [ { "id": "zombie", "weight": 20 }, { "id": "angry_skeleton", "weight": 12 }, { "id": "boney_skeleton", "weight": 12 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "bat", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ { "buildingId": "fossils", "density": 6.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "diorite", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/flesh_cave.json ================================================ { "flesh_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "flesh_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "flesh_dirt" }, "subs": [ { "id": "flesh_stone" }, { "id": "flesh_gut" }, { "id": "flesh_gut" } ] }, "wall": { "id": "flesh_dirt", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 4, "weight": 40 }, { "id": "eyeball_grass", "weight": 40 }, { "id": "large_eyeball_grass", "weight": 40 }, { "id": "flesh_tentacle", "weight": 80 }, { "id": "blood_grass", "weight": 200 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "flesh_tentacle_hanging", "weight": 80 }, { "id": "eyeball_vine", "weight": 40 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 240, "maxMobSpawn": 6, "mobs": [ { "id": "blood_eye", "weight": 10 }, { "id": "iron_zombie", "weight": 8 }, { "id": "blood_slime", "weight": 8 }, { "id": "blood_skeleton", "weight": 6 }, { "id": "blood_bat", "weight": 5 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "fossils", "density": 16.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "flesh_dirt", "weight": 1 }, { "id": "flesh_stone", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/granite_cave.json ================================================ { "granite_cave": { "biomeType": "Underground", "scale": 0.6, "wallParallaxe": "stone_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "granite" }, "subs": [ { "id": "cobblestone" } ] }, "wall": { "id": "granite", "full": true }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stalactite_granite", "weight": 15 }, { "id": "stalactite_small_granite", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "rock", "weight": 4 }, { "id": "stone_decos_normal", "weight": 12 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 }, { "id": "stalactite_hanging_granite", "weight": 30 }, { "id": "stalactite_hanging_small_granite", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 300, "maxMobSpawn": 6, "mobs": [ { "id": "zombie", "weight": 20 }, { "id": "boney_skeleton", "weight": 12 }, { "id": "black_skeleton", "weight": 12 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "bat", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ { "buildingId": "mineshaft", "density": 1.0 }, { "buildingId": "fossils", "density": 6.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "granite", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/ice_cave.json ================================================ { "ice_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "ice_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "ice_cobblestone" }, "subs": [ { "id": "snow" }, { "id": "ice" }, { "id": "ice_packed" } ] }, "wall": { "id": "ice_cobblestone", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 1, "weight": 5 }, { "id": "small_tree_snowy", "weight": 30 }, { "id": "stone_decos_ice", "weight": 15 }, { "id": "stone_pillar_ice", "weight": 15 }, { "id": "stalactite_ice", "weight": 5 }, { "id": "stalactite_small_ice", "weight": 5 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_ice", "weight": 30 }, { "id": "stalactite_hanging_small_ice", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 300, "maxMobSpawn": 6, "mobs": [ { "id": "ice_elf", "weight": 10 }, { "id": "zombie", "weight": 8 }, { "id": "large_ice_slime", "weight": 6 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "boney_skeleton", "weight": 1 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "fossils", "density": 2.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "ice_cobblestone", "weight": 1 }, { "id": "snow", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/jungle_cave.json ================================================ { "jungle_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "mud_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "dirt" }, "subs": [ { "id": "coarse_dirt" }, { "id": "cobblestone" }, { "id": "gravel" } ] }, "wall": { "id": "coarse_dirt", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "treeInfo": { "styles": [ "log_acacia" ], "density": 0.2 }, "mushroomInfo": { "styles": [ "brown_mushroom_block", "red_mushroom_block" ], "density": 0.2 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "stone_decos_normal", "weight": 15 }, { "id": "stone_decos_mossy", "weight": 15 }, { "id": "rock", "weight": 4 }, { "id": "grass", "weight": 30 }, { "id": "large_brown_mushroom", "weight": 4 }, { "id": "large_red_mushroom", "weight": 3 }, { "id": "red_mushroom", "weight": 8 }, { "id": "brown_mushroom", "weight": 8 }, { "id": "fern", "weight": 10 }, { "id": "glowing_mushroom", "weight": 10 }, { "id": "watermelon", "weight": 10 }, { "id": "pumpkin", "weight": 10 }, { "id": "small_tree_normal", "weight": 3 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "vine", "weight": 88 }, { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 280, "maxMobSpawn": 6, "mobs": [ { "id": "large_black_slime", "weight": 10 }, { "id": "man_eater", "weight": 10 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "jungle_bat", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 2 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "mineshaft", "density": 1.0 }, { "buildingId": "under_jungle_cabin", "density": 3.0 }, { "buildingId": "under_stone_cabin", "density": 4.0 }, { "buildingId": "fossils", "density": 6.0 } ] } } ================================================ FILE: biomes/undergrounds/lava_cave.json ================================================ { "lava_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "lava_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "cobblestone" }, "subs": [ { "id": "dirt" }, { "id": "magma_block" } ] }, "wall": { "id": "cobblestone", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "rock", "weight": 4 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 240, "maxMobSpawn": 6, "mobs": [ { "id": "magma_elf", "weight": 10 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "angry_skeleton", "weight": 8 }, { "id": "black_skeleton", "weight": 6 }, { "id": "boney_skeleton", "weight": 5 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "under_dark_oak_cabin", "density": 3.0 }, { "buildingId": "under_jungle_cabin", "density": 3.0 }, { "buildingId": "fossils", "density": 10.0 } ] } } ================================================ FILE: biomes/undergrounds/magma_cave.json ================================================ { "magma_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "lava_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "volcano_burn_stone" }, "subs": [ { "id": "volcano_stone" }, { "id": "volcano_dirt" }, { "id": "magma_block" } ] }, "wall": { "id": "volcano_dirt", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "lava", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 4, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "rock", "weight": 4 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 240, "maxMobSpawn": 6, "mobs": [ { "id": "magma_elf", "weight": 10 }, { "id": "magma_birdo", "weight": 6 }, { "id": "meteor", "weight": 4 }, { "id": "zombie", "weight": 6 }, { "id": "large_black_slime", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "angry_skeleton", "weight": 2 }, { "id": "boney_skeleton", "weight": 1 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [] }, "buildingInfo": [ { "buildingId": "fossils", "density": 6.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "volcano_dirt", "weight": 1 }, { "id": "volcano_stone", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/mud_cave.json ================================================ { "mud_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "mud_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "cobblestone" }, "subs": [ { "id": "coarse_dirt" }, { "id": "dirt" }, { "id": "gravel" } ] }, "wall": { "id": "dirt", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "rock", "weight": 4 }, { "id": "grass", "weight": 30 }, { "id": "red_mushroom", "weight": 8 }, { "id": "brown_mushroom", "weight": 8 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "vine", "weight": 34 }, { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 300, "maxMobSpawn": 6, "mobs": [ { "id": "large_black_slime", "weight": 12 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "bat", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "black_skeleton", "weight": 12 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "mineshaft", "density": 1.0 }, { "buildingId": "under_spruce_cabin", "density": 1.0 }, { "buildingId": "under_oak_cabin", "density": 2.0 }, { "buildingId": "under_dark_oak_cabin", "density": 3.0 }, { "buildingId": "under_jungle_cabin", "density": 3.0 }, { "buildingId": "fossils", "density": 6.0 } ] } } ================================================ FILE: biomes/undergrounds/mushroom_cave.json ================================================ { "mushroom_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "stone_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "mycelium" }, "subs": [ { "id": "brown_mushroom_block" }, { "id": "red_mushroom_block" }, { "id": "mushroom_stem" } ] }, "wall": { "id": "mycelium", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "mushroomInfo": { "styles": [ "brown_mushroom_block", "red_mushroom_block" ], "density": 0.5 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "brown_mushroom", "weight": 20 }, { "id": "red_mushroom", "weight": 20 }, { "id": "large_brown_mushroom", "weight": 5 }, { "id": "large_red_mushroom", "weight": 10 }, { "id": "glowing_mushroom", "weight": 4 } ], "hangingWeight": 100, "hangingPlaceables": [] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 400, "maxMobSpawn": 6, "mobs": [], "animalSpeed": 300, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 }, { "id": "brown_mushroom_cow", "weight": 10 }, { "id": "red_mushroom_cow", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "fossils", "density": 6.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "mycelium", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/normal_cave.json ================================================ { "normal_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "pile_cave_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "cobblestone" }, "subs": [ { "id": "dirt" }, { "id": "gravel" } ] }, "wall": { "id": "coarse_dirt", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "rock", "weight": 4 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "vine", "weight": 18 }, { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 10 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 8 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 8 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 8 }, { "itemId": "grenade", "min": 1, "max": 3, "weight": 5 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 4 } ], "spawn": { "mobSpeed": 300, "maxMobSpawn": 6, "mobs": [ { "id": "large_green_slime", "weight": 5 }, { "id": "large_black_slime", "weight": 8 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "bat", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "angry_skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 1 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "mineshaft", "density": 1.0 }, { "buildingId": "under_spruce_cabin", "density": 1.0 }, { "buildingId": "under_oak_cabin", "density": 2.0 }, { "buildingId": "under_dark_oak_cabin", "density": 3.0 }, { "buildingId": "under_jungle_cabin", "density": 3.0 }, { "buildingId": "fossils", "density": 6.0 } ] } } ================================================ FILE: biomes/undergrounds/stone_cave.json ================================================ { "stone_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "stone_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "cobblestone" }, "subs": [ { "id": "dirt" }, { "id": "cobblestone" } ] }, "wall": { "id": "cobblestone", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 40 }, { "id": "stalactite_stone", "weight": 15 }, { "id": "stalactite_small_stone", "weight": 10 }, { "id": "stone_pillar_normal", "weight": 4 }, { "id": "rock", "weight": 4 }, { "id": "stone_decos_normal", "weight": 12 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_stone", "weight": 30 }, { "id": "stalactite_hanging_small_stone", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 250, "maxMobSpawn": 6, "mobs": [ { "id": "large_black_slime", "weight": 12 }, { "id": "boney_skeleton", "weight": 12 }, { "id": "black_skeleton", "weight": 12 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "bat", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "mineshaft", "density": 1.0 }, { "buildingId": "under_spruce_cabin", "density": 1.0 }, { "buildingId": "under_oak_cabin", "density": 2.0 }, { "buildingId": "under_dark_oak_cabin", "density": 3.0 }, { "buildingId": "under_jungle_cabin", "density": 3.0 }, { "buildingId": "fossils", "density": 8.0 } ] } } ================================================ FILE: biomes/undergrounds/tainted_cave.json ================================================ { "tainted_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "tainted_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "tainted_stone" }, "subs": [ { "id": "tainted_dirt" } ] }, "wall": { "id": "tainted_stone", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 3, "weight": 40 }, { "id": "small_tree_tainted", "weight": 10 }, { "id": "large_poison_mushroom", "weight": 10 }, { "id": "poison_mushroom", "weight": 10 }, { "id": "tainted_grass", "weight": 50 }, { "id": "stone_decos_tainted", "weight": 10 }, { "id": "stone_pillar_tainted", "weight": 10 }, { "id": "stalactite_tainted", "weight": 10 }, { "id": "stalactite_small_tainted", "weight": 10 }, { "id": "stab_tainted", "weight": 10 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "tainted_vine", "weight": 40 }, { "id": "stalactite_hanging_tainted", "weight": 10 }, { "id": "stalactite_hanging_small_tainted", "weight": 10 }, { "id": "stab_hanging_tainted", "weight": 4 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 220, "maxMobSpawn": 6, "mobs": [ { "id": "large_tainted_slime", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "enderman", "weight": 15 }, { "id": "evoker", "weight": 6 }, { "id": "phantom", "weight": 5 }, { "id": "tainted_skeleton", "weight": 2 }, { "id": "tainted_creeper", "weight": 2 }, { "id": "enderman", "weight": 2 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "under_tainted_cabin", "density": 3.0 }, { "buildingId": "fossils", "density": 4.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "tainted_dirt", "weight": 1 }, { "id": "tainted_stone", "weight": 1 } ] } } } ================================================ FILE: biomes/undergrounds/waste_cave.json ================================================ { "waste_cave": { "biomeType": "Underground", "scale": 1.0, "wallParallaxe": "red_sand_wall", "musics": { "underground": [ "mcunder1", "mcunder2", "mcunder3", "mcunder4" ] }, "composition": { "main": { "id": "red_sand_stone" }, "subs": [ { "id": "red_sand" }, { "id": "cobblestone" }, { "id": "red_sand" } ] }, "wall": { "id": "red_sand_stone", "full": false }, "oreGroupName": "default", "liquidInfo": { "liquid": "water", "maxAllowCount": 500 }, "distributions": { "airWeight": 100, "surfacePlaceables": [ { "id": "pot", "tag": 0, "weight": 5 }, { "id": "stalactite_waste", "weight": 5 }, { "id": "stalactite_small_waste", "weight": 5 }, { "id": "rock_waste", "weight": 20 } ], "hangingWeight": 100, "hangingPlaceables": [ { "id": "stalactite_hanging_waste", "weight": 30 }, { "id": "stalactite_hanging_small_waste", "weight": 30 } ] }, "pot": [ { "itemId": "torch", "min": 1, "max": 5, "weight": 15 }, { "itemId": "potion_healing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_night_vision", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_strength", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_leaping", "min": 1, "max": 1, "weight": 1 }, { "itemId": "potion_water_breathing", "min": 1, "max": 1, "weight": 1 }, { "itemId": "wooden_arrow", "min": 3, "max": 10, "weight": 12 }, { "itemId": "lighting_arrow", "min": 3, "max": 10, "weight": 5 }, { "itemId": "coal", "min": 1, "max": 2, "weight": 10 }, { "itemId": "flint", "min": 1, "max": 4, "weight": 10 }, { "itemId": "grenade", "min": 1, "max": 1, "weight": 4 }, { "itemId": "bomb", "min": 1, "max": 1, "weight": 2 } ], "spawn": { "mobSpeed": 300, "maxMobSpawn": 6, "mobs": [ { "id": "large_waste_slime", "weight": 10 }, { "id": "waste_block_slime", "weight": 4 }, { "id": "large_waste_block_slime", "weight": 4 }, { "id": "waste_mummy", "weight": 10 }, { "id": "zombie", "weight": 10 }, { "id": "spider", "weight": 8 }, { "id": "bald_zombie", "weight": 8 }, { "id": "villager_zombie", "weight": 6 }, { "id": "waste_ghost", "weight": 5 }, { "id": "skeleton", "weight": 2 }, { "id": "creeper", "weight": 2 }, { "id": "flower_creeper", "weight": 1 }, { "id": "enderman", "weight": 3 } ], "animalSpeed": 600, "maxAnimalSpawn": 5, "animals": [ { "id": "squid", "weight": 10 } ] }, "buildingInfo": [ { "buildingId": "mineshaft", "density": 1.0 }, { "buildingId": "fossils", "density": 6.0 } ], "environmentBlocks": { "total": 100, "blocks": [ { "id": "red_sand", "weight": 1 }, { "id": "red_sand_stone", "weight": 1 } ] } } } ================================================ FILE: block_entity_ai/BrewingEntity.json ================================================ { "BrewingEntity": { "script": { "path": "BrewingEntity.lua" } } } ================================================ FILE: block_entity_ai/BrewingEntity.lua ================================================ ---@class TC.BrewingEntity:ModBlockEntity local BrewingEntity = class("BrewingEntity", ModBlockEntity) function BrewingEntity:Init() self.inventory = Inventory.new(4) self.potionSlot = self.inventory:GetSlot(0) self.sourceSlot = self.inventory:GetSlot(1) self.outputSlot = self.inventory:GetSlot(2) self.fuelSlot = self.inventory:GetSlot(3) self.processedTime = 0 self.totalProcessTime = 0 self.currentRecipeID = 0 self.remainProcessTimes = 0 self.blockEntity.dataWatcher:AddInventory(self.inventory) end function BrewingEntity:OnKilled(parameterDestroy) local cx, cy = MapUtils.GetFrontCenterXY(self.blockEntity.xi, self.blockEntity.yi) ---@param slot Slot local function _TryDropItemAndClearSlot(slot) if slot.hasStack then ItemUtils.CreateDrop(slot:GetStack(), cx, cy, Utils.RandSym(3), Utils.RandDoubleArea(-4, 1)) slot:ClearStack() end end _TryDropItemAndClearSlot(self.sourceSlot) _TryDropItemAndClearSlot(self.potionSlot) _TryDropItemAndClearSlot(self.outputSlot) _TryDropItemAndClearSlot(self.fuelSlot) end function BrewingEntity:Update() if self.currentRecipeID > 0 then self.processedTime = self.processedTime + 1 end local nextLoop = false local lastRecipeID = self.currentRecipeID if self.currentRecipeID > 0 and self.processedTime >= self.totalProcessTime then -- brewing finish local recipe = RecipeUtils.GetRecipe(self.currentRecipeID) local recipeSourceStackSize = recipe.inputs[1].stackSize local recipePotionStackSize = recipe.inputs[2].stackSize local recipeOutputStack = recipe.outputs[1]:GetStack() local outputItem = recipeOutputStack:GetItem() if not self.outputSlot.hasStack then self.outputSlot:PushStack(recipeOutputStack:Clone()) else local outputStack = self.outputSlot:GetStack() assert(outputStack:IsItemStackEqual(recipeOutputStack, true), "Current output item is not same as the recipe item!") outputStack:SetStackSize(outputStack.stackSize + recipeOutputStack.stackSize) end assert(self.sourceSlot.hasStack, "Current source item is not exist!") assert(self.potionSlot.hasStack, "Current potion item is not exist!") self.sourceSlot:DecrStackSize(recipeSourceStackSize) self.potionSlot:DecrStackSize(recipePotionStackSize) self.remainProcessTimes = self.remainProcessTimes - 1 local inputOk = self.sourceSlot.hasStack and self.sourceSlot:GetStack().stackSize >= recipeSourceStackSize inputOk = inputOk and self.potionSlot.hasStack and self.potionSlot:GetStack().stackSize >= recipePotionStackSize if inputOk then if self.outputSlot:GetStack().stackSize + recipeOutputStack.stackSize <= outputItem.maxStackSize then -- output can add for the next loop nextLoop = true end end self.currentRecipeID = 0 self.processedTime = 0 self.totalProcessTime = 0 end if self.remainProcessTimes <= 0 then if self.fuelSlot.hasStack then if self.fuelSlot:GetStack():GetItem().id == Reg.ItemID("tc:blaze_powder") then self.fuelSlot:DecrStackSize(1) self.remainProcessTimes = 20 if nextLoop then self.currentRecipeID = lastRecipeID if self.currentRecipeID > 0 then self.totalProcessTime = RecipeUtils.GetRecipe(self.currentRecipeID).exData.time end end end end elseif nextLoop then self.currentRecipeID = lastRecipeID if self.currentRecipeID > 0 then self.totalProcessTime = RecipeUtils.GetRecipe(self.currentRecipeID).exData.time end end if self.currentRecipeID > 0 then self.blockEntity:SetAnimation(1) else self.blockEntity:SetAnimation(0) end end function BrewingEntity:FlushRecipeData() if self.sourceSlot.hasStack and self.potionSlot.hasStack then local recipeID = RecipeUtils.SearchRecipe(Reg.RecipeConfigID("Brew"), self.inventory, 0, 2) if recipeID == 0 then self.currentRecipeID = 0 self.processedTime = 0 self.totalProcessTime = 0 elseif recipeID > 0 and recipeID ~= self.currentRecipeID then if self.outputSlot.hasStack then local recipeOutputStack = RecipeUtils.GetRecipe(recipeID).outputs[1]:GetStack() local outputStack = self.outputSlot:GetStack() if outputStack:IsItemStackEqual(recipeOutputStack, true) then if outputStack.stackSize + recipeOutputStack.stackSize > recipeOutputStack:GetItem().maxStackSize then recipeID = 0 end else recipeID = 0 end end self.currentRecipeID = recipeID self.processedTime = 0 if recipeID == 0 then self.totalProcessTime = 0 else local recipe = RecipeUtils.GetRecipe(recipeID) self.totalProcessTime = recipe.exData.time end end else self.currentRecipeID = 0 self.processedTime = 0 self.totalProcessTime = 0 end if self.remainProcessTimes <= 0 and self.currentRecipeID > 0 and self.fuelSlot.hasStack and self.fuelSlot:GetStack():GetItem().id == Reg.ItemID("tc:blaze_powder") then self.fuelSlot:DecrStackSize(1) self.remainProcessTimes = 20 end if self.remainProcessTimes <= 0 and self.currentRecipeID > 0 then self.currentRecipeID = 0 self.processedTime = 0 self.totalProcessTime = 0 end end function BrewingEntity:OnClicked(parameterClick) local player = PlayerUtils.Get(parameterClick.playerEntityIndex) if player then local GuiID = require("ui.GuiID") player:OpenGui(Mod.current, GuiID.Brewing, self.blockEntity.xi, self.blockEntity.yi) end end function BrewingEntity:Save() local res = { processedTime = self.processedTime, remainProcessTimes = self.remainProcessTimes, } if self.sourceSlot.hasStack then res.sourceSlot = self.sourceSlot:GetStack():Serialization() end if self.potionSlot.hasStack then res.potionSlot = self.potionSlot:GetStack():Serialization() end if self.outputSlot.hasStack then res.outputSlot = self.outputSlot:GetStack():Serialization() end if self.fuelSlot.hasStack then res.fuelSlot = self.fuelSlot:GetStack():Serialization() end return res end function BrewingEntity:Load(tagTable) self.processedTime = tagTable.processedTime self.remainProcessTimes = tagTable.remainProcessTimes if tagTable.sourceSlot ~= nil then self.sourceSlot:PushStack(ItemStack.Deserialization(tagTable.sourceSlot)) end if tagTable.potionSlot ~= nil then self.potionSlot:PushStack(ItemStack.Deserialization(tagTable.potionSlot)) end if tagTable.outputSlot ~= nil then self.outputSlot:PushStack(ItemStack.Deserialization(tagTable.outputSlot)) end if tagTable.fuelSlot ~= nil then self.fuelSlot:PushStack(ItemStack.Deserialization(tagTable.fuelSlot)) end self.currentRecipeID = RecipeUtils.SearchRecipe(Reg.RecipeConfigID("Brew"), self.inventory, 0, 2) end return BrewingEntity ================================================ FILE: block_entity_ai/Chest30Entity.json ================================================ { "Chest30Entity": { "script": { "path": "Chest30Entity.lua" } } } ================================================ FILE: block_entity_ai/Chest30Entity.lua ================================================ ---@class TC.Chest30Entity:TC.IChestEntity local Chest30Entity = class("Chest30Entity", require("IChestEntity")) function Chest30Entity:Init() Chest30Entity.super.Init(self, 30) end function Chest30Entity:OnClicked(parameterClick) self:InnerOnClicked(parameterClick, require("ui.GuiID").Chest30) end return Chest30Entity ================================================ FILE: block_entity_ai/IChestEntity.lua ================================================ ---@class TC.IChestEntity:ModBlockEntity local IChestEntity = class("IChestEntity", ModBlockEntity) function IChestEntity:Init(slotCount) slotCount = slotCount or 1 ---@type Inventory self.inventory = Inventory.new(slotCount) self.inventorySize = slotCount self.blockEntity.dataWatcher:AddInventory(self.inventory) end function IChestEntity:OnKilled(parameterDestroy) local cx, cy = MapUtils.GetFrontCenterXY(self.blockEntity.xi, self.blockEntity.yi) local cnt = self.inventory.slotCount for i = 1, cnt do local slot = self.inventory:GetSlot(i - 1) if slot.hasStack then ItemUtils.CreateDrop(slot:GetStack(), cx, cy, Utils.RandSym(3), Utils.RandDoubleArea(-4, 1)) slot:ClearStack() end end end function IChestEntity:InnerOnClicked(parameterClick, guiID) local player = PlayerUtils.Get(parameterClick.playerEntityIndex) if player then player:OpenGui(Mod.current, guiID, self.blockEntity.xi, self.blockEntity.yi) end end function IChestEntity:Save() local res = { inventory = self.inventory:Serialization() } return res end function IChestEntity:Load(tagTable) self.inventory:Deserialization(tagTable.inventory) end return IChestEntity ================================================ FILE: block_entity_ai/IShooterEntity.lua ================================================ ---@class TC.IShooterEntity:TC.IChestEntity local IShooterEntity = class("IShooterEntity", require("IChestEntity")) function IShooterEntity:Init(slotCount) IShooterEntity.super.Init(self, slotCount) self.direction = 0 -- 0 left 1 right 2 up 3 down self.wi = 2 self.hi = 2 self.active = false -- TODO ANIMATION!!!!!!!! end function IShooterEntity:OnActivated(isActive) if not isActive then self.active = false elseif not self.active then self.active = true local indices = {} local size = self.inventorySize for i = 0, size - 1 do local slot = self.inventory:GetSlot(i) if slot.hasStack then indices[#indices + 1] = i end end if #indices == 0 then return end local pickIndex = indices[math.random(1, #indices)] local slot = self.inventory:GetSlot(pickIndex) if not slot.hasStack then return end local shootX = self.blockEntity.xi - math.floor(self.wi / 2) * 16 local shootX2 = shootX + self.wi * 16 local shootY2 = self.blockEntity.yi * 16 + 16 local shootY = shootY2 - self.hi * 16 local centerX = (shootX + shootX2) / 2 local centerY = (shootY + shootY2) / 2 local dirX = 0 local dirY = 0 local shootWidth = 16 local shootHeight = 16 local stack = slot:GetStack() local item = stack:GetItem() if item.shootable and item.projectileID > 0 then -- TODO: ProjectileNS::Data &dp = projectileData->GetData(di.projectileId); shootWidth = 32 shootHeight = 32 shootWidth = math.max(shootWidth, shootHeight) shootHeight = shootWidth end if self.direction == 0 then shootX = shootX - shootWidth / 2 shootY = centerY dirX = -1 dirY = 0 elseif self.direction == 1 then shootX = shootX2 + shootWidth / 2 shootY = centerY dirX = 1 dirY = 0 elseif self.direction == 2 then shootX = centerX shootY = shootY - shootHeight / 2 dirX = 0 dirY = -1 elseif self.direction == 3 then shootX = centerX shootY = shootY2 + shootHeight / 2 dirX = 0 dirY = 1 end if item.shootable then local speed = 15 -- TODO: Projectile Shoot! --ProjectileUtils else local speed = 4 ItemUtils.CreateDrop(stack:Clone(1), shootX, shootY, speed * dirX + Utils.RandSym(0.25), speed * dirY + Utils.RandSym(0.25)) slot:DecrStackSize(1) end SoundUtils.PlaySound(Reg.SoundID("bow"), self.blockEntity.xi, self.blockEntity.yi) end end return IShooterEntity ================================================ FILE: block_entity_ai/Shooter9Entity.json ================================================ { "Shooter9Entity": { "script": { "path": "Shooter9Entity.lua" } } } ================================================ FILE: block_entity_ai/Shooter9Entity.lua ================================================ ---@class TC.Shooter9Entity:TC.IShooterEntity local Shooter9Entity = class("Shooter9Entity", require("IShooterEntity")) function Shooter9Entity:Init() Shooter9Entity.super.Init(self, 9) end function Shooter9Entity:OnClicked(parameterClick) self:InnerOnClicked(parameterClick, require("ui.GuiID").Shooter9) end return Shooter9Entity ================================================ FILE: block_entity_ai/SmeltEntity.json ================================================ { "SmeltEntity": { "script": { "path": "SmeltEntity.lua" } } } ================================================ FILE: block_entity_ai/SmeltEntity.lua ================================================ ---@class TC.SmeltEntity:ModBlockEntity local SmeltEntity = class("SmeltEntity", ModBlockEntity) function SmeltEntity:Init() self.inventory = Inventory.new(4) self.inputSlot = self.inventory:GetSlot(0) self.fuelSlot = self.inventory:GetSlot(1) self.outputSlot = self.inventory:GetSlot(2) self.fuelBackSlot = self.inventory:GetSlot(3) self.burnTime = 0 -- current burning remain time self.burnTotalTime = 0 self.cookedTime = 0 self.totalCookTime = 0 self.currentRecipeID = 0 self.blockEntity.dataWatcher:AddInventory(self.inventory) end function SmeltEntity:OnPlaced() end function SmeltEntity:OnKilled(parameterDestroy) local cx, cy = MapUtils.GetFrontCenterXY(self.blockEntity.xi, self.blockEntity.yi) ---@param slot Slot local function _TryDropItemAndClearSlot(slot) if slot.hasStack then ItemUtils.CreateDrop(slot:GetStack(), cx, cy, Utils.RandSym(3), Utils.RandDoubleArea(-4, 1)) slot:ClearStack() end end _TryDropItemAndClearSlot(self.inputSlot) _TryDropItemAndClearSlot(self.outputSlot) _TryDropItemAndClearSlot(self.fuelSlot) _TryDropItemAndClearSlot(self.fuelBackSlot) end function SmeltEntity:Update() if self.currentRecipeID > 0 then self.cookedTime = self.cookedTime + 1 end if self.burnTime > 0 then self.burnTime = self.burnTime - 1 end local lastRecipeID = self.currentRecipeID local nextCookLoop = false if self.currentRecipeID > 0 and self.cookedTime >= self.totalCookTime then -- current cooking is finished local recipe = RecipeUtils.GetRecipe(self.currentRecipeID) -- add the output local recipeInputStackSize = recipe.inputs[1].stackSize local recipeOutputStack = recipe.outputs[1]:GetStack() local outputItem = recipeOutputStack:GetItem() if not self.outputSlot.hasStack then self.outputSlot:PushStack(recipeOutputStack:Clone()) else local outputStack = self.outputSlot:GetStack() assert(outputStack:IsItemStackEqual(recipeOutputStack, true), "Current output item is not same as the recipe item!") outputStack:SetStackSize(outputStack.stackSize + recipeOutputStack.stackSize) end -- remove the input assert(self.inputSlot.hasStack, "Current input item is not exist!") self.inputSlot:DecrStackSize(recipeInputStackSize) -- check the next loop if self.inputSlot.hasStack and self.inputSlot:GetStack().stackSize >= recipeInputStackSize then -- input item is exist and enough for the next loop if self.outputSlot:GetStack().stackSize + recipeOutputStack.stackSize <= outputItem.maxStackSize then -- output can add for the next loop nextCookLoop = true end end self.cookedTime = 0 self.totalCookTime = 0 self.currentRecipeID = 0 end if self.burnTime <= 0 then -- current fuel is burning over self.burnTotalTime = 0 if self.currentRecipeID > 0 or nextCookLoop then local hasFuel = false if self.fuelSlot.hasStack then local fuelItem = self.fuelSlot:GetStack():GetItem() if fuelItem.fuelTime > 0 then local canNextFuelLoop = true local canReturnItem = false if fuelItem.fuelReturnItemID > 0 then if self.fuelBackSlot.hasStack then local fuelStack = self.fuelBackSlot:GetStack() if fuelStack:GetItem().id == fuelItem.fuelReturnItemID then if fuelStack.stackSize < fuelStack:GetItem().maxStackSize then canReturnItem = true end end else canReturnItem = true end canNextFuelLoop = canReturnItem end if canNextFuelLoop then hasFuel = true self.burnTotalTime = fuelItem.fuelTime self.burnTime = self.burnTotalTime self.fuelSlot:DecrStackSize(1) if canReturnItem then if self.fuelBackSlot.hasStack then local fuelStack = self.fuelBackSlot:GetStack() fuelStack:SetStackSize(fuelStack.stackSize + 1) else self.fuelBackSlot:PushStack( ItemStack.new(ItemRegistry.GetItemByID(fuelItem.fuelReturnItemID))) end end if nextCookLoop then self.currentRecipeID = lastRecipeID if self.currentRecipeID > 0 then self.totalCookTime = RecipeUtils.GetRecipe(self.currentRecipeID).exData.time end end end end end if not hasFuel then self.currentRecipeID = 0 self.cookedTime = 0 self.totalCookTime = 0 end end else if nextCookLoop then self.currentRecipeID = lastRecipeID if self.currentRecipeID > 0 then self.totalCookTime = RecipeUtils.GetRecipe(self.currentRecipeID).exData.time end end end if self.burnTime == 0 then -- normal animation self.blockEntity:SetAnimation(0) else -- burning animation self.blockEntity:SetAnimation(1) end end function SmeltEntity:FlushRecipeData() if self.inputSlot.hasStack then local lastRecipeID = self.currentRecipeID local recipeID = RecipeUtils.SearchRecipe(Reg.RecipeConfigID("Smelt"), self.inventory, 0, 1) if recipeID > 0 and recipeID ~= lastRecipeID then -- recipe data changed if self.outputSlot.hasStack then local recipe = RecipeUtils.GetRecipe(recipeID) local recipeOutputStack = recipe.outputs[1]:GetStack() local outputStack = self.outputSlot:GetStack() if not outputStack:IsItemStackEqual(recipeOutputStack, true) then -- recipe is invalid because the recipe output is not same recipeID = 0 else local outputItem = outputStack:GetItem() if outputStack.stackSize + recipeOutputStack.stackSize > outputItem.maxStackSize then -- recipe is invalid because cannot add full recipe output items into output slot recipeID = 0 end end end end if recipeID > 0 then if self.burnTime == 0 then if not self.fuelSlot.hasStack or self.fuelSlot:GetStack():GetItem().fuelTime == 0 then -- fuel is invalid, so recipe is also invalid recipeID = 0 end end end if lastRecipeID ~= recipeID then -- recipe is changed, reset the cooking data self.currentRecipeID = recipeID self.cookedTime = 0 self.totalCookTime = 0 if self.currentRecipeID > 0 then self.totalCookTime = RecipeUtils.GetRecipe(self.currentRecipeID).exData.time end end else -- no input item exist, clear cooking data self.currentRecipeID = 0 self.cookedTime = 0 self.totalCookTime = 0 end end function SmeltEntity:OnClicked(parameterClick) local player = PlayerUtils.Get(parameterClick.playerEntityIndex) if player then local GuiID = require("ui.GuiID") player:OpenGui(Mod.current, GuiID.Smelt, self.blockEntity.xi, self.blockEntity.yi) end end function SmeltEntity:Save() local res = { burnTime = self.burnTime, burnTotalTime = self.burnTotalTime, cookedTime = self.cookedTime, } if self.inputSlot.hasStack then res.inputSlot = self.inputSlot:GetStack():Serialization() end if self.fuelSlot.hasStack then res.fuelSlot = self.fuelSlot:GetStack():Serialization() end if self.outputSlot.hasStack then res.outputSlot = self.outputSlot:GetStack():Serialization() end if self.fuelBackSlot.hasStack then res.fuelBackSlot = self.fuelBackSlot:GetStack():Serialization() end return res end function SmeltEntity:Load(tagTable) if tagTable.burnTime ~= nil then self.burnTime = tagTable.burnTime end if tagTable.burnTotalTime ~= nil then self.burnTotalTime = tagTable.burnTotalTime end if tagTable.cookedTime ~= nil then self.cookedTime = tagTable.cookedTime end if tagTable.inputSlot ~= nil then self.inputSlot:PushStack(ItemStack.Deserialization(tagTable.inputSlot)) end if tagTable.fuelSlot ~= nil then self.fuelSlot:PushStack(ItemStack.Deserialization(tagTable.fuelSlot)) end if tagTable.outputSlot ~= nil then self.outputSlot:PushStack(ItemStack.Deserialization(tagTable.outputSlot)) end if tagTable.fuelBackSlot ~= nil then self.fuelBackSlot:PushStack(ItemStack.Deserialization(tagTable.fuelBackSlot)) end self.currentRecipeID = RecipeUtils.SearchRecipe(Reg.RecipeConfigID("Smelt"), self.inventory, 0, 1) end return SmeltEntity ================================================ FILE: block_presets/Anvil.json ================================================ { "Anvil": { "script": { "path": "Anvil.lua" } } } ================================================ FILE: block_presets/Anvil.lua ================================================ ---@class TC.Anvil:ModBlock local Anvil = class("Anvil", ModBlock) local GuiID = require("ui.GuiID") function Anvil.OnClicked(xi, yi, parameterClick) local player = PlayerUtils.Get(parameterClick.playerEntityIndex) if player then player:OpenGui(Mod.current, GuiID.Repair, xi, yi) end end return Anvil ================================================ FILE: block_presets/Bed.json ================================================ { "Bed": { "pOnClicked": "ClickBed" } } ================================================ FILE: block_presets/Brewing.json ================================================ { "Brewing": { "entityId": "BrewingEntity" } } ================================================ FILE: block_presets/BurnerTower.json ================================================ { "BurnerTower": { "entityId": "Tower", "pOnScreenUpdate": "UpdateBurnerTower", "pOnPlaced": "TowerPlaced", "pOnDestroy": "TowerDestroy", "pOnClicked": "ClickTower" } } ================================================ FILE: block_presets/Button.json ================================================ { "Button": { "pOnClicked": "ClickSwitch", "isTrigger": true } } ================================================ FILE: block_presets/Cake.json ================================================ { "Cake": { "pOnClicked": "ClickCake" } } ================================================ FILE: block_presets/Cobweb.json ================================================ { "Cobweb": { "script": { "path": "Cobweb.lua" }, "pOnDraw": "DrawCobweb" } } ================================================ FILE: block_presets/Cobweb.lua ================================================ ---@class TC.Cobweb:ModBlock local Cobweb = class("Cobweb", ModBlock) function Cobweb.OnPlayerOverlap(xi, yi, player) if player.speedX > 0.25 then player:SetSpeedX(0.25) elseif player.speedX < -0.25 then player:SetSpeedX(0.25) end if player.speedY > 0.25 then player:SetSpeedY(0.25) elseif player.speedY < -0.25 then player:SetSpeedY(0.25) end if Utils.RandTry(32) then MapUtils.RemoveFrontAndDrop(xi, yi) end end return Cobweb ================================================ FILE: block_presets/CraftingTable.json ================================================ { "CraftingTable": { "script": { "path": "CraftingTable.lua" } } } ================================================ FILE: block_presets/CraftingTable.lua ================================================ ---@class TC.CraftingTable:ModBlock local CraftingTable = class("CraftingTable", ModBlock) local GuiID = require("ui.GuiID") function CraftingTable.OnClicked(xi, yi, parameterClick) local player = PlayerUtils.Get(parameterClick.playerEntityIndex) if player then player:OpenGui(Mod.current, GuiID.Craft3x, xi, yi) end end return CraftingTable ================================================ FILE: block_presets/Crop.json ================================================ { "Crop": { "pOnDestroy": "CropDestroy", "pOnRandomEvent": "RandomGrowCrop" } } ================================================ FILE: block_presets/CrystalTower.json ================================================ { "CrystalTower": { "pOnScreenUpdate": "UpdateCrystalTower", "entityId": "Tower", "pOnPlaced": "TowerPlaced", "pOnDestroy": "TowerDestroy", "pOnClicked": "ClickTower" } } ================================================ FILE: block_presets/DaylightTrigger.json ================================================ { "DaylightTrigger": { "isTrigger": true, "pOnRandomEvent": "RandomDayLightTrigger" } } ================================================ FILE: block_presets/DoorClosed.json ================================================ { "DoorClosed": { "pOnDraw": "DrawDoorClosed", "pOnClicked": "ClickOpenDoor", "pOnActivated": "DoorActivated" } } ================================================ FILE: block_presets/DoorOpened.json ================================================ { "DoorOpened": { "pOnDraw": "DrawDoorOpened", "pOnClicked": "ClickCloseDoor", "pOnActivated": "DoorActivated" } } ================================================ FILE: block_presets/Enchantment.json ================================================ { "Enchantment": { "script": { "path": "EnchantmentTable.lua" } } } ================================================ FILE: block_presets/EnchantmentTable.lua ================================================ ---@class TC.EnchantmentTable:ModBlock local EnchantmentTable = class("EnchantmentTable", ModBlock) local GuiID = require("ui.GuiID") local ModTextures = require("mod_textures.ModTextures") function EnchantmentTable.OnClicked(xi, yi, parameterClick) local player = PlayerUtils.Get(parameterClick.playerEntityIndex) if player then player:OpenGui(Mod.current, GuiID.Enchantment, xi, yi) end end function EnchantmentTable.UpdateScreen(xi, yi, tickTime) local checkTime = xi + yi + tickTime if checkTime % 32 == 0 then local effect = EffectUtils.Create(Reg.EffectID("heal"), xi * 16 + Utils.RandInt(16), yi * 16 - 48 + Utils.RandInt(16), Utils.RandSym(1), Utils.RandSym(1) - 0.5, Utils.RandSym(0.5), 1, 0.75) effect.color = Color.new(70, 70, 255) end if checkTime % 16 == 0 then local pickXi = Utils.RandIntArea(xi - 5, 12) local pickYi = Utils.RandIntArea(yi - 6, 7) local picked = false local frontID = MapUtils.GetFrontID(pickXi, pickYi) if frontID > 0 and (frontID == Reg.BlockID("book") or BlockUtils.GetSubGroupID(frontID) == Reg.BlockSubGroupID("BOOKCASE")) then picked = true end if picked then local effectX = pickXi * 16 + 8 local effectY = pickYi * 16 + 8 local cx = xi * 16 + 8 local cy = yi * 16 - 32 local effectAngle = Utils.GetAngle(effectX - cx, effectY - cy) local effectSpeed = 1 local effectSpeedAngle = Utils.FixAngle(effectAngle + math.pi) local spx = math.cos(effectSpeedAngle) * effectSpeed local spy = math.sin(effectSpeedAngle) * effectSpeed local effect = EffectUtils.Create( Reg.EffectID("heal"), effectX, effectY, spx, spy, Utils.RandSym(0.25), Utils.RandDoubleArea(0.5, 0.7), 1, Color.new(70, 70, 255) ) effect:SetDisappearTime(240) end end end function EnchantmentTable.PostRenderFurniture(xi, yi, tickTime) local sourceRect = Rect.new(0, 0, 32, 32) local ex = SpriteExData.new() ex.angle = Utils.CosValue(tickTime, 256, xi) * math.pi ex.origin = Vector2.new(16, 16) local drawX = (xi - 1) * 16 + 4 * Utils.SinValue(tickTime, 128, xi) + 24 - MiscUtils.screenX local drawY = (yi - 1) * 16 + 6 * Utils.CosValue(tickTime, 128, xi) - 24 - MiscUtils.screenY local pos = Vector2.new(drawX, drawY) Sprite.draw(ModTextures.getInstance():getTexture("fly_book"), pos, sourceRect, Color.White, ex, 0) end return EnchantmentTable ================================================ FILE: block_presets/EndRod.json ================================================ { "EndRod": { "pOnDraw": "DrawTorch" } } ================================================ FILE: block_presets/EnderStorage.json ================================================ { "EnderStorage": { "script": { "path": "EnderStorage.lua" } } } ================================================ FILE: block_presets/EnderStorage.lua ================================================ ---@class TC.EnderStorage:ModBlock local EnderStorage = class("EnderStorage", ModBlock) local GuiID = require("ui.GuiID") function EnderStorage.OnClicked(xi, yi, parameterClick) local player = PlayerUtils.Get(parameterClick.playerEntityIndex) if player then player:OpenGui(Mod.current, GuiID.EnderChest30, xi, yi) end end return EnderStorage ================================================ FILE: block_presets/Facing.json ================================================ { "Facing": { "pOnPlaced": "DirectionPlaced", "directionDraw": true } } ================================================ FILE: block_presets/Farmland.json ================================================ { "Farmland": { "pOnRandomEvent": "RandomFarmland" } } ================================================ FILE: block_presets/Furnace.json ================================================ { "Furnace": { "script": { "path": "Furnace.lua" }, "entityId": "SmeltEntity" } } ================================================ FILE: block_presets/Furnace.lua ================================================ ---@class TC.Furnace:ModBlock local Furnace = class("Furnace", ModBlock) function Furnace.OnPlaced(xi, yi) end function Furnace.OnDestroy(xi, yi, parameterDestroy) end function Furnace.OnClicked(xi, yi, parameterClick) end return Furnace ================================================ FILE: block_presets/Grass.json ================================================ { "Grass": { "pOnDestroy": "GrassDestroy" } } ================================================ FILE: block_presets/GrowGrass.json ================================================ { "GrowGrass": { "pOnDrawCoverGroup": "SetDirtGrassCover", "pOnRandomEvent": "RandomGrowGrass" } } ================================================ FILE: block_presets/HeartCrystal.json ================================================ { "HeartCrystal": { "script": { "path": "HeartCrystal.lua" } } } ================================================ FILE: block_presets/HeartCrystal.lua ================================================ ---@class TC.HeartCrystal:ModBlock local HeartCrystal = class("HeartCrystal", ModBlock) local PlayerConstants = require("player.PlayerConstants") function HeartCrystal.OnDestroy(xi, yi, parameterDestroy) for i = 1, 32 do local effectAngle = Utils.RandSym(math.pi) local d = 240 local effectX = xi * 16 + 8 + math.cos(effectAngle) * d local effectY = (yi - 1) * 16 + 8 + math.sin(effectAngle) * d local effectSpeed = 4 - Utils.RandDouble(1.5) local effectSpeedAngle = Utils.FixAngle(effectAngle + math.pi) local spx = math.cos(effectSpeedAngle) * effectSpeed local spy = math.sin(effectSpeedAngle) * effectSpeed local colorChannel = Utils.RandIntArea(200, 50) local effect = EffectUtils.SendFromServer( Reg.EffectID("flash2"), effectX, effectY, spx, spy, Utils.RandSym(0.5), Utils.RandDoubleArea(1.0, 0.55), 1, Color.new(colorChannel, colorChannel * 0.45, colorChannel * 0.45) ) effect:SetDisappearTime(120) end SoundUtils.PlaySound(Reg.SoundID("travel"), xi, yi) local players = PlayerUtils.SearchByCircle(xi * 16 + 8, yi * 16 + 8, 64 * 16) ---@param player Player for _, player in each(players) do player:AddExperience(35) local addValue = 20 player.maxHealth = math.min(player.maxHealth + addValue, PlayerConstants.MaxHealthA) player:Heal(addValue) end end return HeartCrystal ================================================ FILE: block_presets/IceSmelt.json ================================================ { "IceSmelt": { "pOnRandomEvent": "RandomSmeltIce" } } ================================================ FILE: block_presets/InsideStorage.json ================================================ { "InsideStorage": { "insideDrop": true, "entityId": "Storage", "pOnPlaced": "ChestPlaced", "pOnDestroy": "InsideChestDestroy", "pOnDraw": "DrawChest", "pOnClicked": "ClickStorage" } } ================================================ FILE: block_presets/Kelp.json ================================================ { "Kelp": { "pOnRandomEvent": "RandomGrowKelp" } } ================================================ FILE: block_presets/MagmaBlock.json ================================================ { "MagmaBlock": { "script": { "path": "MagmaBlock.lua" } } } ================================================ FILE: block_presets/MagmaBlock.lua ================================================ ---@class TC.MagmaBlock:ModBlock local MagmaBlock = class("MagmaBlock", ModBlock) function MagmaBlock.OnPlayerCollide(xi, yi, player, collisionDirection) player:AddBuff(Reg.BuffID("fire"), 120) end return MagmaBlock ================================================ FILE: block_presets/Melon.json ================================================ { "Melon": { "pOnDestroy": "MelonDestroy" } } ================================================ FILE: block_presets/MelonStem.json ================================================ { "MelonStem": { "pOnRandomEvent": "RandomGrowMelon" } } ================================================ FILE: block_presets/MoonlightTrigger.json ================================================ { "MoonlightTrigger": { "isTrigger": true, "pOnRandomEvent": "RandomMoonLightTrigger" } } ================================================ FILE: block_presets/NetherAltar.json ================================================ { "NetherAltar": { "script": { "path": "NetherAltar.lua" } } } ================================================ FILE: block_presets/NetherAltar.lua ================================================ ---@class TC.NetherAltar:ModBlock local NetherAltar = class("NetherAltar", ModBlock) function NetherAltar.OnDestroy(xi, yi, parameterDestroy) NpcUtils.Create(Reg.NpcID("worm_head"), xi * 16 - 1000, yi * 16) SoundUtils.PlaySound(Reg.SoundID("monster"), xi, yi) end return NetherAltar ================================================ FILE: block_presets/Painting.json ================================================ { "Painting": { "pOnPlaced": "PaintingPlaced" } } ================================================ FILE: block_presets/PortalDoor.json ================================================ { "PortalDoor": { "pOnClicked": "ClickPortalDoor", "pOnScreenUpdate": "UpdatePortalDoor" } } ================================================ FILE: block_presets/Pot.json ================================================ { "Pot": { "pOnDraw": "DrawPot", "pOnDestroy": "PotDestroy" } } ================================================ FILE: block_presets/Pumpkin.json ================================================ { "Pumpkin": { "pOnDestroy": "MelonDestroy" } } ================================================ FILE: block_presets/RandomDisplay.json ================================================ { "RandomDisplay": { "pOnDraw": "DrawGeneral" } } ================================================ FILE: block_presets/RedstoneLamp.json ================================================ { "RedstoneLamp": { "pOnActivated": "LampActivated", "pOnScreenUpdate": "UpdateLamp" } } ================================================ FILE: block_presets/RedstonePlate.json ================================================ { "RedstonePlate": { "script": { "path": "RedstonePlate.lua" }, "isTrigger": true } } ================================================ FILE: block_presets/RedstonePlate.lua ================================================ ---@class TC.RedstonePlate:ModBlock local RedstonePlate = class("RedstonePlate", ModBlock) function RedstonePlate.OnPlayerOverlap(xi, yi, player) if player.stand and math.abs(player.bottomY - (yi + 1) * 16) < 4 then MapUtils.TriggerSignal(xi, yi, true) MapUtils.DelayTriggerSignal(xi, yi, false, 32) end end return RedstonePlate ================================================ FILE: block_presets/RedstoneTorch.json ================================================ { "RedstoneTorch": { "pOnDraw": "DrawTorch", "pOnScreenUpdate": "UpdateRedstoneTorch", "isTrigger": true, "pOnClicked": "ClickSwitch", "noSmartAct": true } } ================================================ FILE: block_presets/Sapling.json ================================================ { "Sapling": { "pOnRandomEvent": "RandomGrowTree" } } ================================================ FILE: block_presets/Shooter.json ================================================ { "Shooter": { "entityId": "Shooter", "pOnActivated": "ShooterActivated", "pOnPlaced": "ShooterPlaced", "pOnDestroy": "ShooterDestroy", "pOnClicked": "ClickShooter" } } ================================================ FILE: block_presets/SnowQueenBall.json ================================================ { "SnowQueenBall": { "script": { "path": "SnowQueenBall.lua" } } } ================================================ FILE: block_presets/SnowQueenBall.lua ================================================ ---@class TC.SnowQueenBall:ModBlock local SnowQueenBall = class("SnowQueenBall", ModBlock) local RecordData = require("record.RecordData") function SnowQueenBall.OnClicked(xi, yi, parameterClick) if RecordData.getInstance().hasSnowQueen then return end local npc = NpcUtils.Create(Reg.NpcID("snow_queen"), xi * 16, yi * 16 - 160, 0, -8) local modNpc = npc:GetModNpc() if modNpc ~= nil then modNpc.hookXi = xi modNpc.hookYi = yi end SoundUtils.PlaySound(Reg.SoundID("monster"), xi, yi) end return SnowQueenBall ================================================ FILE: block_presets/SoulSand.json ================================================ { "SoulSand": { "script": { "path": "SoulSand.lua" } } } ================================================ FILE: block_presets/SoulSand.lua ================================================ ---@class TC.SoulSand:ModBlock local SoulSand = class("SoulSand", ModBlock) function SoulSand.OnPlayerCollide(xi, yi, player, collisionDirection) if player.speedRate > 0.5 then player.speedRate = player.speedRate * 0.75 if player.speedRate < 0.5 then player.speedRate = 0.5 end end end return SoulSand ================================================ FILE: block_presets/Sponge.json ================================================ { "Sponge": { "pOnTouchLiquid": "SpongeTouchLiquid" } } ================================================ FILE: block_presets/Stalactite.json ================================================ { "Stalactite": { "pOnDraw": "DrawGeneral", "pOnScreenUpdate": "UpdateStalactite" } } ================================================ FILE: block_presets/Storage.json ================================================ { "Storage": { "entityId": "Chest30Entity" } } ================================================ FILE: block_presets/Sugarcane.json ================================================ { "Sugarcane": { "pOnDraw": "DrawGeneral", "pOnRandomEvent": "RandomGrowSugarCane" } } ================================================ FILE: block_presets/TNT.json ================================================ { "TNT": { "pOnActivated": "TNTActivated", "pOnDestroy": "TNTDestroy" } } ================================================ FILE: block_presets/Torch.json ================================================ { "Torch": { "pOnDraw": "DrawTorch", "noSmartAct": true } } ================================================ FILE: block_presets/TrapStorage.json ================================================ { "TrapStorage": { "entityId": "Storage", "pOnPlaced": "ChestPlaced", "pOnDestroy": "ChestDestroy", "pOnDraw": "DrawChest", "pOnClicked": "ClickTrappedStorage" } } ================================================ FILE: block_presets/Vine.json ================================================ { "Vine": { "pOnDraw": "DrawGeneral", "pOnRandomEvent": "RandomGrowVine" } } ================================================ FILE: block_presets/WetSponge.json ================================================ { "WetSponge": { "pOnScreenUpdate": "UpdateWetSponge" } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_black.json ================================================ { "block": { "wooden_bed_black": { "textureData": "wooden_bed_black.png", "color": [ 99, 99, 99 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 0, 0, 0 ], "preset": "Bed" } }, "item": { "wooden_bed_black": { "type": "BLOCKS", "iconTextureData": "wooden_bed_black.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_black", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_blue.json ================================================ { "block": { "wooden_bed_blue": { "textureData": "wooden_bed_blue.png", "color": [ 119, 129, 188 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 0, 0, 120 ], "preset": "Bed" } }, "item": { "wooden_bed_blue": { "type": "BLOCKS", "iconTextureData": "wooden_bed_blue.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_blue", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_brown.json ================================================ { "block": { "wooden_bed_brown": { "textureData": "wooden_bed_brown.png", "color": [ 167, 133, 108 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 130, 100, 50 ], "preset": "Bed" } }, "item": { "wooden_bed_brown": { "type": "BLOCKS", "iconTextureData": "wooden_bed_brown.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_brown", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_cyan.json ================================================ { "block": { "wooden_bed_cyan": { "textureData": "wooden_bed_cyan.png", "color": [ 88, 180, 180 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 0, 120, 120 ], "preset": "Bed" } }, "item": { "wooden_bed_cyan": { "type": "BLOCKS", "iconTextureData": "wooden_bed_cyan.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_cyan", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_gray.json ================================================ { "block": { "wooden_bed_gray": { "textureData": "wooden_bed_gray.png", "color": [ 125, 125, 128 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 60, 60 ], "preset": "Bed" } }, "item": { "wooden_bed_gray": { "type": "BLOCKS", "iconTextureData": "wooden_bed_gray.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_gray", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_green.json ================================================ { "block": { "wooden_bed_green": { "textureData": "wooden_bed_green.png", "color": [ 144, 66, 92 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 0, 120, 0 ], "preset": "Bed" } }, "item": { "wooden_bed_green": { "type": "BLOCKS", "iconTextureData": "wooden_bed_green.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_green", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_light_blue.json ================================================ { "block": { "wooden_bed_light_blue": { "textureData": "wooden_bed_light_blue.png", "color": [ 130, 215, 240 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 90, 120 ], "preset": "Bed" } }, "item": { "wooden_bed_light_blue": { "type": "BLOCKS", "iconTextureData": "wooden_bed_light_blue.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_light_blue", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_light_gray.json ================================================ { "block": { "wooden_bed_light_gray": { "textureData": "wooden_bed_light_gray.png", "color": [ 160, 166, 169 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 120, 100 ], "preset": "Bed" } }, "item": { "wooden_bed_light_gray": { "type": "BLOCKS", "iconTextureData": "wooden_bed_light_gray.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_light_gray", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_lime.json ================================================ { "block": { "wooden_bed_lime": { "textureData": "wooden_bed_lime.png", "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 50, 100, 0 ], "preset": "Bed" } }, "item": { "wooden_bed_lime": { "type": "BLOCKS", "iconTextureData": "wooden_bed_lime.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_lime", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_magenta.json ================================================ { "block": { "wooden_bed_magenta": { "textureData": "wooden_bed_magenta.png", "color": [ 202, 109, 193 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 60, 120 ], "preset": "Bed" } }, "item": { "wooden_bed_magenta": { "type": "BLOCKS", "iconTextureData": "wooden_bed_magenta.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_magenta", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_orange.json ================================================ { "block": { "wooden_bed_orange": { "textureData": "wooden_bed_orange.png", "color": [ 248, 116, 93 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 140, 120, 100 ], "preset": "Bed" } }, "item": { "wooden_bed_orange": { "type": "BLOCKS", "iconTextureData": "wooden_bed_orange.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_orange", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_pink.json ================================================ { "block": { "wooden_bed_pink": { "textureData": "wooden_bed_pink.png", "color": [ 212, 155, 188 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 130, 100, 100 ], "preset": "Bed" } }, "item": { "wooden_bed_pink": { "type": "BLOCKS", "iconTextureData": "wooden_bed_pink.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_pink", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_purple.json ================================================ { "block": { "wooden_bed_purple": { "textureData": "wooden_bed_purple.png", "color": [ 90, 114, 204 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 30, 120 ], "preset": "Bed" } }, "item": { "wooden_bed_purple": { "type": "BLOCKS", "iconTextureData": "wooden_bed_purple.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_purple", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_red.json ================================================ { "block": { "wooden_bed_red": { "textureData": "wooden_bed_red.png", "color": [ 186, 100, 97 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 0, 0 ], "preset": "Bed" } }, "item": { "wooden_bed_red": { "type": "BLOCKS", "iconTextureData": "wooden_bed_red.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_red", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_white.json ================================================ { "block": { "wooden_bed_white": { "note": "各色床 89:0-15", "textureData": "wooden_bed_white.png", "color": [ 201, 208, 208 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 170, 150 ], "preset": "Bed" } }, "item": { "wooden_bed_white": { "type": "BLOCKS", "iconTextureData": "wooden_bed_white.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_white", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/beds/wooden_bed_yellow.json ================================================ { "block": { "wooden_bed_yellow": { "textureData": "wooden_bed_yellow.png", "color": [ 252, 218, 96 ], "type": "FURNITURE", "subGroup": "BED", "width": 4, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 120, 0 ], "preset": "Bed" } }, "item": { "wooden_bed_yellow": { "type": "BLOCKS", "iconTextureData": "wooden_bed_yellow.png", "group": "GROUP_WOODEN_BED", "blockId": "wooden_bed_yellow", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/benches/bench_acacia.json ================================================ { "block": { "bench_acacia": { "textureData": "bench_acacia.png", "color": [ 190, 125, 90 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 180, 100, 60 ] } }, "item": { "bench_acacia": { "type": "BLOCKS", "iconTextureData": "bench_acacia.png", "group": "GROUP_BENCH", "blockId": "bench_acacia", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/benches/bench_birch.json ================================================ { "block": { "bench_birch": { "textureData": "bench_birch.png", "color": [ 220, 210, 160 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 200, 130 ] } }, "item": { "bench_birch": { "type": "BLOCKS", "iconTextureData": "bench_birch.png", "group": "GROUP_BENCH", "blockId": "bench_birch", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/benches/bench_dark_oak.json ================================================ { "block": { "bench_dark_oak": { "textureData": "bench_dark_oak.png", "color": [ 106, 86, 66 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 30, 10 ] } }, "item": { "bench_dark_oak": { "type": "BLOCKS", "iconTextureData": "bench_dark_oak.png", "group": "GROUP_BENCH", "blockId": "bench_dark_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/benches/bench_jungle.json ================================================ { "block": { "bench_jungle": { "textureData": "bench_jungle.png", "color": [ 137, 110, 92 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 70, 50 ] } }, "item": { "bench_jungle": { "type": "BLOCKS", "iconTextureData": "bench_jungle.png", "group": "GROUP_BENCH", "blockId": "bench_jungle", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/benches/bench_nether.json ================================================ { "block": { "bench_nether": { "textureData": "bench_nether.png", "color": [ 76, 29, 34 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": false, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 76, 29, 34 ] } }, "item": { "bench_nether": { "type": "BLOCKS", "iconTextureData": "bench_nether.png", "group": "GROUP_BENCH", "blockId": "bench_nether", "antiLava": true } } } ================================================ FILE: blocks/furnitures/benches/bench_oak.json ================================================ { "block": { "bench_oak": { "textureData": "bench_oak.png", "color": [ 167, 136, 79 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 173, 137, 80 ] } }, "item": { "bench_oak": { "type": "BLOCKS", "iconTextureData": "bench_oak.png", "group": "GROUP_BENCH", "blockId": "bench_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/benches/bench_palm.json ================================================ { "block": { "bench_palm": { "textureData": "bench_palm.png", "color": [ 182, 141, 86 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 182, 141, 86 ] } }, "item": { "bench_palm": { "type": "BLOCKS", "iconTextureData": "bench_palm.png", "group": "GROUP_BENCH", "blockId": "bench_palm", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/benches/bench_spruce.json ================================================ { "block": { "bench_spruce": { "textureData": "bench_spruce.png", "color": [ 144, 119, 93 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 90, 60 ] } }, "item": { "bench_spruce": { "type": "BLOCKS", "iconTextureData": "bench_spruce.png", "group": "GROUP_BENCH", "blockId": "bench_spruce", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/benches/bench_tainted.json ================================================ { "block": { "bench_tainted": { "textureData": "bench_tainted.png", "color": [ 89, 85, 107 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 89, 85, 107 ] } }, "item": { "bench_tainted": { "type": "BLOCKS", "iconTextureData": "bench_tainted.png", "group": "GROUP_BENCH", "blockId": "bench_tainted", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/benches/bench_volcano.json ================================================ { "block": { "bench_volcano": { "textureData": "bench_volcano.png", "color": [ 200, 60, 60 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 60, 60 ] } }, "item": { "bench_volcano": { "type": "BLOCKS", "iconTextureData": "bench_volcano.png", "group": "GROUP_BENCH", "blockId": "bench_volcano", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/bookcases/bookcase_acacia.json ================================================ { "block": { "bookcase_acacia": { "textureData": "bookcase_acacia.png", "color": [ 190, 125, 90 ], "type": "FURNITURE", "subGroup": "BOOKCASE", "width": 3, "height": 4, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 180, 100, 60 ], "preset": "Storage" } }, "item": { "bookcase_acacia": { "type": "BLOCKS", "iconTextureData": "bookcase_acacia.png", "group": "GROUP_BOOKCASE", "blockId": "bookcase_acacia", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/bookcases/bookcase_birch.json ================================================ { "block": { "bookcase_birch": { "textureData": "bookcase_birch.png", "color": [ 220, 210, 160 ], "type": "FURNITURE", "subGroup": "BOOKCASE", "width": 3, "height": 4, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 200, 200, 130 ], "preset": "Storage" } }, "item": { "bookcase_birch": { "type": "BLOCKS", "iconTextureData": "bookcase_birch.png", "group": "GROUP_BOOKCASE", "blockId": "bookcase_birch", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/bookcases/bookcase_dark_oak.json ================================================ { "block": { "bookcase_dark_oak": { "textureData": "bookcase_dark_oak.png", "color": [ 106, 86, 66 ], "type": "FURNITURE", "subGroup": "BOOKCASE", "width": 3, "height": 4, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 60, 30, 10 ], "preset": "Storage" } }, "item": { "bookcase_dark_oak": { "type": "BLOCKS", "iconTextureData": "bookcase_dark_oak.png", "group": "GROUP_BOOKCASE", "blockId": "bookcase_dark_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/bookcases/bookcase_jungle.json ================================================ { "block": { "bookcase_jungle": { "textureData": "bookcase_jungle.png", "color": [ 137, 110, 92 ], "type": "FURNITURE", "subGroup": "BOOKCASE", "width": 3, "height": 4, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 100, 70, 50 ], "preset": "Storage" } }, "item": { "bookcase_jungle": { "type": "BLOCKS", "iconTextureData": "bookcase_jungle.png", "group": "GROUP_BOOKCASE", "blockId": "bookcase_jungle", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/bookcases/bookcase_nether.json ================================================ { "block": { "bookcase_nether": { "textureData": "bookcase_nether.png", "color": [ 73, 29, 34 ], "type": "FURNITURE", "subGroup": "BOOKCASE", "width": 3, "height": 4, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": false, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 73, 29, 34 ], "preset": "Storage" } }, "item": { "bookcase_nether": { "type": "BLOCKS", "iconTextureData": "bookcase_nether.png", "group": "GROUP_BOOKCASE", "blockId": "bookcase_nether", "antiLava": true } } } ================================================ FILE: blocks/furnitures/bookcases/bookcase_oak.json ================================================ { "block": { "bookcase_oak": { "textureData": "bookcase_oak.png", "color": [ 167, 136, 79 ], "type": "FURNITURE", "subGroup": "BOOKCASE", "width": 3, "height": 4, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 173, 137, 80 ], "preset": "Storage" } }, "item": { "bookcase_oak": { "type": "BLOCKS", "iconTextureData": "bookcase_oak.png", "group": "GROUP_BOOKCASE", "blockId": "bookcase_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/bookcases/bookcase_palm.json ================================================ { "block": { "bookcase_palm": { "textureData": "bookcase_palm.png", "color": [ 182, 141, 86 ], "type": "FURNITURE", "subGroup": "BOOKCASE", "width": 3, "height": 4, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 182, 141, 86 ], "preset": "Storage" } }, "item": { "bookcase_palm": { "type": "BLOCKS", "iconTextureData": "bookcase_palm.png", "group": "GROUP_BOOKCASE", "blockId": "bookcase_palm", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/bookcases/bookcase_spruce.json ================================================ { "block": { "bookcase_spruce": { "textureData": "bookcase_spruce.png", "color": [ 144, 119, 93 ], "type": "FURNITURE", "subGroup": "BOOKCASE", "width": 3, "height": 4, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 120, 90, 60 ], "preset": "Storage" } }, "item": { "bookcase_spruce": { "type": "BLOCKS", "iconTextureData": "bookcase_spruce.png", "group": "GROUP_BOOKCASE", "blockId": "bookcase_spruce", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/bookcases/bookcase_tainted.json ================================================ { "block": { "bookcase_tainted": { "textureData": "bookcase_tainted.png", "color": [ 89, 85, 107 ], "type": "FURNITURE", "subGroup": "BOOKCASE", "width": 3, "height": 4, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 89, 85, 107 ], "preset": "Storage" } }, "item": { "bookcase_tainted": { "type": "BLOCKS", "iconTextureData": "bookcase_tainted.png", "group": "GROUP_BOOKCASE", "blockId": "bookcase_tainted", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/bookcases/bookcase_volcano.json ================================================ { "block": { "bookcase_volcano": { "textureData": "bookcase_volcano.png", "color": [ 200, 60, 60 ], "type": "FURNITURE", "subGroup": "BOOKCASE", "width": 3, "height": 4, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 200, 60, 60 ], "preset": "Storage" } }, "item": { "bookcase_volcano": { "type": "BLOCKS", "iconTextureData": "bookcase_volcano.png", "group": "GROUP_BOOKCASE", "blockId": "bookcase_volcano", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/bosses/nether_altar.json ================================================ { "block": { "nether_altar": { "textureData": "nether_altar.png", "color": [ 166, 0, 0 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "NONE", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "DIAMOND", "hardness": 1000, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 166, 0, 0 ], "preset": "NetherAltar" } }, "item": { "nether_altar": { "type": "MATERIALS", "iconTextureData": "nether_altar_icon.png", "group": "GROUP_OTHERS_FURNITURE" } } } ================================================ FILE: blocks/furnitures/bosses/snow_glass_ball.json ================================================ { "block": { "snow_glass_ball": { "textureData": "snow_glass_ball.png", "color": [ 200, 200, 255 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "NONE", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "DIAMOND", "hardness": 1000000000, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 200, 255 ], "preset": "SnowQueenBall" } }, "item": { "snow_glass_ball": { "type": "MATERIALS", "iconTextureData": "snow_glass_ball_icon.png", "group": "GROUP_OTHERS_FURNITURE" } } } ================================================ FILE: blocks/furnitures/cabinet/cabinet_acacia.json ================================================ { "block": { "cabinet_acacia": { "textureData": "wooden_cabinet_acacia.png", "color": [ 190, 125, 90 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 180, 100, 60 ], "preset": "Storage" } }, "item": { "cabinet_acacia": { "type": "BLOCKS", "iconTextureData": "wooden_cabinet_acacia.png", "group": "GROUP_WOODEN_CABINET", "blockId": "cabinet_acacia", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/cabinet/cabinet_birch.json ================================================ { "block": { "cabinet_birch": { "textureData": "wooden_cabinet_birch.png", "color": [ 220, 210, 160 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 200, 200, 130 ], "preset": "Storage" } }, "item": { "cabinet_birch": { "type": "BLOCKS", "iconTextureData": "wooden_cabinet_birch.png", "group": "GROUP_WOODEN_CABINET", "blockId": "cabinet_birch", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/cabinet/cabinet_dark_oak.json ================================================ { "block": { "cabinet_dark_oak": { "textureData": "wooden_cabinet_dark_oak.png", "color": [ 106, 86, 66 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 60, 30, 10 ], "preset": "Storage" } }, "item": { "cabinet_dark_oak": { "type": "BLOCKS", "iconTextureData": "wooden_cabinet_dark_oak.png", "group": "GROUP_WOODEN_CABINET", "blockId": "cabinet_dark_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/cabinet/cabinet_jungle.json ================================================ { "block": { "cabinet_jungle": { "textureData": "wooden_cabinet_jungle.png", "color": [ 137, 110, 92 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 100, 70, 50 ], "preset": "Storage" } }, "item": { "cabinet_jungle": { "type": "BLOCKS", "iconTextureData": "wooden_cabinet_jungle.png", "group": "GROUP_WOODEN_CABINET", "blockId": "cabinet_jungle", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/cabinet/cabinet_nether.json ================================================ { "block": { "cabinet_nether": { "textureData": "cabinet_nether.png", "color": [ 73, 29, 34 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": false, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 73, 29, 34 ], "preset": "Storage" } }, "item": { "cabinet_nether": { "type": "BLOCKS", "iconTextureData": "cabinet_nether.png", "group": "GROUP_WOODEN_CABINET", "blockId": "cabinet_nether", "antiLava": true } } } ================================================ FILE: blocks/furnitures/cabinet/cabinet_oak.json ================================================ { "block": { "cabinet_oak": { "textureData": "wooden_cabinet_oak.png", "color": [ 167, 136, 79 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 173, 137, 80 ], "preset": "Storage" } }, "item": { "cabinet_oak": { "type": "BLOCKS", "iconTextureData": "wooden_cabinet_oak.png", "group": "GROUP_WOODEN_CABINET", "blockId": "cabinet_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/cabinet/cabinet_palm.json ================================================ { "block": { "cabinet_palm": { "textureData": "wooden_cabinet_palm.png", "color": [ 182, 141, 86 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 182, 141, 86 ], "preset": "Storage" } }, "item": { "cabinet_palm": { "type": "BLOCKS", "iconTextureData": "wooden_cabinet_palm.png", "group": "GROUP_WOODEN_CABINET", "blockId": "cabinet_palm", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/cabinet/cabinet_spruce.json ================================================ { "block": { "cabinet_spruce": { "textureData": "wooden_cabinet_spruce.png", "color": [ 144, 119, 93 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 120, 90, 60 ], "preset": "Storage" } }, "item": { "cabinet_spruce": { "type": "BLOCKS", "iconTextureData": "wooden_cabinet_spruce.png", "group": "GROUP_WOODEN_CABINET", "blockId": "cabinet_spruce", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/cabinet/cabinet_tainted.json ================================================ { "block": { "cabinet_tainted": { "textureData": "wooden_cabinet_tainted.png", "color": [ 89, 85, 107 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 89, 85, 107 ], "preset": "Storage" } }, "item": { "cabinet_tainted": { "type": "BLOCKS", "iconTextureData": "wooden_cabinet_tainted.png", "group": "GROUP_WOODEN_CABINET", "blockId": "cabinet_tainted", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/cabinet/cabinet_volcano.json ================================================ { "block": { "cabinet_volcano": { "textureData": "wooden_cabinet_volcano.png", "color": [ 200, 60, 60 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "particleColor": [ 255, 200, 60, 60 ], "preset": "Storage" } }, "item": { "cabinet_volcano": { "type": "BLOCKS", "iconTextureData": "wooden_cabinet_volcano.png", "group": "GROUP_WOODEN_CABINET", "blockId": "cabinet_volcano", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chairs/chair_acacia.json ================================================ { "block": { "chair_acacia": { "textureData": "wooden_chair_acacia.png", "color": [ 190, 125, 90 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 180, 100, 60 ], "preset": "Facing" } }, "item": { "chair_acacia": { "type": "BLOCKS", "iconTextureData": "wooden_chair_acacia_icon.png", "group": "GROUP_WOODEN_CHAIR", "blockId": "chair_acacia", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chairs/chair_birch.json ================================================ { "block": { "chair_birch": { "textureData": "wooden_chair_birch.png", "color": [ 220, 210, 160 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 200, 130 ], "preset": "Facing" } }, "item": { "chair_birch": { "type": "BLOCKS", "iconTextureData": "wooden_chair_birch_icon.png", "group": "GROUP_WOODEN_CHAIR", "blockId": "chair_birch", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chairs/chair_dark_oak.json ================================================ { "block": { "chair_dark_oak": { "textureData": "wooden_chair_dark_oak.png", "color": [ 106, 86, 66 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 30, 10 ], "preset": "Facing" } }, "item": { "chair_dark_oak": { "type": "BLOCKS", "iconTextureData": "wooden_chair_dark_oak_icon.png", "group": "GROUP_WOODEN_CHAIR", "blockId": "chair_dark_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chairs/chair_jungle.json ================================================ { "block": { "chair_jungle": { "textureData": "wooden_chair_jungle.png", "color": [ 137, 110, 92 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 70, 50 ], "preset": "Facing" } }, "item": { "chair_jungle": { "type": "BLOCKS", "iconTextureData": "wooden_chair_jungle_icon.png", "group": "GROUP_WOODEN_CHAIR", "blockId": "chair_jungle", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chairs/chair_nether.json ================================================ { "block": { "chair_nether": { "textureData": "chair_nether.png", "color": [ 73, 29, 34 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": false, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 73, 29, 34 ], "preset": "Facing" } }, "item": { "chair_nether": { "type": "BLOCKS", "iconTextureData": "chair_nether_icon.png", "group": "GROUP_WOODEN_CHAIR", "blockId": "chair_nether", "antiLava": true } } } ================================================ FILE: blocks/furnitures/chairs/chair_oak.json ================================================ { "block": { "chair_oak": { "textureData": "wooden_chair_oak.png", "color": [ 167, 136, 79 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 173, 137, 80 ], "preset": "Facing" } }, "item": { "chair_oak": { "type": "BLOCKS", "iconTextureData": "wooden_chair_oak_icon.png", "group": "GROUP_WOODEN_CHAIR", "blockId": "chair_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chairs/chair_palm.json ================================================ { "block": { "chair_palm": { "textureData": "wooden_chair_palm.png", "color": [ 182, 141, 86 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 182, 141, 86 ], "preset": "Facing" } }, "item": { "chair_palm": { "type": "BLOCKS", "iconTextureData": "wooden_chair_palm_icon.png", "group": "GROUP_WOODEN_CHAIR", "blockId": "chair_palm", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chairs/chair_spruce.json ================================================ { "block": { "chair_spruce": { "textureData": "wooden_chair_spruce.png", "color": [ 144, 119, 93 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 90, 60 ], "preset": "Facing" } }, "item": { "chair_spruce": { "type": "BLOCKS", "iconTextureData": "wooden_chair_spruce_icon.png", "group": "GROUP_WOODEN_CHAIR", "blockId": "chair_spruce", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chairs/chair_tainted.json ================================================ { "block": { "chair_tainted": { "textureData": "wooden_chair_tainted.png", "color": [ 89, 85, 107 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 89, 85, 107 ], "preset": "Facing" } }, "item": { "chair_tainted": { "type": "BLOCKS", "iconTextureData": "wooden_chair_tainted_icon.png", "group": "GROUP_WOODEN_CHAIR", "blockId": "chair_tainted", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chairs/chair_volcano.json ================================================ { "block": { "chair_volcano": { "textureData": "wooden_chair_volcano.png", "color": [ 200, 60, 60 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 60, 60 ], "preset": "Facing" } }, "item": { "chair_volcano": { "type": "BLOCKS", "iconTextureData": "wooden_chair_volcano_icon.png", "group": "GROUP_WOODEN_CHAIR", "blockId": "chair_volcano", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chests/barrel.json ================================================ { "block": { "barrel": { "textureData": "barrel.png", "color": [ 171, 121, 45 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "soundGroupId": "wood", "functionSoundId": "barrel_open", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 160, 110, 40 ], "preset": "Storage" } }, "item": { "barrel": { "type": "BLOCKS", "iconTextureData": "barrel_icon.png", "group": "GROUP_WOODEN_FURNITURE", "blockId": "barrel", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chests/chest.json ================================================ { "block": { "chest": { "textureData": "chest.png", "color": [ 171, 121, 45 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "soundGroupId": "wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 160, 110, 40 ], "preset": "Storage", "animation": [ { "animationId": 0, "frameStart": 0 }, { "animationId": 1, "frameStart": 3 } ] } }, "item": { "chest": { "type": "BLOCKS", "iconTextureData": "chest_icon.png", "group": "GROUP_WOODEN_FURNITURE", "blockId": "chest", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/chests/ender_chest.json ================================================ { "block": { "ender_chest": { "textureData": "ender_chest.png", "color": [ 36, 55, 52 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "IRON", "hardness": 500, "slipperiness": 1.0, "soundGroupId": "stone", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 33, 33, 33 ], "preset": "EnderStorage", "animation": [ { "animationId": 0, "frameStart": 0 }, { "animationId": 1, "frameStart": 3 } ] } }, "item": { "ender_chest": { "type": "BLOCKS", "iconTextureData": "ender_chest_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "ender_chest" } } } ================================================ FILE: blocks/furnitures/chests/nether_chest.json ================================================ { "block": { "nether_chest": { "textureData": "nether_chest.png", "color": [ 73, 29, 34 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "stone", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 73, 29, 34 ], "preset": "Storage", "animation": [ { "animationId": 0, "frameStart": 0 }, { "animationId": 1, "frameStart": 3 } ] } }, "item": { "nether_chest": { "type": "BLOCKS", "iconTextureData": "nether_chest_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "nether_chest" } } } ================================================ FILE: blocks/furnitures/chests/shulker_box.json ================================================ { "block": { "shulker_box": { "textureData": "shulker_box.png", "color": [ 111, 111, 111 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "stone", "functionSoundId": "shulker_box_open", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ], "preset": "InsideStorage", "animation": [ { "animationId": 0, "frameStart": 0 }, { "animationId": 1, "frameStart": 3 } ] } }, "item": { "shulker_box": { "type": "CHESTS", "iconTextureData": "shulker_box_icon.png", "group": "GROUP_SHULKER_BOX", "blockId": "shulker_box" } } } ================================================ FILE: blocks/furnitures/chests/stone_chest.json ================================================ { "block": { "stone_chest": { "textureData": "stone_chest.png", "color": [ 111, 111, 111 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 130, "slipperiness": 1.0, "soundGroupId": "stone", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ], "preset": "Storage", "animation": [ { "animationId": 0, "frameStart": 0 }, { "animationId": 1, "frameStart": 3 } ] } }, "item": { "stone_chest": { "type": "BLOCKS", "iconTextureData": "stone_chest_icon.png", "group": "GROUP_STONE_FURNITURE", "blockId": "stone_chest" } } } ================================================ FILE: blocks/furnitures/chests/trapped_chest.json ================================================ { "block": { "trapped_chest": { "textureData": "trapped_chest.png", "color": [ 171, 121, 45 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "soundGroupId": "wood", "functionSoundId": "chest", "functionSoundId2": "chestclosed", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 160, 110, 40 ], "preset": "TrapStorage" } }, "item": { "trapped_chest": { "type": "BLOCKS", "iconTextureData": "trapped_chest_icon.png", "group": "GROUP_WOODEN_FURNITURE", "blockId": "trapped_chest", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/doors/door_nether.json ================================================ { "block": { "door_nether": { "note": "地狱门 ", "textureData": "door_nether.png", "color": [ 73, 29, 34 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 73, 29, 34 ], "transformId": "door_nether_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "door_nether": { "type": "BLOCKS", "iconTextureData": "door_nether_icon.png", "group": "GROUP_DOOR", "blockId": "door_nether", "antiLava": true } } } ================================================ FILE: blocks/furnitures/doors/door_nether_open.json ================================================ { "block": { "door_nether_open": { "note": "地狱门 ", "textureData": "door_nether.png", "color": [ 73, 29, 34 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 73, 29, 34 ], "transformId": "door_nether", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/doors/iron_door.json ================================================ { "block": { "iron_door": { "note": "铁门 ", "textureData": "iron_door.png", "color": [ 166, 166, 166 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 180, 180, 180 ], "transformId": "iron_door_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "iron_door": { "type": "BLOCKS", "iconTextureData": "iron_door_icon.png", "group": "GROUP_DOOR", "blockId": "iron_door" } } } ================================================ FILE: blocks/furnitures/doors/iron_door_open.json ================================================ { "block": { "iron_door_open": { "note": "铁门 ", "textureData": "iron_door.png", "color": [ 166, 166, 166 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 180, 180, 180 ], "transformId": "iron_door", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_acacia.json ================================================ { "block": { "wooden_door_acacia": { "textureData": "wooden_door_acacia.png", "color": [ 144, 74, 47 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 130, 70, 40 ], "transformId": "wooden_door_acacia_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "wooden_door_acacia": { "type": "BLOCKS", "iconTextureData": "wooden_door_acacia_icon.png", "group": "GROUP_DOOR", "blockId": "wooden_door_acacia", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_acacia_open.json ================================================ { "block": { "wooden_door_acacia_open": { "textureData": "wooden_door_acacia.png", "color": [ 144, 74, 47 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 130, 70, 40 ], "transformId": "wooden_door_acacia", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_birch.json ================================================ { "block": { "wooden_door_birch": { "textureData": "wooden_door_birch.png", "color": [ 170, 160, 120 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 165, 155, 110 ], "transformId": "wooden_door_birch_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "wooden_door_birch": { "type": "BLOCKS", "iconTextureData": "wooden_door_birch_icon.png", "group": "GROUP_DOOR", "blockId": "wooden_door_birch", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_birch_open.json ================================================ { "block": { "wooden_door_birch_open": { "textureData": "wooden_door_birch.png", "color": [ 170, 160, 120 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 165, 155, 110 ], "transformId": "wooden_door_birch", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_dark_oak.json ================================================ { "block": { "wooden_door_dark_oak": { "textureData": "wooden_door_dark_oak.png", "color": [ 44, 26, 16 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 46, 28, 18 ], "transformId": "wooden_door_dark_oak_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "wooden_door_dark_oak": { "type": "BLOCKS", "iconTextureData": "wooden_door_dark_oak_icon.png", "group": "GROUP_DOOR", "blockId": "wooden_door_dark_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_dark_oak_open.json ================================================ { "block": { "wooden_door_dark_oak_open": { "textureData": "wooden_door_dark_oak.png", "color": [ 44, 26, 16 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 46, 28, 18 ], "transformId": "wooden_door_dark_oak", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_jungle.json ================================================ { "block": { "wooden_door_jungle": { "textureData": "wooden_door_jungle.png", "color": [ 150, 108, 77 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 150, 100, 80 ], "transformId": "wooden_door_jungle_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "wooden_door_jungle": { "type": "BLOCKS", "iconTextureData": "wooden_door_jungle_icon.png", "group": "GROUP_DOOR", "blockId": "wooden_door_jungle", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_jungle_open.json ================================================ { "block": { "wooden_door_jungle_open": { "textureData": "wooden_door_jungle.png", "color": [ 150, 108, 77 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 150, 100, 80 ], "transformId": "wooden_door_jungle", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_oak.json ================================================ { "block": { "wooden_door_oak": { "textureData": "wooden_door_oak.png", "color": [ 159, 132, 77 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 144, 122, 80 ], "transformId": "wooden_door_oak_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "wooden_door_oak": { "type": "BLOCKS", "iconTextureData": "wooden_door_oak_icon.png", "group": "GROUP_DOOR", "blockId": "wooden_door_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_oak_open.json ================================================ { "block": { "wooden_door_oak_open": { "textureData": "wooden_door_oak.png", "color": [ 159, 132, 77 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 144, 122, 80 ], "transformId": "wooden_door_oak", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_palm.json ================================================ { "block": { "wooden_door_palm": { "textureData": "wooden_door_palm.png", "color": [ 182, 141, 86 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 182, 141, 86 ], "transformId": "wooden_door_palm_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "wooden_door_palm": { "type": "BLOCKS", "iconTextureData": "wooden_door_palm_icon.png", "group": "GROUP_DOOR", "blockId": "wooden_door_palm", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_palm_open.json ================================================ { "block": { "wooden_door_palm_open": { "textureData": "wooden_door_palm.png", "color": [ 182, 141, 86 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 182, 141, 86 ], "transformId": "wooden_door_palm", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_spruce.json ================================================ { "block": { "wooden_door_spruce": { "textureData": "wooden_door_spruce.png", "color": [ 77, 55, 30 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 70, 40 ], "transformId": "wooden_door_spruce_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "wooden_door_spruce": { "type": "BLOCKS", "iconTextureData": "wooden_door_spruce_icon.png", "group": "GROUP_DOOR", "blockId": "wooden_door_spruce", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_spruce_open.json ================================================ { "block": { "wooden_door_spruce_open": { "textureData": "wooden_door_spruce.png", "color": [ 77, 55, 30 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 70, 40 ], "transformId": "wooden_door_spruce", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_tainted.json ================================================ { "block": { "wooden_door_tainted": { "textureData": "wooden_door_tainted.png", "color": [ 89, 85, 107 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 89, 85, 107 ], "transformId": "wooden_door_tainted_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "wooden_door_tainted": { "type": "BLOCKS", "iconTextureData": "wooden_door_tainted_icon.png", "group": "GROUP_DOOR", "blockId": "wooden_door_tainted", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_tainted_open.json ================================================ { "block": { "wooden_door_tainted_open": { "textureData": "wooden_door_tainted.png", "color": [ 89, 85, 107 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 89, 85, 107 ], "transformId": "wooden_door_tainted", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_volcano.json ================================================ { "block": { "wooden_door_volcano": { "textureData": "wooden_door_volcano.png", "color": [ 200, 60, 60 ], "type": "FURNITURE", "subGroup": "CLOSED_DOOR", "width": 1, "height": 4, "collision": "SOLID", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 60, 60 ], "transformId": "wooden_door_volcano_open", "preset": "DoorClosed", "isDoorClosed": true } }, "item": { "wooden_door_volcano": { "type": "BLOCKS", "iconTextureData": "wooden_door_volcano_icon.png", "group": "GROUP_DOOR", "blockId": "wooden_door_volcano", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/doors/wooden_door_volcano_open.json ================================================ { "block": { "wooden_door_volcano_open": { "textureData": "wooden_door_volcano.png", "color": [ 200, 60, 60 ], "type": "FURNITURE", "subGroup": "OPENED_DOOR", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 60, 60 ], "transformId": "wooden_door_volcano", "preset": "DoorOpened", "isDoorOpened": true } } } ================================================ FILE: blocks/furnitures/farms/carrot.json ================================================ { "block": { "carrot": { "textureData": "carrot.png", "color": [ 222, 177, 66 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isRipen": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 170, 140, 80 ], "preset": "Crop", "maxTag": 3, "cropDrops": [ { "itemId": "carrot", "minCount": 2, "maxCount": 4 } ], "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X", "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } } } ================================================ FILE: blocks/furnitures/farms/melon_stem.json ================================================ { "block": { "melon_stem": { "textureData": "melon_stem.png", "color": [ 102, 88, 19 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 155, 125, 28 ], "transformId": "watermelon", "preset": "MelonStem", "maxTag": 3, "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X", "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } } } ================================================ FILE: blocks/furnitures/farms/nether_wart.json ================================================ { "block": { "nether_wart": { "textureData": "nether_wart.png", "color": [ 92, 21, 26 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isLossyCollection": true, "isRipen": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 166, 37, 48 ], "preset": "Crop", "maxTag": 3, "cropDrops": [ { "itemId": "nether_wart", "minCount": 2, "maxCount": 4 } ], "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X", "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } } } ================================================ FILE: blocks/furnitures/farms/potato.json ================================================ { "block": { "potato": { "textureData": "potato.png", "color": [ 13, 132, 13 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isRipen": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 13, 133, 13 ], "preset": "Crop", "maxTag": 3, "cropDrops": [ { "itemId": "potato", "minCount": 2, "maxCount": 4 } ], "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X", "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } } } ================================================ FILE: blocks/furnitures/farms/pumpkin.json ================================================ { "block": { "pumpkin": { "textureData": "pumpkin.png", "color": [ 205, 123, 12 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 123, 13 ], "isCarveable": true, "transformId": "pumpkin_stem", "transformId2": "pumpkin_carved", "preset": "Pumpkin" } }, "item": { "pumpkin": { "type": "BLOCKS", "iconTextureData": "pumpkin_icon.png", "group": "GROUP_SAPLING", "blockId": "pumpkin" } } } ================================================ FILE: blocks/furnitures/farms/pumpkin_carved.json ================================================ { "block": { "pumpkin_carved": { "textureData": "pumpkin_carved.png", "color": [ 205, 123, 12 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 123, 13 ] } }, "item": { "pumpkin_carved": { "type": "BLOCKS", "iconTextureData": "pumpkin_carved_icon.png", "group": "GROUP_SAPLING", "blockId": "pumpkin_carved" } } } ================================================ FILE: blocks/furnitures/farms/pumpkin_stem.json ================================================ { "block": { "pumpkin_stem": { "textureData": "pumpkin_stem.png", "color": [ 153, 125, 28 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 13, 133, 13 ], "transformId": "pumpkin", "preset": "MelonStem", "maxTag": 3, "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X", "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } } } ================================================ FILE: blocks/furnitures/farms/sugar_cane.json ================================================ { "block": { "sugar_cane": { "textureData": "sugar_cane.png", "color": [ 133, 189, 59 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "TOP", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 133, 188, 60 ], "preset": "Sugarcane" } } } ================================================ FILE: blocks/furnitures/farms/watermelon.json ================================================ { "block": { "watermelon": { "textureData": "watermelon.png", "color": [ 108, 121, 33 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "isChipCollection": true, "lossyItemId": "melon_slice", "chipCount": 6, "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 144, 144, 38 ], "transformId": "melon_stem", "preset": "Melon" } }, "item": { "watermelon": { "type": "BLOCKS", "iconTextureData": "watermelon_icon.png", "group": "GROUP_MELON", "blockId": "watermelon" } } } ================================================ FILE: blocks/furnitures/farms/wheat.json ================================================ { "block": { "wheat": { "textureData": "wheat.png", "color": [ 106, 118, 11 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isLossyCollection": true, "isRipen": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 106, 118, 17 ], "preset": "Crop", "maxTag": 3, "cropDrops": [ { "itemId": "wheat", "minCount": 2, "maxCount": 4 }, { "itemId": "seed", "minCount": 1, "maxCount": 2 } ], "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X", "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } } } ================================================ FILE: blocks/furnitures/flowers/allium.json ================================================ { "block": { "allium": { "textureData": "allium.png", "color": [ 188, 110, 250 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 188, 109, 255 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "allium": { "type": "BLOCKS", "iconTextureData": "allium.png", "group": "GROUP_FLOWER", "blockId": "allium" } } } ================================================ FILE: blocks/furnitures/flowers/azure_bluet.json ================================================ { "block": { "azure_bluet": { "textureData": "azure_bluet.png", "color": [ 225, 225, 225 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 188, 188, 188 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "azure_bluet": { "type": "BLOCKS", "iconTextureData": "azure_bluet.png", "group": "GROUP_FLOWER", "blockId": "azure_bluet" } } } ================================================ FILE: blocks/furnitures/flowers/blue_orchid.json ================================================ { "block": { "blue_orchid": { "textureData": "blue_orchid.png", "color": [ 47, 177, 233 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 50, 180, 230 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "blue_orchid": { "type": "BLOCKS", "iconTextureData": "blue_orchid.png", "group": "GROUP_FLOWER", "blockId": "blue_orchid" } } } ================================================ FILE: blocks/furnitures/flowers/dandelion.json ================================================ { "block": { "dandelion": { "textureData": "dandelion.png", "color": [ 240, 210, 17 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 255, 233, 24 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "dandelion": { "type": "BLOCKS", "iconTextureData": "dandelion.png", "group": "GROUP_FLOWER", "blockId": "dandelion" } } } ================================================ FILE: blocks/furnitures/flowers/fern.json ================================================ { "block": { "fern": { "textureData": "fern.png", "color": [ 60, 90, 50 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 66, 99, 55 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "fern": { "type": "BLOCKS", "iconTextureData": "fern.png", "group": "GROUP_GRASS", "blockId": "fern", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/flowers/lilac.json ================================================ { "block": { "lilac": { "textureData": "lilac.png", "color": [ 137, 93, 148 ], "type": "FURNITURE", "width": 2, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 140, 100, 140 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 64, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "lilac": { "type": "BLOCKS", "iconTextureData": "lilac.png", "group": "GROUP_LARGE_FLOWER", "blockId": "lilac" } } } ================================================ FILE: blocks/furnitures/flowers/orange_tulip.json ================================================ { "block": { "orange_tulip": { "textureData": "orange_tulip.png", "color": [ 238, 144, 18 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isDestroyByWeapon": false, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 233, 144, 17 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "orange_tulip": { "type": "BLOCKS", "iconTextureData": "orange_tulip.png", "group": "GROUP_FLOWER", "blockId": "orange_tulip" } } } ================================================ FILE: blocks/furnitures/flowers/peony.json ================================================ { "block": { "peony": { "textureData": "peony.png", "color": [ 227, 180, 255 ], "type": "FURNITURE", "width": 2, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 222, 180, 255 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 64, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "peony": { "type": "BLOCKS", "iconTextureData": "peony.png", "group": "GROUP_LARGE_FLOWER", "blockId": "peony" } } } ================================================ FILE: blocks/furnitures/flowers/pink_tulip.json ================================================ { "block": { "pink_tulip": { "textureData": "pink_tulip.png", "color": [ 214, 171, 218 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 222, 190, 222 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "pink_tulip": { "type": "BLOCKS", "iconTextureData": "pink_tulip.png", "group": "GROUP_FLOWER", "blockId": "pink_tulip" } } } ================================================ FILE: blocks/furnitures/flowers/poppy.json ================================================ { "block": { "poppy": { "textureData": "poppy.png", "color": [ 220, 6, 6 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 200, 1, 1 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "poppy": { "type": "BLOCKS", "iconTextureData": "poppy.png", "group": "GROUP_FLOWER", "blockId": "poppy" } } } ================================================ FILE: blocks/furnitures/flowers/red_tulip.json ================================================ { "block": { "red_tulip": { "textureData": "red_tulip.png", "color": [ 210, 15, 13 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 120, 1, 1 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "red_tulip": { "type": "BLOCKS", "iconTextureData": "red_tulip.png", "group": "GROUP_FLOWER", "blockId": "red_tulip" } } } ================================================ FILE: blocks/furnitures/flowers/rose_bush.json ================================================ { "block": { "rose_bush": { "textureData": "rose_bush.png", "color": [ 210, 10, 10 ], "type": "FURNITURE", "width": 2, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 222, 11, 11 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 64, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "rose_bush": { "type": "BLOCKS", "iconTextureData": "rose_bush.png", "group": "GROUP_LARGE_FLOWER", "blockId": "rose_bush" } } } ================================================ FILE: blocks/furnitures/flowers/sunflower.json ================================================ { "block": { "sunflower": { "textureData": "sunflower.png", "color": [ 135, 226, 55 ], "type": "FURNITURE", "width": 2, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 233, 233, 55 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 64, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sunflower": { "type": "BLOCKS", "iconTextureData": "sunflower.png", "group": "GROUP_LARGE_FLOWER", "blockId": "sunflower" } } } ================================================ FILE: blocks/furnitures/flowers/white_tulip.json ================================================ { "block": { "white_tulip": { "textureData": "white_tulip.png", "color": [ 222, 222, 222 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 222, 222, 222 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "white_tulip": { "type": "BLOCKS", "iconTextureData": "white_tulip.png", "group": "GROUP_FLOWER", "blockId": "white_tulip" } } } ================================================ FILE: blocks/furnitures/grasses/blood_grass.json ================================================ { "block": { "blood_grass": { "textureData": "blood_grass.png", "color": [ 80, 20, 20 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "isLossyCollection": true, "soundId": "grass", "stepSoundId": "grass", "particleColor": [ 255, 80, 20, 20 ], "preset": "Grass", "animation": [ { "animationId": 0, "frameRandom": true, "frameStart": 0, "frameCount": 6, "shake": true, "shakeCenterX": 8, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.2 } ] } } } ================================================ FILE: blocks/furnitures/grasses/eyeball_grass.json ================================================ { "block": { "eyeball_grass": { "textureData": "eyeball_grass.png", "color": [ 238, 178, 198 ], "type": "FURNITURE", "width": 2, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 238, 178, 198 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 64, "shakePeriod": 128, "shakeAngle": 0.05 } ] } } } ================================================ FILE: blocks/furnitures/grasses/grass.json ================================================ { "block": { "grass": { "textureData": "grass.png", "color": [ 110, 162, 63 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "isLossyCollection": true, "soundId": "grass", "stepSoundId": "grass", "particleColor": [ 255, 100, 150, 60 ], "preset": "Grass", "animation": [ { "animationId": 0, "frameRandom": true, "frameStart": 0, "frameCount": 6, "shake": true, "shakeCenterX": 8, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "grass": { "type": "BLOCKS", "iconTextureData": "grass_icon.png", "group": "GROUP_GRASS", "blockId": "grass", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/grasses/large_eyeball_grass.json ================================================ { "block": { "large_eyeball_grass": { "textureData": "large_eyeball_grass.png", "color": [ 238, 178, 198 ], "type": "FURNITURE", "width": 2, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 238, 178, 198 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 64, "shakePeriod": 128, "shakeAngle": 0.05 } ] } } } ================================================ FILE: blocks/furnitures/grasses/tainted_grass.json ================================================ { "block": { "tainted_grass": { "textureData": "tainted_grass.png", "color": [ 120, 60, 190 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_TAINTED_DECO_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "isLossyCollection": true, "soundId": "grass", "stepSoundId": "grass", "particleColor": [ 255, 120, 60, 190 ], "preset": "Grass", "animation": [ { "animationId": 0, "frameRandom": true, "frameStart": 0, "frameCount": 6, "shake": true, "shakeCenterX": 8, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.2 } ] } } } ================================================ FILE: blocks/furnitures/lightings/candle.json ================================================ { "block": { "candle": { "textureData": "candle.png", "color": [ 255, 166, 77 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isFragile": true, "isLighting": true, "lightColor": [ 24, 2, 2, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 255, 155, 40 ], "covers": [ { "modTextureId": "candle_fire", "offsetX": 0, "offsetY": -12 } ] } }, "item": { "candle": { "type": "BLOCKS", "iconTextureData": "candle.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "candle" } } } ================================================ FILE: blocks/furnitures/lightings/candle_holder.json ================================================ { "block": { "candle_holder": { "textureData": "candle_holder.png", "color": [ 255, 168, 77 ], "type": "FURNITURE", "width": 2, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isFragile": true, "isLighting": true, "lightColor": [ 26, 4, 4, 0 ], "lightX": 0, "lightY": 0, "lightWi": 3, "lightHi": 1, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 50, 70, 80 ], "covers": [ { "modTextureId": "candle_fire", "offsetX": 8, "offsetY": -10 }, { "modTextureId": "candle_fire", "offsetX": -4, "offsetY": -2 }, { "modTextureId": "candle_fire", "offsetX": 20, "offsetY": -2 } ] } }, "item": { "candle_holder": { "type": "BLOCKS", "iconTextureData": "candle_holder.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "candle_holder" } } } ================================================ FILE: blocks/furnitures/lightings/chandeliers.json ================================================ { "block": { "chandeliers": { "textureData": "chandeliers.png", "color": [ 141, 225, 203 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isFragile": true, "isLighting": true, "lightColor": [ 28, 8, 8, 8 ], "lightX": 0, "lightY": 2, "lightWi": 2, "lightHi": 1, "soundGroupId": "glass", "stepSoundId": "step_cloth", "particleColor": [ 255, 222, 22, 222 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 24, "shakeCenterY": 0, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "chandeliers": { "type": "BLOCKS", "iconTextureData": "chandeliers.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "chandeliers" } } } ================================================ FILE: blocks/furnitures/lightings/fire_lamp.json ================================================ { "block": { "fire_lamp": { "textureData": "fire_lamp.png", "color": [ 128, 100, 60 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isFragile": true, "isLighting": true, "lightColor": [ 28, 8, 8, 0 ], "lightX": 0, "lightY": 2, "lightWi": 3, "lightHi": 1, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 180, 150, 100 ], "animation": [ { "animationId": 0, "frameSpeed": 8, "frameStart": 0, "frameCount": 4, "shake": true, "shakeCenterX": 24, "shakeCenterY": 0, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "fire_lamp": { "type": "BLOCKS", "iconTextureData": "fire_lamp_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "fire_lamp" } } } ================================================ FILE: blocks/furnitures/lightings/jack_o_lantern.json ================================================ { "block": { "jack_o_lantern": { "textureData": "jack_o_lantern.png", "color": [ 205, 123, 12 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "lightOpacity": 3, "isLighting": true, "lightColor": [ 32, 0, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 2, "lightHi": 2, "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 123, 13 ] } }, "item": { "jack_o_lantern": { "type": "BLOCKS", "iconTextureData": "jack_o_lantern.png", "group": "GROUP_SAPLING", "blockId": "jack_o_lantern" } } } ================================================ FILE: blocks/furnitures/lightings/lantern.json ================================================ { "block": { "lantern": { "textureData": "lantern.png", "color": [ 225, 225, 160 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isNoWater": false, "isFragile": true, "isLighting": true, "lightColor": [ 32, 0, 0, 0 ], "lightX": 0, "lightY": 1, "lightWi": 1, "lightHi": 1, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 225, 225, 160 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 0, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "lantern": { "type": "BLOCKS", "iconTextureData": "lantern.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "lantern" } } } ================================================ FILE: blocks/furnitures/lightings/nether_lamp.json ================================================ { "block": { "nether_lamp": { "textureData": "nether_lamp.png", "color": [ 73, 29, 34 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isFragile": true, "isLighting": true, "lightColor": [ 28, 8, 8, 0 ], "lightX": 0, "lightY": 2, "lightWi": 3, "lightHi": 1, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 73, 29, 34 ], "animation": [ { "animationId": 0, "frameSpeed": 8, "frameStart": 0, "frameCount": 4, "shake": true, "shakeCenterX": 24, "shakeCenterY": 0, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "nether_lamp": { "type": "BLOCKS", "iconTextureData": "nether_lamp_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "nether_lamp" } } } ================================================ FILE: blocks/furnitures/misc/anvil.json ================================================ { "block": { "anvil": { "textureData": "anvil.png", "color": [ 55, 55, 55 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 200, "slipperiness": 1.0, "placeSoundId": "anvil_land", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ], "preset": "Anvil" } }, "item": { "anvil": { "type": "BLOCKS", "iconTextureData": "anvil.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "anvil" } } } ================================================ FILE: blocks/furnitures/misc/book.json ================================================ { "block": { "book": { "textureData": "book.png", "color": [ 177, 177, 55 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 40, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 140, 140, 50 ], "animation": [ { "animationId": 0, "frameRandom": true, "frameStart": 0, "frameCount": 4 } ] } }, "item": { "book_block": { "type": "BLOCKS", "iconTextureData": "book_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "book", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/misc/brewing_stand.json ================================================ { "block": { "brewing_stand": { "textureData": "brewing_stand.png", "color": [ 44, 44, 44 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 90, 80, 40 ], "preset": "Brewing" } }, "item": { "brewing_stand": { "type": "BLOCKS", "iconTextureData": "brewing_stand.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "brewing_stand" } } } ================================================ FILE: blocks/furnitures/misc/cake.json ================================================ { "block": { "cake": { "textureData": "cake.png", "color": [ 244, 244, 244 ], "type": "FURNITURE", "width": 2, "height": 1, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 30, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isLossyCollection": true, "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 90, 50, 10 ], "preset": "Cake", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_Y" } ] } }, "item": { "cake": { "type": "BLOCKS", "iconTextureData": "cake_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "cake" } } } ================================================ FILE: blocks/furnitures/misc/campfire.json ================================================ { "block": { "campfire": { "textureData": "campfire.png", "color": [ 249, 235, 170 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isNoWater": true, "isFragile": true, "isLighting": true, "lightColor": [ 32, 8, 8, 0 ], "lightX": 0, "lightY": 0, "lightWi": 2, "lightHi": 2, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 249, 235, 170 ], "exParticle": "campfire_particle", "animation": [ { "animationId": 0, "frameSpeed": 8, "frameStart": 0, "frameCount": 4 } ] } }, "item": { "campfire": { "type": "BLOCKS", "iconTextureData": "campfire_icon.png", "group": "GROUP_WOODEN_FURNITURE", "blockId": "campfire" } } } ================================================ FILE: blocks/furnitures/misc/cauldron.json ================================================ { "block": { "cauldron": { "textureData": "cauldron.png", "color": [ 77, 77, 77 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "cauldron": { "type": "BLOCKS", "iconTextureData": "cauldron.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "cauldron" } } } ================================================ FILE: blocks/furnitures/misc/cobweb.json ================================================ { "block": { "cobweb": { "textureData": "cobweb.png", "color": [ 188, 188, 188 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "ALL", "attachable": "ALL", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 30, "isKilledByLava": true, "isNoWater": true, "isFragile": true, "isDestroyByWeapon": true, "slipperiness": 1.0, "isActAsTile": true, "soundId": "grass", "stepSoundId": "grass", "particleColor": [ 255, 222, 222, 222 ], "preset": "Cobweb" } }, "item": { "cobweb": { "type": "BLOCKS", "iconTextureData": "cobweb_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "cobweb" } } } ================================================ FILE: blocks/furnitures/misc/crafting_table.json ================================================ { "block": { "crafting_table": { "textureData": "crafting_table.png", "color": [ 159, 132, 77 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 160, 130, 80 ], "preset": "CraftingTable" } }, "item": { "crafting_table": { "type": "BLOCKS", "iconTextureData": "crafting_table.png", "group": "GROUP_WOODEN_FURNITURE", "blockId": "crafting_table", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/misc/enchantment_table.json ================================================ { "block": { "enchantment_table": { "textureData": "enchantment_table.png", "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "PICKAXE", "mineGrade": "DIAMOND", "hardness": 500, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 76, 76, 155 ], "preset": "Enchantment" } }, "item": { "enchantment_table": { "type": "BLOCKS", "iconTextureData": "enchantment_table.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "enchantment_table" } } } ================================================ FILE: blocks/furnitures/misc/flower_pot.json ================================================ { "block": { "flower_pot": { "textureData": "flower_pot.png", "color": [ 121, 67, 50 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 121, 67, 50 ] } }, "item": { "flower_pot": { "type": "BLOCKS", "iconTextureData": "flower_pot.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "flower_pot" } } } ================================================ FILE: blocks/furnitures/misc/flower_pot_large.json ================================================ { "block": { "flower_pot_large": { "textureData": "flower_pot_large.png", "color": [ 121, 67, 50 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 121, 67, 50 ] } }, "item": { "flower_pot_large": { "type": "BLOCKS", "iconTextureData": "flower_pot_large.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "flower_pot_large" } } } ================================================ FILE: blocks/furnitures/misc/furnace.json ================================================ { "block": { "furnace": { "textureData": "furnace.png", "color": [ 133, 133, 133 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ], "exParticle": "furnace_particle", "preset": "Furnace", "animation": [ { "animationId": 0, "frameStart": 0 }, { "animationId": 1, "frameStart": 1 } ] } }, "item": { "furnace": { "type": "BLOCKS", "iconTextureData": "furnace_icon.png", "group": "GROUP_STONE_FURNITURE", "blockId": "furnace" } } } ================================================ FILE: blocks/furnitures/misc/health_crystal.json ================================================ { "block": { "health_crystal": { "textureData": "health_crystal.png", "color": [ 166, 0, 0 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "NONE", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 166, 0, 0 ], "preset": "HeartCrystal" } }, "item": { "health_crystal": { "type": "MATERIALS", "iconTextureData": "health_crystal.png", "group": "GROUP_OTHERS_FURNITURE" } } } ================================================ FILE: blocks/furnitures/misc/jukebox.json ================================================ { "block": { "jukebox": { "textureData": "jukebox.png", "color": [ 222, 100, 62 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 100, 60 ] } }, "item": { "jukebox": { "type": "MATERIALS", "iconTextureData": "jukebox.png", "group": "GROUP_OTHERS_FURNITURE", "onTest": true } } } ================================================ FILE: blocks/furnitures/misc/pot.json ================================================ { "block": { "pot": { "textureData": "pot.png", "color": [ 119, 85, 75 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isLossyCollection": true, "isDestroyByWeapon": true, "soundGroupId": "shatter", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 150, 110, 100 ], "preset": "Pot" } } } ================================================ FILE: blocks/furnitures/misc/potion.json ================================================ { "block": { "potion": { "textureData": "potion.png", "color": [ 66, 66, 255 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "glass", "particleColor": [ 255, 55, 55, 255 ] } } } ================================================ FILE: blocks/furnitures/misc/sign.json ================================================ { "block": { "sign": { "textureData": "sign.png", "color": [ 170, 133, 78 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 100, 40 ] } }, "item": { "sign": { "type": "MATERIALS", "iconTextureData": "sign_icon.png", "group": "GROUP_WOODEN_FURNITURE", "fuelTime": 60, "onTest": true } } } ================================================ FILE: blocks/furnitures/misc/skull.json ================================================ { "block": { "skull": { "textureData": "skull.png", "color": [ 125, 188, 66 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isFragile": true, "isLossyCollection": true, "isDestroyByWeapon": true, "soundGroupId": "glass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 244, 177, 144 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/misc/thorn.json ================================================ { "block": { "thorn": { "textureData": "thorn.png", "color": [ 111, 111, 111 ], "renderMode": "RENDER_PIPE", "type": "TILE", "group": "THRON", "collision": "SOLID", "lightOpacity": 3, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "DIAMOND", "hardness": 500000, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 111, 111, 111 ] } } } ================================================ FILE: blocks/furnitures/mushrooms/brown_mushroom.json ================================================ { "block": { "brown_mushroom": { "textureData": "brown_mushroom.png", "color": [ 157, 120, 72 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_MUSHROOM_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 170, 140, 80 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "brown_mushroom": { "type": "BLOCKS", "iconTextureData": "brown_mushroom.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "brown_mushroom" } } } ================================================ FILE: blocks/furnitures/mushrooms/glowing_mushroom.json ================================================ { "block": { "glowing_mushroom": { "textureData": "glowing_mushroom.png", "color": [ 222, 222, 0 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_MUSHROOM_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "slipperiness": 1.0, "isKilledByLava": true, "isLighting": true, "lightColor": [ 12, 4, 4, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 2, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 200, 200, 10 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "glowing_mushroom": { "type": "BLOCKS", "iconTextureData": "glowing_mushroom.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "glowing_mushroom" } } } ================================================ FILE: blocks/furnitures/mushrooms/large_brown_mushroom.json ================================================ { "block": { "large_brown_mushroom": { "textureData": "large_brown_mushroom.png", "color": [ 159, 120, 72 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_MUSHROOM_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 155, 120, 72 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "large_brown_mushroom": { "type": "BLOCKS", "iconTextureData": "large_brown_mushroom.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "large_brown_mushroom" } } } ================================================ FILE: blocks/furnitures/mushrooms/large_poison_mushroom.json ================================================ { "block": { "large_poison_mushroom": { "textureData": "large_poison_mushroom.png", "color": [ 144, 96, 160 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_MUSHROOM_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "slipperiness": 1.0, "isKilledByLava": true, "isLighting": true, "lightColor": [ 10, 6, 0, 6 ], "lightX": 0, "lightY": 0, "lightWi": 2, "lightHi": 2, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 140, 100, 160 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "large_poison_mushroom": { "type": "BLOCKS", "iconTextureData": "large_poison_mushroom.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "large_poison_mushroom" } } } ================================================ FILE: blocks/furnitures/mushrooms/large_red_mushroom.json ================================================ { "block": { "large_red_mushroom": { "textureData": "large_red_mushroom.png", "color": [ 166, 12, 12 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_MUSHROOM_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 200, 10, 10 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "large_red_mushroom": { "type": "BLOCKS", "iconTextureData": "large_red_mushroom.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "large_red_mushroom" } } } ================================================ FILE: blocks/furnitures/mushrooms/poison_mushroom.json ================================================ { "block": { "poison_mushroom": { "textureData": "poison_mushroom.png", "color": [ 144, 96, 160 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_MUSHROOM_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 140, 100, 160 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "poison_mushroom": { "type": "BLOCKS", "iconTextureData": "poison_mushroom.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "poison_mushroom" } } } ================================================ FILE: blocks/furnitures/mushrooms/red_mushroom.json ================================================ { "block": { "red_mushroom": { "textureData": "red_mushroom.png", "color": [ 180, 12, 12 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_MUSHROOM_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 170, 10, 10 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ] } }, "item": { "red_mushroom": { "type": "BLOCKS", "iconTextureData": "red_mushroom.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "red_mushroom" } } } ================================================ FILE: blocks/furnitures/paintings/painting.json ================================================ { "block": { "painting": { "textureData": "painting.png", "color": [ 159, 132, 77 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "WALL", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 180, 150, 100 ] } } } ================================================ FILE: blocks/furnitures/paintings/painting_2x2.json ================================================ { "block": { "painting_2x2": { "textureData": "painting_2x2.png", "color": [ 255, 0, 255 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "WALL", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isNoWater": true, "isFragile": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 255, 0, 255 ], "preset": "Painting", "maxTag": 7, "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "painting_2x2": { "type": "BLOCKS", "iconTextureData": "painting_2x2_icon.png", "group": "GROUP_PAINTING", "blockId": "painting_2x2", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/paintings/painting_2x4.json ================================================ { "block": { "painting_2x4": { "textureData": "painting_2x4.png", "color": [ 255, 0, 255 ], "type": "FURNITURE", "width": 2, "height": 4, "collision": "NONE", "attach": "WALL", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isNoWater": true, "isFragile": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 255, 0, 255 ], "preset": "Painting", "maxTag": 2, "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "painting_2x4": { "type": "BLOCKS", "iconTextureData": "painting_2x4_icon.png", "group": "GROUP_PAINTING", "blockId": "painting_2x4", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/paintings/painting_4x2.json ================================================ { "block": { "painting_4x2": { "textureData": "painting_4x2.png", "color": [ 255, 0, 255 ], "type": "FURNITURE", "width": 4, "height": 2, "collision": "NONE", "attach": "WALL", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isNoWater": true, "isFragile": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 255, 0, 255 ], "preset": "Painting", "maxTag": 5, "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "painting_4x2": { "type": "BLOCKS", "iconTextureData": "painting_4x2_icon.png", "group": "GROUP_PAINTING", "blockId": "painting_4x2", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/paintings/painting_4x4.json ================================================ { "block": { "painting_4x4": { "textureData": "painting_4x4.png", "color": [ 255, 0, 255 ], "type": "FURNITURE", "width": 4, "height": 4, "collision": "NONE", "attach": "WALL", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isNoWater": true, "isFragile": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 255, 0, 255 ], "preset": "Painting", "maxTag": 6, "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "painting_4x4": { "type": "BLOCKS", "iconTextureData": "painting_4x4_icon.png", "group": "GROUP_PAINTING", "blockId": "painting_4x4", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/paintings/painting_8x4.json ================================================ { "block": { "painting_8x4": { "textureData": "painting_8x4.png", "color": [ 255, 0, 255 ], "type": "FURNITURE", "width": 8, "height": 4, "collision": "NONE", "attach": "WALL", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isNoWater": true, "isFragile": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 255, 0, 255 ], "preset": "Painting", "maxTag": 1, "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "painting_8x4": { "type": "BLOCKS", "iconTextureData": "painting_8x4_icon.png", "group": "GROUP_PAINTING", "blockId": "painting_8x4", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/paintings/painting_8x6.json ================================================ { "block": { "painting_8x6": { "textureData": "painting_8x6.png", "color": [ 255, 0, 255 ], "type": "FURNITURE", "width": 8, "height": 6, "collision": "NONE", "attach": "WALL", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isNoWater": true, "isFragile": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 255, 0, 255 ], "preset": "Painting", "maxTag": 1, "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "painting_8x6": { "type": "BLOCKS", "iconTextureData": "painting_8x6_icon.png", "group": "GROUP_PAINTING", "blockId": "painting_8x6", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/paintings/painting_8x8.json ================================================ { "block": { "painting_8x8": { "textureData": "painting_8x8.png", "color": [ 255, 0, 255 ], "type": "FURNITURE", "width": 8, "height": 8, "collision": "NONE", "attach": "WALL", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 20, "isKilledByLava": true, "isNoWater": true, "isFragile": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 255, 0, 255 ], "preset": "Painting", "maxTag": 3, "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "painting_8x8": { "type": "BLOCKS", "iconTextureData": "painting_8x8_icon.png", "group": "GROUP_PAINTING", "blockId": "painting_8x8", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/plants/bush.json ================================================ { "block": { "bush": { "textureData": "bush.png", "color": [ 92, 178, 66 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 120, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 100, 50 ] } } } ================================================ FILE: blocks/furnitures/redstones/daylight_sensor.json ================================================ { "block": { "daylight_sensor": { "textureData": "daylight_sensor.png", "color": [ 211, 211, 122 ], "type": "FURNITURE", "width": 2, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "lightOpacity": 3, "isLighting": true, "lightColor": [ 6, 0, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 2, "lightHi": 1, "hardness": 72, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "glass", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 80, 70, 50 ], "preset": "DaylightTrigger", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "daylight_sensor": { "type": "BLOCKS", "iconTextureData": "daylight_sensor_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "daylight_sensor" } } } ================================================ FILE: blocks/furnitures/redstones/daylight_sensor_inverted.json ================================================ { "block": { "daylight_sensor_inverted": { "textureData": "daylight_sensor_inverted.png", "color": [ 200, 210, 220 ], "type": "FURNITURE", "width": 2, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "lightOpacity": 3, "isLighting": true, "lightColor": [ 6, 0, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 2, "lightHi": 1, "hardness": 72, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "glass", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 80, 70, 50 ], "preset": "MoonlightTrigger", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "daylight_sensor_inverted": { "type": "BLOCKS", "iconTextureData": "daylight_sensor_inverted_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "daylight_sensor_inverted" } } } ================================================ FILE: blocks/furnitures/redstones/dispenser.json ================================================ { "block": { "dispenser": { "textureData": "dispenser.png", "color": [ 111, 111, 111 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "SOLID", "attach": "ALL", "attachable": "ALL", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 170, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ], "preset": "Shooter", "animation": [ { "animationId": 0, "frameStart": 0 }, { "animationId": 1, "frameStart": 1 }, { "animationId": 2, "frameStart": 2 }, { "animationId": 3, "frameStart": 3 } ] } }, "item": { "dispenser": { "type": "BLOCKS", "iconTextureData": "dispenser_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "dispenser" } } } ================================================ FILE: blocks/furnitures/redstones/lever.json ================================================ { "block": { "lever": { "textureData": "lever.png", "color": [ 33, 166, 180 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 72, "slipperiness": 1.0, "soundGroupId": "stone", "functionSoundId": "button1", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ], "preset": "Button", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "lever": { "type": "BLOCKS", "iconTextureData": "lever_icon.png", "group": "GROUP_BUTTON", "blockId": "lever" } } } ================================================ FILE: blocks/furnitures/redstones/pressure_plates/pressure_plate_golden.json ================================================ { "block": { "pressure_plate_golden": { "textureData": "golden_pressure_plate.png", "color": [ 222, 190, 55 ], "type": "FURNITURE", "subGroup": "PRESSURE_PLATE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 30, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 120, 0 ], "preset": "RedstonePlate", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "golden_pressure_plate": { "type": "BLOCKS", "iconTextureData": "golden_pressure_plate_icon.png", "group": "GROUP_PRESSURE_PLATE", "blockId": "pressure_plate_golden" } } } ================================================ FILE: blocks/furnitures/redstones/pressure_plates/pressure_plate_iron.json ================================================ { "block": { "pressure_plate_iron": { "textureData": "iron_pressure_plate.png", "color": [ 194, 188, 196 ], "type": "FURNITURE", "subGroup": "PRESSURE_PLATE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 30, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 200, 200 ], "preset": "RedstonePlate", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "iron_pressure_plate": { "type": "BLOCKS", "iconTextureData": "iron_pressure_plate_icon.png", "group": "GROUP_PRESSURE_PLATE", "blockId": "pressure_plate_iron" } } } ================================================ FILE: blocks/furnitures/redstones/pressure_plates/pressure_plate_stone.json ================================================ { "block": { "pressure_plate_stone": { "textureData": "stone_pressure_plate.png", "color": [ 111, 111, 111 ], "type": "FURNITURE", "subGroup": "PRESSURE_PLATE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 30, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ], "preset": "RedstonePlate", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "stone_pressure_plate": { "type": "BLOCKS", "iconTextureData": "stone_pressure_plate_icon.png", "group": "GROUP_PRESSURE_PLATE", "blockId": "pressure_plate_stone" } } } ================================================ FILE: blocks/furnitures/redstones/pressure_plates/pressure_plate_wooden.json ================================================ { "block": { "pressure_plate_wooden": { "textureData": "wooden_pressure_plate.png", "color": [ 180, 144, 90 ], "type": "FURNITURE", "subGroup": "PRESSURE_PLATE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 30, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 152, 120, 80 ], "preset": "RedstonePlate", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "wooden_pressure_plate": { "type": "BLOCKS", "iconTextureData": "wooden_pressure_plate_icon.png", "group": "GROUP_PRESSURE_PLATE", "blockId": "pressure_plate_wooden", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/redstones/redstone_lamp.json ================================================ { "block": { "redstone_lamp": { "textureData": "redstone_lamp.png", "color": [ 166, 166, 0 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "SOLID", "attach": "ALL", "attachable": "ALL", "toolType": "AXE", "mineGrade": "GRASS", "lightOpacity": 3, "lightColor": [ 32, 0, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "hardness": 72, "slipperiness": 1.0, "soundGroupId": "glass", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 60, 30 ], "preset": "RedstoneLamp", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "redstone_lamp": { "type": "BLOCKS", "iconTextureData": "redstone_lamp_icon.png", "group": "GROUP_LIGHTING", "blockId": "redstone_lamp" } } } ================================================ FILE: blocks/furnitures/redstones/stone_button.json ================================================ { "block": { "stone_button": { "textureData": "stone_button.png", "color": [ 111, 111, 111 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "WALL", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 72, "slipperiness": 1.0, "soundGroupId": "stone", "functionSoundId": "button1", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ], "preset": "Button", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "stone_button": { "type": "BLOCKS", "iconTextureData": "stone_button_icon.png", "group": "GROUP_BUTTON", "blockId": "stone_button" } } } ================================================ FILE: blocks/furnitures/redstones/wooden_button.json ================================================ { "block": { "wooden_button": { "textureData": "wooden_button.png", "color": [ 159, 132, 77 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "WALL", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 72, "slipperiness": 1.0, "soundGroupId": "wood", "functionSoundId": "button1", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 160, 130, 80 ], "preset": "Button", "animation": [ { "animationId": 0, "tagUsage": "TAG_ADD_FRAME_INDEX_X" } ] } }, "item": { "wooden_button": { "type": "BLOCKS", "iconTextureData": "wooden_button_icon.png", "group": "GROUP_BUTTON", "blockId": "wooden_button", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/rocks/rock.json ================================================ { "block": { "rock": { "textureData": "rock.png", "color": [ 128, 128, 128 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 128, 128, 128 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/rocks/rock_waste.json ================================================ { "block": { "rock_waste": { "textureData": "rock_waste.png", "color": [ 100, 50, 30 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 50, 30 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/saplings/sapling_acacia.json ================================================ { "block": { "sapling_acacia": { "textureData": "sapling_acacia.png", "color": [ 109, 122, 19 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 88, 98, 16 ], "transformId": "log_acacia", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_acacia": { "type": "BLOCKS", "iconTextureData": "sapling_acacia.png", "group": "GROUP_SAPLING", "blockId": "sapling_acacia", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/saplings/sapling_bare_oak.json ================================================ { "block": { "sapling_bare_oak": { "textureData": "sapling_bare_oak.png", "color": [ 120, 90, 55 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 120, 90, 55 ], "transformId": "log_bare_oak", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_bare_oak": { "type": "BLOCKS", "iconTextureData": "sapling_bare_oak.png", "group": "GROUP_SAPLING", "blockId": "sapling_bare_oak", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/saplings/sapling_birch.json ================================================ { "block": { "sapling_birch": { "textureData": "sapling_birch.png", "color": [ 204, 209, 144 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 211, 211, 244 ], "transformId": "log_birch", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_birch": { "type": "BLOCKS", "iconTextureData": "sapling_birch.png", "group": "GROUP_SAPLING", "blockId": "sapling_birch", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/saplings/sapling_cactus.json ================================================ { "block": { "sapling_cactus": { "textureData": "sapling_cactus.png", "color": [ 150, 120, 76 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 150, 120, 30 ], "transformId": "log_cactus", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_cactus": { "type": "BLOCKS", "iconTextureData": "sapling_cactus.png", "group": "GROUP_SAPLING", "blockId": "sapling_cactus" } } } ================================================ FILE: blocks/furnitures/saplings/sapling_dark_oak.json ================================================ { "block": { "sapling_dark_oak": { "textureData": "sapling_dark_oak.png", "color": [ 80, 55, 33 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 88, 55, 33 ], "transformId": "log_dark_oak", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_dark_oak": { "type": "BLOCKS", "iconTextureData": "sapling_dark_oak.png", "group": "GROUP_SAPLING", "blockId": "sapling_dark_oak", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/saplings/sapling_jungle.json ================================================ { "block": { "sapling_jungle": { "textureData": "sapling_jungle.png", "color": [ 54, 123, 54 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 55, 123, 55 ], "transformId": "log_jungle", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_jungle": { "type": "BLOCKS", "iconTextureData": "sapling_jungle.png", "group": "GROUP_SAPLING", "blockId": "sapling_jungle", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/saplings/sapling_oak.json ================================================ { "block": { "sapling_oak": { "textureData": "sapling_oak.png", "color": [ 120, 90, 55 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 88, 66, 27 ], "transformId": "log_oak", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_oak": { "type": "BLOCKS", "iconTextureData": "sapling_oak.png", "group": "GROUP_SAPLING", "blockId": "sapling_oak", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/saplings/sapling_palm.json ================================================ { "block": { "sapling_palm": { "textureData": "sapling_palm.png", "color": [ 130, 114, 70 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 150, 130, 80 ], "transformId": "log_palm", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_palm": { "type": "BLOCKS", "iconTextureData": "sapling_palm.png", "group": "GROUP_SAPLING", "blockId": "sapling_palm", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/saplings/sapling_spruce.json ================================================ { "block": { "sapling_spruce": { "textureData": "sapling_spruce.png", "color": [ 77, 55, 33 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 55, 27, 27 ], "transformId": "log_spruce", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_spruce": { "type": "BLOCKS", "iconTextureData": "sapling_spruce.png", "group": "GROUP_SAPLING", "blockId": "sapling_spruce", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/saplings/sapling_tainted.json ================================================ { "block": { "sapling_tainted": { "textureData": "sapling_tainted.png", "color": [ 67, 39, 90 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 88, 44, 111 ], "transformId": "log_tainted", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_tainted": { "type": "BLOCKS", "iconTextureData": "sapling_tainted.png", "group": "GROUP_SAPLING", "blockId": "sapling_tainted", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/saplings/sapling_volcano.json ================================================ { "block": { "sapling_volcano": { "textureData": "sapling_volcano.png", "color": [ 200, 60, 60 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 200, 60, 60 ], "transformId": "log_volcano_oak", "preset": "Sapling", "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 16, "shakeCenterY": 32, "shakePeriod": 128, "shakeAngle": 0.05 } ] } }, "item": { "sapling_volcano": { "type": "BLOCKS", "iconTextureData": "sapling_volcano.png", "group": "GROUP_SAPLING", "blockId": "sapling_volcano", "fuelTime": 20 } } } ================================================ FILE: blocks/furnitures/seas/coral.json ================================================ { "block": { "coral": { "textureData": "coral.png", "color": [ 255, 190, 220 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 222, 222, 222 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/seas/kelp.json ================================================ { "block": { "kelp": { "textureData": "kelp.png", "color": [ 88, 171, 48 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "isChipCollection": true, "lossyItemId": "kelp", "chipCount": 4, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": true, "soundId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 88, 171, 48 ], "preset": "Kelp", "animation": [ { "animationId": 0, "frameSpeed": 8, "frameStart": 0, "frameCount": 4 } ] } } } ================================================ FILE: blocks/furnitures/seas/sea_grass.json ================================================ { "block": { "sea_grass": { "textureData": "sea_grass.png", "color": [ 60, 160, 10 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 60, 160, 0 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/seas/sea_shell.json ================================================ { "block": { "sea_shell": { "textureData": "sea_shell.png", "color": [ 244, 133, 119 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 222, 222, 222 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/small_trees/small_tree_desert.json ================================================ { "block": { "small_tree_desert": { "textureData": "small_tree_desert.png", "color": [ 197, 133, 19 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_SAND_DECO_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 200, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 140, 120 ] } } } ================================================ FILE: blocks/furnitures/small_trees/small_tree_normal.json ================================================ { "block": { "small_tree_normal": { "textureData": "small_tree.png", "color": [ 183, 165, 80 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_PLANT_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 200, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 110, 100, 50 ] } } } ================================================ FILE: blocks/furnitures/small_trees/small_tree_snowy.json ================================================ { "block": { "small_tree_snowy": { "textureData": "small_tree_snowy.png", "color": [ 166, 188, 190 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_ICE_DECO_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 200, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 60, 140 ] } } } ================================================ FILE: blocks/furnitures/small_trees/small_tree_tainted.json ================================================ { "block": { "small_tree_tainted": { "textureData": "small_tree_tainted.png", "color": [ 83, 48, 122 ], "type": "FURNITURE", "width": 3, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_TAINTED_DECO_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 200, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 60, 140 ] } } } ================================================ FILE: blocks/furnitures/small_trees/small_tree_waste.json ================================================ { "block": { "small_tree_waste": { "textureData": "small_tree_waste.png", "color": [ 100, 50, 30 ], "type": "FURNITURE", "width": 3, "height": 4, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_SAND_DECO_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 200, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 50, 30 ] } } } ================================================ FILE: blocks/furnitures/stabs/stab_hanging_tainted.json ================================================ { "block": { "stab_hanging_tainted": { "textureData": "tainted_stab_hanging.png", "color": [ 108, 65, 156 ], "type": "FURNITURE", "width": 2, "height": 3, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_TAINTED_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 128, 128, 128 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stabs/stab_tainted.json ================================================ { "block": { "stab_tainted": { "textureData": "tainted_stab.png", "color": [ 108, 65, 156 ], "type": "FURNITURE", "width": 2, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_TAINTED_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 128, 128, 128 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_andesite.json ================================================ { "block": { "stalactite_andesite": { "textureData": "andesite_stalactite.png", "color": [ 111, 111, 135 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_ANDESITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 111, 111, 135 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_desert.json ================================================ { "block": { "stalactite_desert": { "textureData": "desert_stalactite.png", "color": [ 176, 162, 123 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_SAND_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 130, 100 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_diorite.json ================================================ { "block": { "stalactite_diorite": { "textureData": "diorite_stalactite.png", "color": [ 118, 118, 118 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_DIORITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 118, 118, 118 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_granite.json ================================================ { "block": { "stalactite_granite": { "textureData": "granite_stalactite.png", "color": [ 111, 81, 69 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_GRANITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 111, 81, 69 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_andesite.json ================================================ { "block": { "stalactite_hanging_andesite": { "textureData": "andesite_stalactite_hanging.png", "color": [ 111, 111, 135 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_ANDESITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 111, 111, 135 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_desert.json ================================================ { "block": { "stalactite_hanging_desert": { "textureData": "desert_stalactite_hanging.png", "color": [ 176, 162, 123 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_SAND_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 160, 140 ], "preset": "Stalactite" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_diorite.json ================================================ { "block": { "stalactite_hanging_diorite": { "textureData": "diorite_stalactite_hanging.png", "color": [ 118, 118, 118 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_DIORITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 118, 118, 118 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_granite.json ================================================ { "block": { "stalactite_hanging_granite": { "textureData": "granite_stalactite_hanging.png", "color": [ 111, 81, 69 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_GRANITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 111, 81, 69 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_ice.json ================================================ { "block": { "stalactite_hanging_ice": { "textureData": "ice_stalactite_hanging.png", "color": [ 124, 202, 235 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_ICE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 180, 220 ], "preset": "Stalactite" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_small_andesite.json ================================================ { "block": { "stalactite_hanging_small_andesite": { "textureData": "andesite_small_stalactite_hanging.png", "color": [ 111, 111, 135 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_ANDESITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 111, 111, 135 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_small_desert.json ================================================ { "block": { "stalactite_hanging_small_desert": { "textureData": "desert_small_stalactite_hanging.png", "color": [ 176, 162, 123 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_SAND_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 160, 140 ], "preset": "Stalactite" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_small_diorite.json ================================================ { "block": { "stalactite_hanging_small_diorite": { "textureData": "diorite_small_stalactite_hanging.png", "color": [ 118, 118, 118 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_DIORITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 118, 118, 118 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_small_granite.json ================================================ { "block": { "stalactite_hanging_small_granite": { "textureData": "granite_small_stalactite_hanging.png", "color": [ 111, 81, 69 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_GRANITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 111, 81, 69 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_small_ice.json ================================================ { "block": { "stalactite_hanging_small_ice": { "textureData": "ice_small_stalactite_hanging.png", "color": [ 124, 202, 235 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_ICE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 180, 220 ], "preset": "Stalactite" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_small_stone.json ================================================ { "block": { "stalactite_hanging_small_stone": { "textureData": "stone_small_stalactite_hanging.png", "color": [ 128, 128, 128 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_STONE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 128, 128, 128 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_small_tainted.json ================================================ { "block": { "stalactite_hanging_small_tainted": { "textureData": "tainted_small_stalactite_hanging.png", "color": [ 108, 65, 156 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_TAINTED_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 100, 140 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_small_waste.json ================================================ { "block": { "stalactite_hanging_small_waste": { "textureData": "waste_small_stalactite_hanging.png", "color": [ 104, 46, 23 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_WASTE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 104, 46, 23 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_stone.json ================================================ { "block": { "stalactite_hanging_stone": { "textureData": "stone_stalactite_hanging.png", "color": [ 128, 128, 128 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_STONE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 128, 128, 128 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_tainted.json ================================================ { "block": { "stalactite_hanging_tainted": { "textureData": "tainted_stalactite_hanging.png", "color": [ 108, 65, 156 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_TAINTED_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 100, 140 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_hanging_waste.json ================================================ { "block": { "stalactite_hanging_waste": { "textureData": "waste_stalactite_hanging.png", "color": [ 104, 46, 23 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "placeCheck": "PLACE_WASTE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 104, 46, 23 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_ice.json ================================================ { "block": { "stalactite_ice": { "textureData": "ice_stalactite.png", "color": [ 124, 202, 235 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_ICE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 180, 220 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_small_andesite.json ================================================ { "block": { "stalactite_small_andesite": { "textureData": "andesite_small_stalactite.png", "color": [ 111, 111, 135 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_ANDESITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 111, 111, 135 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_small_desert.json ================================================ { "block": { "stalactite_small_desert": { "textureData": "desert_small_stalactite.png", "color": [ 176, 162, 123 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_SAND_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 130, 100 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_small_diorite.json ================================================ { "block": { "stalactite_small_diorite": { "textureData": "diorite_small_stalactite.png", "color": [ 118, 118, 118 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_DIORITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 118, 118, 118 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_small_granite.json ================================================ { "block": { "stalactite_small_granite": { "textureData": "granite_small_stalactite.png", "color": [ 111, 81, 69 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_GRANITE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 111, 81, 69 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_small_ice.json ================================================ { "block": { "stalactite_small_ice": { "textureData": "ice_small_stalactite.png", "color": [ 124, 202, 235 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_ICE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 180, 220 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_small_stone.json ================================================ { "block": { "stalactite_small_stone": { "textureData": "stone_small_stalactite.png", "color": [ 128, 128, 128 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_STONE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 128, 128, 128 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_small_tainted.json ================================================ { "block": { "stalactite_small_tainted": { "textureData": "tainted_small_stalactite.png", "color": [ 108, 65, 156 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_TAINTED_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 100, 140 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_small_waste.json ================================================ { "block": { "stalactite_small_waste": { "textureData": "waste_small_stalactite.png", "color": [ 104, 46, 23 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_WASTE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 104, 46, 23 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_stone.json ================================================ { "block": { "stalactite_stone": { "textureData": "stone_stalactite.png", "color": [ 128, 128, 128 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_STONE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 128, 128, 128 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_tainted.json ================================================ { "block": { "stalactite_tainted": { "textureData": "tainted_stalactite.png", "color": [ 108, 65, 156 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_TAINTED_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 100, 140 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stalactites/stalactite_waste.json ================================================ { "block": { "stalactite_waste": { "textureData": "waste_stalactite.png", "color": [ 104, 46, 23 ], "type": "FURNITURE", "width": 1, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_WASTE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 104, 46, 23 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stone_decoses/stone_decos_ice.json ================================================ { "block": { "stone_decos_ice": { "textureData": "stone_decos_ice.png", "color": [ 124, 202, 235 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_ICE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 170, 200 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stone_decoses/stone_decos_mossy.json ================================================ { "block": { "stone_decos_mossy": { "textureData": "stone_decos_mossy.png", "color": [ 106, 66, 55 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 140, 110 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stone_decoses/stone_decos_normal.json ================================================ { "block": { "stone_decos_normal": { "textureData": "stone_decos.png", "color": [ 128, 128, 128 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 128, 128, 128 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stone_decoses/stone_decos_tainted.json ================================================ { "block": { "stone_decos_tainted": { "textureData": "stone_decos_tainted.png", "color": [ 108, 65, 156 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_TAINTED_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 60, 140 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stone_decoses/stone_decos_waste.json ================================================ { "block": { "stone_decos_waste": { "textureData": "stone_decos_waste.png", "color": [ 100, 50, 30 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 50, 30 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stone_pillars/stone_pillar_desert.json ================================================ { "block": { "stone_pillar_desert": { "textureData": "stone_pillar_desert.png", "type": "FURNITURE", "width": 2, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_SAND_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 150, 160, 110 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stone_pillars/stone_pillar_ice.json ================================================ { "block": { "stone_pillar_ice": { "textureData": "stone_pillar_ice.png", "color": [ 128, 128, 128 ], "type": "FURNITURE", "width": 2, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_ICE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 200, 255 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stone_pillars/stone_pillar_normal.json ================================================ { "block": { "stone_pillar_normal": { "textureData": "stone_pillar.png", "type": "FURNITURE", "width": 2, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_STONE_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 128, 128, 128 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/stone_pillars/stone_pillar_tainted.json ================================================ { "block": { "stone_pillar_tainted": { "textureData": "stone_pillar_tainted.png", "color": [ 108, 65, 156 ], "type": "FURNITURE", "width": 2, "height": 3, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_TAINTED_DECO_CHECK", "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 80, 50, 120 ], "preset": "RandomDisplay" } } } ================================================ FILE: blocks/furnitures/tables/table_acacia.json ================================================ { "block": { "table_acacia": { "textureData": "wooden_table_acacia.png", "color": [ 190, 125, 90 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 180, 100, 60 ] } }, "item": { "table_acacia": { "type": "BLOCKS", "iconTextureData": "wooden_table_acacia.png", "group": "GROUP_WOODEN_TABLE", "blockId": "table_acacia", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/tables/table_birch.json ================================================ { "block": { "table_birch": { "textureData": "wooden_table_birch.png", "color": [ 220, 210, 160 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 200, 130 ] } }, "item": { "table_birch": { "type": "BLOCKS", "iconTextureData": "wooden_table_birch.png", "group": "GROUP_WOODEN_TABLE", "blockId": "table_birch", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/tables/table_dark_oak.json ================================================ { "block": { "table_dark_oak": { "textureData": "wooden_table_dark_oak.png", "color": [ 106, 86, 66 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 30, 10 ] } }, "item": { "table_dark_oak": { "type": "BLOCKS", "iconTextureData": "wooden_table_dark_oak.png", "group": "GROUP_WOODEN_TABLE", "blockId": "table_dark_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/tables/table_jungle.json ================================================ { "block": { "table_jungle": { "textureData": "wooden_table_jungle.png", "color": [ 137, 110, 92 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 70, 50 ] } }, "item": { "table_jungle": { "type": "BLOCKS", "iconTextureData": "wooden_table_jungle.png", "group": "GROUP_WOODEN_TABLE", "blockId": "table_jungle", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/tables/table_nether.json ================================================ { "block": { "table_nether": { "textureData": "table_nether.png", "color": [ 72, 29, 34 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": false, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 72, 29, 34 ] } }, "item": { "table_nether": { "type": "BLOCKS", "iconTextureData": "table_nether.png", "group": "GROUP_WOODEN_TABLE", "blockId": "table_nether", "antiLava": true } } } ================================================ FILE: blocks/furnitures/tables/table_oak.json ================================================ { "block": { "table_oak": { "textureData": "wooden_table_oak.png", "color": [ 167, 136, 79 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 173, 137, 80 ] } }, "item": { "table_oak": { "type": "BLOCKS", "iconTextureData": "wooden_table_oak.png", "group": "GROUP_WOODEN_TABLE", "blockId": "table_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/tables/table_palm.json ================================================ { "block": { "table_palm": { "textureData": "wooden_table_palm.png", "color": [ 182, 141, 86 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 182, 141, 86 ] } }, "item": { "table_palm": { "type": "BLOCKS", "iconTextureData": "wooden_table_palm.png", "group": "GROUP_WOODEN_TABLE", "blockId": "table_palm", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/tables/table_spruce.json ================================================ { "block": { "table_spruce": { "textureData": "wooden_table_spruce.png", "color": [ 144, 119, 93 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 90, 60 ] } }, "item": { "table_spruce": { "type": "BLOCKS", "iconTextureData": "wooden_table_spruce.png", "group": "GROUP_WOODEN_TABLE", "blockId": "table_spruce", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/tables/table_tainted.json ================================================ { "block": { "table_tainted": { "textureData": "wooden_table_tainted.png", "color": [ 89, 85, 107 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 89, 85, 107 ] } }, "item": { "table_tainted": { "type": "BLOCKS", "iconTextureData": "wooden_table_tainted.png", "group": "GROUP_WOODEN_TABLE", "blockId": "table_tainted", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/tables/table_volcano.json ================================================ { "block": { "table_volcano": { "textureData": "wooden_table_volcano.png", "color": [ 200, 60, 60 ], "type": "FURNITURE", "width": 3, "height": 2, "collision": "PLATFORM", "attach": "BOTTOM", "attachable": "TOP", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 140, "slipperiness": 1.0, "isKilledByLava": true, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 60, 60 ] } }, "item": { "table_volcano": { "type": "BLOCKS", "iconTextureData": "wooden_table_volcano.png", "group": "GROUP_WOODEN_TABLE", "blockId": "table_volcano", "fuelTime": 60 } } } ================================================ FILE: blocks/furnitures/tentacles/flesh_tentacle.json ================================================ { "block": { "flesh_tentacle": { "textureData": "flesh_tentacle.png", "color": [ 131, 37, 34 ], "type": "FURNITURE", "width": 2, "height": 8, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 300, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": false, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 131, 37, 34 ], "animation": [ { "animationId": 0, "frameRandom": true, "frameStart": 0, "frameCount": 4, "shake": true, "shakeCenterX": 16, "shakeCenterY": 128, "shakePeriod": 256, "shakeAngle": 0.1 } ] } } } ================================================ FILE: blocks/furnitures/tentacles/flesh_tentacle_hanging.json ================================================ { "block": { "flesh_tentacle_hanging": { "textureData": "flesh_tentacle_hanging.png", "color": [ 131, 37, 34 ], "type": "FURNITURE", "width": 2, "height": 8, "collision": "NONE", "attach": "TOP", "attachable": "NONE", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 300, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": false, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 131, 37, 34 ], "animation": [ { "animationId": 0, "frameRandom": true, "frameStart": 0, "frameCount": 4, "shake": true, "shakeCenterX": 16, "shakeCenterY": 0, "shakePeriod": 256, "shakeAngle": 0.1 } ] } } } ================================================ FILE: blocks/furnitures/torches/blue_torch.json ================================================ { "block": { "blue_torch": { "textureData": "torch.png", "color": [ 143, 115, 73 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TORCH", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isFragile": true, "isKilledByLava": true, "isNoWater": true, "modTextureId": "TORCH_FIRE_BLUE", "isLighting": true, "lightColor": [ 20, 0, 0, 32 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "isFlash": true, "flashTime": 128, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 100, 40 ], "exParticle": "torch_particle", "preset": "Torch", "covers": [ { "modTextureId": "torch_fire_blue", "offsetX": 0, "offsetY": -14 } ] } }, "item": { "blue_torch": { "type": "BLOCKS", "iconTextureData": "blue_torch_icon.png", "textureData": "torch_entity.png", "group": "GROUP_TORCH", "blockId": "blue_torch", "isHandLight": true, "entityWidth": 8, "entityHeight": 16, "handX": 4, "handY": 14, "firePoints": [[4,0]] } } } ================================================ FILE: blocks/furnitures/torches/end_rod.json ================================================ { "block": { "end_rod": { "textureData": "end_rod.png", "color": [ 205, 192, 177 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TORCH", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isFragile": true, "isKilledByLava": true, "isNoWater": false, "isLighting": true, "lightColor": [ 32, 0, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "isFlash": true, "flashTime": 128, "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 205, 192, 177 ], "exParticle": "end_rod_particle", "preset": "EndRod" } }, "item": { "end_rod": { "type": "BLOCKS", "iconTextureData": "end_rod_icon.png", "group": "GROUP_LIGHTING", "blockId": "end_rod" } } } ================================================ FILE: blocks/furnitures/torches/green_torch.json ================================================ { "block": { "green_torch": { "textureData": "torch.png", "color": [ 143, 115, 73 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TORCH", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isFragile": true, "isKilledByLava": true, "isNoWater": true, "modTextureId": "TORCH_FIRE_GREEN", "isLighting": true, "lightColor": [ 20, 0, 32, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "isFlash": true, "flashTime": 128, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 100, 40 ], "exParticle": "torch_particle", "preset": "Torch", "covers": [ { "modTextureId": "torch_fire_green", "offsetX": 0, "offsetY": -14 } ] } }, "item": { "green_torch": { "type": "BLOCKS", "iconTextureData": "green_torch_icon.png", "textureData": "torch_entity.png", "group": "GROUP_TORCH", "blockId": "green_torch", "isHandLight": true, "entityWidth": 8, "entityHeight": 16, "handX": 4, "handY": 14, "firePoints": [[4,0]] } } } ================================================ FILE: blocks/furnitures/torches/red_torch.json ================================================ { "block": { "red_torch": { "textureData": "torch.png", "color": [ 143, 115, 73 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TORCH", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isFragile": true, "isKilledByLava": true, "isNoWater": true, "isLighting": true, "lightColor": [ 24, 32, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "isFlash": true, "flashTime": 128, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 100, 40 ], "exParticle": "torch_particle", "preset": "Torch", "covers": [ { "modTextureId": "torch_fire_red", "offsetX": 0, "offsetY": -14 } ] } }, "item": { "red_torch": { "type": "BLOCKS", "iconTextureData": "red_torch_icon.png", "textureData": "torch_entity.png", "group": "GROUP_TORCH", "blockId": "red_torch", "isHandLight": true, "entityWidth": 8, "entityHeight": 16, "handX": 4, "handY": 14, "firePoints": [[4,0]] } } } ================================================ FILE: blocks/furnitures/torches/redstone_torch.json ================================================ { "block": { "redstone_torch": { "textureData": "torch.png", "color": [ 143, 115, 73 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TORCH", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isFragile": true, "isKilledByLava": true, "isNoWater": true, "modTextureId": "TORCH_REDSTONE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 100, 40 ], "exParticle": "torch_particle", "preset": "RedstoneTorch", "covers": [ { "modTextureId": "torch_redstone", "offsetX": 0, "offsetY": -14 } ] } }, "item": { "redstone_torch": { "type": "BLOCKS", "iconTextureData": "redstone_torch_icon.png", "group": "GROUP_LIGHTING", "blockId": "redstone_torch" } } } ================================================ FILE: blocks/furnitures/torches/torch.json ================================================ { "block": { "torch": { "textureData": "torch.png", "color": [ 110, 90, 57 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TORCH", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isFragile": true, "isKilledByLava": true, "isNoWater": true, "isLighting": true, "lightColor": [ 30, 0, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "isFlash": true, "flashTime": 128, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 100, 40 ], "exParticle": "torch_particle", "preset": "Torch", "covers": [ { "modTextureId": "torch_fire", "offsetX": 0, "offsetY": -14 } ] } }, "item": { "torch": { "ai": "Torch", "type": "BLOCKS", "iconTextureData": "torch_icon.png", "textureData": "torch_entity.png", "group": "GROUP_TORCH", "blockId": "torch", "fuelTime": 30, "isHandLight": true, "entityWidth": 8, "entityHeight": 16, "handX": 4, "handY": 14, "firePoints": [[4,0]] } } } ================================================ FILE: blocks/furnitures/torches/white_torch.json ================================================ { "block": { "white_torch": { "textureData": "torch.png", "color": [ 143, 115, 73 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TORCH", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isFragile": true, "isKilledByLava": true, "isNoWater": true, "modTextureId": "TORCH_FIRE_WHITE", "isLighting": true, "lightColor": [ 32, 24, 24, 24 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "isFlash": true, "flashTime": 128, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 100, 40 ], "exParticle": "torch_particle", "preset": "Torch", "covers": [ { "modTextureId": "torch_fire_white", "offsetX": 0, "offsetY": -14 } ] } }, "item": { "white_torch": { "type": "BLOCKS", "iconTextureData": "white_torch_icon.png", "textureData": "torch_entity.png", "group": "GROUP_TORCH", "blockId": "white_torch", "isHandLight": true, "entityWidth": 8, "entityHeight": 16, "handX": 4, "handY": 14, "firePoints": [[4,0]] } } } ================================================ FILE: blocks/furnitures/torches/yellow_torch.json ================================================ { "block": { "yellow_torch": { "textureData": "torch.png", "color": [ 143, 115, 73 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TORCH", "attachable": "NONE", "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "isFragile": true, "isKilledByLava": true, "isNoWater": true, "isLighting": true, "lightColor": [ 24, 32, 32, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "isFlash": true, "flashTime": 128, "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 100, 40 ], "exParticle": "torch_particle", "preset": "Torch", "covers": [ { "modTextureId": "torch_fire_yellow", "offsetX": 0, "offsetY": -14 } ] } }, "item": { "yellow_torch": { "type": "BLOCKS", "iconTextureData": "yellow_torch_icon.png", "textureData": "torch_entity.png", "group": "GROUP_TORCH", "blockId": "yellow_torch", "isHandLight": true, "entityWidth": 8, "entityHeight": 16, "handX": 4, "handY": 14, "firePoints": [[4,0]] } } } ================================================ FILE: blocks/furnitures/vines/eyeball_vine.json ================================================ { "block": { "eyeball_vine": { "textureData": "eyeball_vine.png", "color": [ 100, 55, 55 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "BOTTOM", "placeCheck": "PLACE_VINE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": false, "isDestroyByWeapon": false, "soundId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 100, 55, 55 ], "preset": "Vine" } } } ================================================ FILE: blocks/furnitures/vines/tainted_vine.json ================================================ { "block": { "tainted_vine": { "textureData": "tainted_vine.png", "color": [ 80, 40, 120 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "BOTTOM", "placeCheck": "PLACE_VINE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": true, "soundId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 80, 40, 120 ], "preset": "Vine" } } } ================================================ FILE: blocks/furnitures/vines/vine.json ================================================ { "block": { "vine": { "textureData": "vine.png", "color": [ 68, 110, 31 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "TOP", "attachable": "BOTTOM", "placeCheck": "PLACE_VINE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isFragile": true, "isDestroyByWeapon": true, "soundId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 92, 125, 53 ], "preset": "Vine" } } } ================================================ FILE: blocks/tiles/andesites/andesite.json ================================================ { "block": { "andesite": { "textureData": "andesite.png", "color": [ 102, 102, 117 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ANDESITE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 140, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 120, 120 ] } }, "item": { "andesite": { "type": "BLOCKS", "iconTextureData": "andesite_icon.png", "group": "GROUP_ANDESITE", "blockId": "andesite" } } } ================================================ FILE: blocks/tiles/andesites/andesite_polished.json ================================================ { "block": { "andesite_polished": { "textureData": "andesite_polished.png", "color": [ 133, 133, 156 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 130, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 120, 120 ] } }, "item": { "andesite_polished": { "type": "BLOCKS", "iconTextureData": "andesite_polished_icon.png", "group": "GROUP_ANDESITE", "blockId": "andesite_polished" } } } ================================================ FILE: blocks/tiles/auroras/aurora_block.json ================================================ { "block": { "aurora_block": { "textureData": "aurora_block.png", "color": [ 100, 200, 200 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "COBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "DIAMOND", "hardness": 150, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 200, 200 ], "hasColorWave": true } } } ================================================ FILE: blocks/tiles/auroras/aurora_pillar.json ================================================ { "block": { "aurora_pillar": { "textureData": "aurora_pillar.png", "color": [ 100, 200, 200 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 200, 200 ], "hasColorWave": true } } } ================================================ FILE: blocks/tiles/diorites/diorite.json ================================================ { "block": { "diorite": { "textureData": "diorite.png", "color": [ 144, 144, 144 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "DIORITE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 140, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 170, 170, 170 ] } }, "item": { "diorite": { "type": "BLOCKS", "iconTextureData": "diorite_icon.png", "group": "GROUP_DIORITE", "blockId": "diorite" } } } ================================================ FILE: blocks/tiles/diorites/diorite_polished.json ================================================ { "block": { "diorite_polished": { "textureData": "diorite_polished.png", "color": [ 210, 210, 210 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 140, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 170, 170, 170 ] } }, "item": { "diorite_polished": { "type": "BLOCKS", "iconTextureData": "diorite_polished_icon.png", "group": "GROUP_DIORITE", "blockId": "diorite_polished" } } } ================================================ FILE: blocks/tiles/ends/end_stone.json ================================================ { "block": { "end_stone": { "textureData": "end_stone.png", "color": [ 198, 198, 188 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ENDSTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 240, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 180, 180, 150 ] } }, "item": { "end_stone": { "type": "BLOCKS", "iconTextureData": "end_stone_icon.png", "group": "GROUP_ENDSTONE", "blockId": "end_stone", "onTest": true } } } ================================================ FILE: blocks/tiles/ends/end_stone_brick.json ================================================ { "block": { "end_stone_brick": { "textureData": "end_stone_brick.png", "color": [ 227, 227, 215 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 6, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 230, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 200, 180 ] } }, "item": { "end_stone_brick": { "type": "BLOCKS", "iconTextureData": "end_stone_brick_icon.png", "group": "GROUP_ENDSTONE_BRICK", "blockId": "end_stone_brick", "onTest": true } } } ================================================ FILE: blocks/tiles/fences/cobblestone_fence.json ================================================ { "block": { "cobblestone_fence": { "textureData": "cobblestone_fence.png", "color": [ 111, 111, 111 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "cobblestone_fence": { "type": "BLOCKS", "iconTextureData": "cobblestone_fence_icon.png", "group": "GROUP_STONE_FENCE", "blockId": "cobblestone_fence" } } } ================================================ FILE: blocks/tiles/fences/fence_acacia.json ================================================ { "block": { "fence_acacia": { "textureData": "fence_acacia.png", "color": [ 160, 105, 74 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 180, 100, 60 ] } }, "item": { "fence_acacia": { "type": "BLOCKS", "iconTextureData": "fence_acacia_icon.png", "group": "GROUP_WOODEN_FENCE", "blockId": "fence_acacia", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/fences/fence_birch.json ================================================ { "block": { "fence_birch": { "textureData": "fence_birch.png", "color": [ 218, 209, 155 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 200, 130 ] } }, "item": { "fence_birch": { "type": "BLOCKS", "iconTextureData": "fence_birch_icon.png", "group": "GROUP_WOODEN_FENCE", "blockId": "fence_birch", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/fences/fence_dark_oak.json ================================================ { "block": { "fence_dark_oak": { "textureData": "fence_dark_oak.png", "color": [ 100, 80, 60 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 30, 10 ] } }, "item": { "fence_dark_oak": { "type": "BLOCKS", "iconTextureData": "fence_dark_oak_icon.png", "group": "GROUP_WOODEN_FENCE", "blockId": "fence_dark_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/fences/fence_jungle.json ================================================ { "block": { "fence_jungle": { "textureData": "fence_jungle.png", "color": [ 134, 107, 90 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 70, 50 ] } }, "item": { "fence_jungle": { "type": "BLOCKS", "iconTextureData": "fence_jungle_icon.png", "group": "GROUP_WOODEN_FENCE", "blockId": "fence_jungle", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/fences/fence_nether.json ================================================ { "block": { "fence_nether": { "textureData": "fence_nether.png", "color": [ 90, 60, 70 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 90, 60, 70 ] } }, "item": { "fence_nether": { "type": "BLOCKS", "iconTextureData": "fence_nether_icon.png", "group": "GROUP_NETHER_FENCE", "blockId": "fence_nether" } } } ================================================ FILE: blocks/tiles/fences/fence_oak.json ================================================ { "block": { "fence_oak": { "textureData": "fence_oak.png", "color": [ 159, 132, 77 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 173, 137, 80 ] } }, "item": { "fence_oak": { "type": "BLOCKS", "iconTextureData": "fence_oak_icon.png", "group": "GROUP_WOODEN_FENCE", "blockId": "fence_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/fences/fence_palm.json ================================================ { "block": { "fence_palm": { "textureData": "fence_palm.png", "color": [ 182, 141, 86 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 182, 141, 86 ] } }, "item": { "fence_palm": { "type": "BLOCKS", "iconTextureData": "fence_palm_icon.png", "group": "GROUP_WOODEN_FENCE", "blockId": "fence_palm", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/fences/fence_spruce.json ================================================ { "block": { "fence_spruce": { "textureData": "fence_spruce.png", "color": [ 144, 119, 93 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 90, 60 ] } }, "item": { "fence_spruce": { "type": "BLOCKS", "iconTextureData": "fence_spruce_icon.png", "group": "GROUP_WOODEN_FENCE", "blockId": "fence_spruce", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/fences/fence_tainted.json ================================================ { "block": { "fence_tainted": { "textureData": "fence_tainted.png", "color": [ 89, 85, 107 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 89, 85, 107 ] } }, "item": { "fence_tainted": { "type": "BLOCKS", "iconTextureData": "fence_tainted_icon.png", "group": "GROUP_WOODEN_FENCE", "blockId": "fence_tainted", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/fences/fence_volcano.json ================================================ { "block": { "fence_volcano": { "textureData": "fence_volcano.png", "color": [ 200, 60, 60 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 60, 60 ] } }, "item": { "fence_volcano": { "type": "BLOCKS", "iconTextureData": "fence_volcano_icon.png", "group": "GROUP_WOODEN_FENCE", "blockId": "fence_volcano", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/fences/iron_bar.json ================================================ { "block": { "iron_bar": { "textureData": "iron_bar.png", "color": [ 100, 100, 100 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "BAR", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 200, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "iron_bar": { "type": "BLOCKS", "iconTextureData": "iron_bar_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "iron_bar" } } } ================================================ FILE: blocks/tiles/fences/mossy_cobblestone_fence.json ================================================ { "block": { "mossy_cobblestone_fence": { "textureData": "mossy_cobblestone_fence.png", "color": [ 73, 100, 77 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "FENCE", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "mossy_cobblestone_fence": { "type": "BLOCKS", "iconTextureData": "mossy_cobblestone_fence_icon.png", "group": "GROUP_STONE_FENCE", "blockId": "mossy_cobblestone_fence" } } } ================================================ FILE: blocks/tiles/fleshes/flesh_dirt.json ================================================ { "block": { "flesh_dirt": { "textureData": "flesh_dirt.png", "color": [ 120, 36, 40 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "FLESH_DIRT", "collision": "SOLID", "growGroup": "FLESH_GROUP", "hangGrowGroup": "FLESH_GROUP", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 90, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "hasGrassCover": true, "isRipen": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 36, 40 ], "preset": "GrowGrass", "covers": [ { "modTextureId": "flesh_grass", "offsetX": -8, "offsetY": -8 } ] } }, "item": { "flesh_dirt": { "type": "BLOCKS", "iconTextureData": "flesh_dirt_icon.png", "group": "GROUP_FLESH", "blockId": "flesh_dirt" } } } ================================================ FILE: blocks/tiles/fleshes/flesh_gut.json ================================================ { "block": { "flesh_gut": { "textureData": "flesh_gut.png", "color": [ 120, 36, 40 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "FLESH_GUT", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 90, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 36, 40 ] } }, "item": { "flesh_gut": { "type": "BLOCKS", "iconTextureData": "flesh_gut_icon.png", "group": "GROUP_FLESH", "blockId": "flesh_gut" } } } ================================================ FILE: blocks/tiles/fleshes/flesh_stone.json ================================================ { "block": { "flesh_stone": { "textureData": "flesh_stone.png", "color": [ 103, 29, 25 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "FLESH_STONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 180, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 103, 29, 25 ] } }, "item": { "flesh_stone": { "type": "BLOCKS", "iconTextureData": "flesh_stone_icon.png", "group": "GROUP_FLESH", "blockId": "flesh_stone" } } } ================================================ FILE: blocks/tiles/glasses/glass.json ================================================ { "block": { "glass": { "textureData": "glass.png", "color": [ 233, 233, 255 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 10, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 200, 200 ] } }, "item": { "glass": { "type": "BLOCKS", "iconTextureData": "glass_icon.png", "group": "GROUP_GLASS", "blockId": "glass", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_black.json ================================================ { "block": { "stained_glass_black": { "textureData": "stained_glass_black.png", "color": [ 99, 99, 99 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 0, 0, 0 ] } }, "item": { "stained_glass_black": { "type": "BLOCKS", "iconTextureData": "stained_glass_black_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_black", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_blue.json ================================================ { "block": { "stained_glass_blue": { "textureData": "stained_glass_blue.png", "color": [ 119, 129, 188 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 0, 0, 120 ] } }, "item": { "stained_glass_blue": { "type": "BLOCKS", "iconTextureData": "stained_glass_blue_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_blue", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_brown.json ================================================ { "block": { "stained_glass_brown": { "textureData": "stained_glass_brown.png", "color": [ 167, 133, 108 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 130, 100, 50 ] } }, "item": { "stained_glass_brown": { "type": "BLOCKS", "iconTextureData": "stained_glass_brown_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_brown", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_cyan.json ================================================ { "block": { "stained_glass_cyan": { "textureData": "stained_glass_cyan.png", "color": [ 88, 180, 180 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 0, 120, 120 ] } }, "item": { "stained_glass_cyan": { "type": "BLOCKS", "iconTextureData": "stained_glass_cyan_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_cyan", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_gray.json ================================================ { "block": { "stained_glass_gray": { "textureData": "stained_glass_gray.png", "color": [ 125, 125, 128 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 60, 60, 60 ] } }, "item": { "stained_glass_gray": { "type": "BLOCKS", "iconTextureData": "stained_glass_gray_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_gray", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_green.json ================================================ { "block": { "stained_glass_green": { "textureData": "stained_glass_green.png", "color": [ 144, 66, 92 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 0, 120, 0 ] } }, "item": { "stained_glass_green": { "type": "BLOCKS", "iconTextureData": "stained_glass_green_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_green", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_light_blue.json ================================================ { "block": { "stained_glass_light_blue": { "textureData": "stained_glass_light_blue.png", "color": [ 130, 215, 240 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 60, 90, 120 ] } }, "item": { "stained_glass_light_blue": { "type": "BLOCKS", "iconTextureData": "stained_glass_light_blue_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_light_blue", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_light_gray.json ================================================ { "block": { "stained_glass_light_gray": { "textureData": "stained_glass_light_gray.png", "color": [ 160, 166, 169 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 120, 100 ] } }, "item": { "stained_glass_light_gray": { "type": "BLOCKS", "iconTextureData": "stained_glass_light_gray_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_light_gray", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_lime.json ================================================ { "block": { "stained_glass_lime": { "textureData": "stained_glass_lime.png", "color": [ 171, 212, 151 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 50, 100, 0 ] } }, "item": { "stained_glass_lime": { "type": "BLOCKS", "iconTextureData": "stained_glass_lime_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_lime", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_magenta.json ================================================ { "block": { "stained_glass_magenta": { "textureData": "stained_glass_magenta.png", "color": [ 202, 109, 193 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 60, 120 ] } }, "item": { "stained_glass_magenta": { "type": "BLOCKS", "iconTextureData": "stained_glass_magenta_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_magenta", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_orange.json ================================================ { "block": { "stained_glass_orange": { "textureData": "stained_glass_orange.png", "color": [ 248, 116, 93 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 120, 100 ] } }, "item": { "stained_glass_orange": { "type": "BLOCKS", "iconTextureData": "stained_glass_orange_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_orange", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_pink.json ================================================ { "block": { "stained_glass_pink": { "textureData": "stained_glass_pink.png", "color": [ 212, 155, 188 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 130, 100, 100 ] } }, "item": { "stained_glass_pink": { "type": "BLOCKS", "iconTextureData": "stained_glass_pink_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_pink", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_purple.json ================================================ { "block": { "stained_glass_purple": { "textureData": "stained_glass_purple.png", "color": [ 90, 114, 204 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 60, 30, 120 ] } }, "item": { "stained_glass_purple": { "type": "BLOCKS", "iconTextureData": "stained_glass_purple_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_purple", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_red.json ================================================ { "block": { "stained_glass_red": { "textureData": "stained_glass_red.png", "color": [ 186, 100, 97 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 0, 0 ] } }, "item": { "stained_glass_red": { "type": "BLOCKS", "iconTextureData": "stained_glass_red_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_red", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_white.json ================================================ { "block": { "stained_glass_white": { "note": "各色玻璃 186:0-15", "textureData": "stained_glass_white.png", "color": [ 201, 208, 208 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 170, 150 ] } }, "item": { "stained_glass_white": { "type": "BLOCKS", "iconTextureData": "stained_glass_white_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_white", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/glasses/stained_glass_yellow.json ================================================ { "block": { "stained_glass_yellow": { "textureData": "stained_glass_yellow.png", "color": [ 252, 218, 96 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLASS", "collision": "SOLID", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 120, 0 ] } }, "item": { "stained_glass_yellow": { "type": "BLOCKS", "iconTextureData": "stained_glass_yellow_icon.png", "group": "GROUP_GLASS", "blockId": "stained_glass_yellow", "oreDictionary": [ "OD_GLASS" ] } } } ================================================ FILE: blocks/tiles/granites/granite.json ================================================ { "block": { "granite": { "textureData": "granite.png", "color": [ 127, 92, 48 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "GRANITE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 180, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 175, 137, 122 ] } }, "item": { "granite": { "type": "BLOCKS", "iconTextureData": "granite_icon.png", "group": "GROUP_GRANITE", "blockId": "granite" } } } ================================================ FILE: blocks/tiles/granites/granite_polished.json ================================================ { "block": { "granite_polished": { "textureData": "granite_polished.png", "color": [ 145, 112, 85 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 170, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 175, 137, 122 ] } }, "item": { "granite_polished": { "type": "BLOCKS", "iconTextureData": "granite_polished_icon.png", "group": "GROUP_GRANITE", "blockId": "granite_polished" } } } ================================================ FILE: blocks/tiles/ices/blue_ice.json ================================================ { "block": { "blue_ice": { "textureData": "blue_ice.png", "color": [ 114, 161, 247 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 2, "isLighting": true, "lightColor": [ 10, 0, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 0.2, "isLossyCollection": true, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 114, 161, 247 ] } }, "item": { "blue_ice": { "type": "BLOCKS", "iconTextureData": "blue_ice_icon.png", "group": "GROUP_SNOW_BRICK", "blockId": "blue_ice" } } } ================================================ FILE: blocks/tiles/ices/ice.json ================================================ { "block": { "ice": { "textureData": "ice.png", "color": [ 207, 207, 255 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 2, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 0.5, "isLossyCollection": true, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 170, 200, 255 ] } }, "item": { "ice": { "type": "BLOCKS", "iconTextureData": "ice_icon.png", "group": "GROUP_SNOW_BRICK", "blockId": "ice" } } } ================================================ FILE: blocks/tiles/ices/ice_brick.json ================================================ { "block": { "ice_brick": { "textureData": "ice_brick.png", "color": [ 80, 251, 251 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 6, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 140, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 30, 255, 255 ] } }, "item": { "ice_brick": { "type": "BLOCKS", "iconTextureData": "ice_brick_icon.png", "group": "GROUP_ICE_BRICK", "blockId": "ice_brick" } } } ================================================ FILE: blocks/tiles/ices/ice_cobblestone.json ================================================ { "block": { "ice_cobblestone": { "textureData": "ice_cobblestone.png", "color": [ 12, 200, 200 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ICECOBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 220, "slipperiness": 0.8, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 180, 220, 220 ] } }, "item": { "ice_cobblestone": { "type": "BLOCKS", "iconTextureData": "ice_cobblestone_icon.png", "group": "GROUP_ICE_COBBLESTONE", "blockId": "ice_cobblestone" } } } ================================================ FILE: blocks/tiles/ices/ice_packed.json ================================================ { "block": { "ice_packed": { "textureData": "ice_packed.png", "color": [ 190, 190, 255 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 2, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 0.6, "isLossyCollection": true, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 220, 240 ] } }, "item": { "ice_packed": { "type": "BLOCKS", "iconTextureData": "ice_packed_icon.png", "group": "GROUP_SNOW_BRICK", "blockId": "ice_packed" } } } ================================================ FILE: blocks/tiles/ices/ice_thin.json ================================================ { "block": { "ice_thin": { "textureData": "ice_thin.png", "color": [ 190, 190, 255 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 2, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 0.6, "isLossyCollection": true, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 220, 240 ], "preset": "IceSmelt" } } } ================================================ FILE: blocks/tiles/misc/bedrock.json ================================================ { "block": { "bedrock": { "textureData": "bedrock.png", "color": [ 77, 77, 77 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "DIAMOND", "hardness": 1000000000, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 77, 77, 77 ] } } } ================================================ FILE: blocks/tiles/misc/bone_block.json ================================================ { "block": { "bone_block": { "textureData": "bone_block.png", "color": [ 200, 200, 180 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "COBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 150, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 200, 170 ] } }, "item": { "bone_block": { "type": "BLOCKS", "iconTextureData": "bone_block_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "bone_block" } } } ================================================ FILE: blocks/tiles/misc/brick.json ================================================ { "block": { "brick": { "textureData": "brick.png", "color": [ 123, 51, 37 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 10, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 130, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 50, 36 ] } }, "item": { "brick": { "type": "BLOCKS", "iconTextureData": "brick_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "brick" } } } ================================================ FILE: blocks/tiles/misc/clay.json ================================================ { "block": { "clay": { "textureData": "clay.png", "color": [ 133, 133, 146 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "CLAY", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 80, "isChipCollection": true, "lossyItemId": "clay", "chipCount": 4, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "dirt", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 160, 160, 180 ] } }, "item": { "clay_block": { "type": "BLOCKS", "iconTextureData": "clay_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "clay" } } } ================================================ FILE: blocks/tiles/misc/coarse_dirt.json ================================================ { "block": { "coarse_dirt": { "textureData": "coarse_dirt.png", "color": [ 87, 63, 43 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "COARSE_DIRT", "collision": "SOLID", "growGroup": "NORMAL_GROUP", "hangGrowGroup": "NORMAL_GROUP", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "isLossyCollection": true, "lossyItemId": "dirt", "slipperiness": 1.0, "isKilledByLava": true, "gravity": false, "allowSlope": true, "isWallDark": true, "hasGrassCover": true, "isRipen": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 91, 64, 44 ], "preset": "GrowGrass", "covers": [ { "modTextureId": "grass", "offsetX": -8, "offsetY": -8 } ] } }, "item": { "coarse_dirt": { "type": "BLOCKS", "iconTextureData": "coarse_dirt_icon.png", "group": "GROUP_DIRT", "blockId": "coarse_dirt" } } } ================================================ FILE: blocks/tiles/misc/dirt.json ================================================ { "block": { "dirt": { "textureData": "dirt.png", "color": [ 90, 57, 43 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "DIRT", "collision": "SOLID", "growGroup": "NORMAL_GROUP", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "hasGrassCover": true, "isRipen": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 91, 64, 44 ], "preset": "GrowGrass", "covers": [ { "modTextureId": "grass", "offsetX": -8, "offsetY": -8 } ] } }, "item": { "dirt": { "type": "BLOCKS", "iconTextureData": "dirt_icon.png", "group": "GROUP_DIRT", "blockId": "dirt" } } } ================================================ FILE: blocks/tiles/misc/dried_kelp_block.json ================================================ { "block": { "dried_kelp_block": { "textureData": "dried_kelp_block.png", "color": [ 47, 59, 42 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 70, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 47, 59, 42 ] } }, "item": { "dried_kelp_block": { "type": "BLOCKS", "iconTextureData": "dried_kelp_block_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "dried_kelp_block", "fuelTime": 800 } } } ================================================ FILE: blocks/tiles/misc/farmland.json ================================================ { "block": { "farmland": { "textureData": "farmland.png", "color": [ 96, 68, 49 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "DIRT", "farmGroup": "FARMLAND_GROUP", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NO_GENERABLE", "isLossyCollection": true, "lossyItemId": "dirt", "soundGroupId": "stone", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 116, 80, 60 ], "preset": "Farmland" } }, "item": { "farmland": { "type": "BLOCKS", "iconTextureData": "farmland_icon.png", "group": "GROUP_DIRT", "blockId": "farmland" } } } ================================================ FILE: blocks/tiles/misc/gravel.json ================================================ { "block": { "gravel": { "textureData": "gravel.png", "color": [ 150, 130, 130 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GRAVEL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": true, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "chanceItemId": "flint", "chanceDrop": 0.4, "soundGroupId": "dirt", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "gravel": { "type": "BLOCKS", "iconTextureData": "gravel_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "gravel" } } } ================================================ FILE: blocks/tiles/misc/hay_bale.json ================================================ { "block": { "hay_bale": { "textureData": "hay_bale.png", "color": [ 205, 171, 0 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 70, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 200, 160, 0 ] } }, "item": { "hay_bale": { "type": "BLOCKS", "iconTextureData": "hay_bale_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "hay_bale" } } } ================================================ FILE: blocks/tiles/misc/obsidian.json ================================================ { "block": { "obsidian": { "textureData": "obsidian.png", "color": [ 28, 28, 60 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "OBSIDIAN", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "DIAMOND", "hardness": 1500, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 0, 0, 0 ] } }, "item": { "obsidian": { "type": "BLOCKS", "iconTextureData": "obsidian_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "obsidian", "antiLava": true } } } ================================================ FILE: blocks/tiles/misc/slime_block.json ================================================ { "block": { "slime_block": { "textureData": "slime_block.png", "color": [ 180, 240, 160 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "SLIME_BLOCK", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 70, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 100, 220, 160 ] } }, "item": { "slime_block": { "type": "BLOCKS", "iconTextureData": "slime_block_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "slime_block" } } } ================================================ FILE: blocks/tiles/misc/tnt.json ================================================ { "block": { "tnt": { "textureData": "tnt.png", "color": [ 148, 26, 22 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 1, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 20, "slipperiness": 1.0, "isFragile": true, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NO_GENERABLE", "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 200, 44, 44 ], "preset": "TNT" } }, "item": { "tnt": { "type": "BLOCKS", "iconTextureData": "tnt_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "tnt" } } } ================================================ FILE: blocks/tiles/mushrooms/brown_mushroom_block.json ================================================ { "block": { "brown_mushroom_block": { "textureData": "brown_mushroom_block.png", "color": [ 130, 100, 80 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 70, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 130, 100, 80 ] } }, "item": { "brown_mushroom_block": { "type": "BLOCKS", "iconTextureData": "brown_mushroom_block_icon.png", "group": "GROUP_MUSHROOM_BLOCK", "blockId": "brown_mushroom_block" } } } ================================================ FILE: blocks/tiles/mushrooms/mushroom_stem.json ================================================ { "block": { "mushroom_stem": { "textureData": "mushroom_stem.png", "color": [ 203, 172, 122 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "MUSHROOM", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 70, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 141, 141, 130 ] } }, "item": { "mushroom_stem": { "type": "BLOCKS", "iconTextureData": "mushroom_stem_icon.png", "group": "GROUP_MUSHROOM_BLOCK", "blockId": "mushroom_stem" } } } ================================================ FILE: blocks/tiles/mushrooms/mycelium.json ================================================ { "block": { "mycelium": { "textureData": "mycelium.png", "color": [ 123, 100, 100 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "DIRT", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "hasGrassCover": true, "isRipen": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 123, 100, 100 ], "preset": "GrowGrass", "covers": [ { "modTextureId": "mycelium_grass", "offsetX": -8, "offsetY": -8 } ] } }, "item": { "mycelium": { "type": "BLOCKS", "iconTextureData": "mycelium_icon.png", "group": "GROUP_MUSHROOM_BLOCK", "blockId": "mycelium" } } } ================================================ FILE: blocks/tiles/mushrooms/red_mushroom_block.json ================================================ { "block": { "red_mushroom_block": { "textureData": "red_mushroom_block.png", "color": [ 178, 28, 28 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 70, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 160, 20, 20 ] } }, "item": { "red_mushroom_block": { "type": "BLOCKS", "iconTextureData": "red_mushroom_block_icon.png", "group": "GROUP_MUSHROOM_BLOCK", "blockId": "red_mushroom_block" } } } ================================================ FILE: blocks/tiles/nethers/glowstone.json ================================================ { "block": { "glowstone": { "textureData": "glowstone.png", "color": [ 224, 200, 134 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "GLOWSTONE", "collision": "SOLID", "lightOpacity": 3, "isLighting": true, "lightColor": [ 26, 5, 5, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 120, "isChipCollection": true, "lossyItemId": "glowstone_dust", "chipCount": 3, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "glass", "stepSoundId": "step_cloth", "particleColor": [ 255, 255, 185, 87 ] } }, "item": { "glowstone": { "type": "BLOCKS", "iconTextureData": "glowstone_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "glowstone" } } } ================================================ FILE: blocks/tiles/nethers/nether_brick.json ================================================ { "block": { "nether_brick": { "textureData": "nether_brick.png", "color": [ 66, 24, 29 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 6, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 70, 40, 50 ] } }, "item": { "nether_brick_block": { "type": "BLOCKS", "iconTextureData": "nether_brick_icon.png", "group": "GROUP_NETHER_BRICK", "blockId": "nether_brick" } } } ================================================ FILE: blocks/tiles/nethers/netherrack.json ================================================ { "block": { "netherrack": { "textureData": "netherrack.png", "color": [ 38, 33, 30 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "NETHERRACK", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 90, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 57, 52, 46 ] } }, "item": { "netherrack": { "type": "BLOCKS", "iconTextureData": "netherrack_icon.png", "group": "GROUP_NETHER", "blockId": "netherrack" } } } ================================================ FILE: blocks/tiles/nethers/red_nether_brick.json ================================================ { "block": { "red_nether_brick": { "textureData": "red_nether_brick.png", "color": [ 80, 0, 0 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 6, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 0, 0 ] } }, "item": { "red_nether_brick": { "type": "BLOCKS", "iconTextureData": "red_nether_brick_icon.png", "group": "GROUP_NETHER_BRICK", "blockId": "red_nether_brick" } } } ================================================ FILE: blocks/tiles/nethers/soul_sand.json ================================================ { "block": { "soul_sand": { "textureData": "soul_sand.png", "color": [ 66, 53, 45 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "SOUL_SAND", "farmGroup": "SOULSAND_GROUP", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 80, "slipperiness": 1.5, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "sand", "stepSoundId": "step_sand", "particleColor": [ 255, 44, 33, 22 ], "preset": "SoulSand" } }, "item": { "soul_sand": { "type": "BLOCKS", "iconTextureData": "soul_sand_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "soul_sand" } } } ================================================ FILE: blocks/tiles/ore_blocks/block_coal.json ================================================ { "block": { "block_coal": { "textureData": "block_coal.png", "color": [ 55, 55, 55 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 33, 33, 33 ] } }, "item": { "block_coal": { "type": "BLOCKS", "iconTextureData": "block_coal_icon.png", "group": "GROUP_ORE_BLOCK", "blockId": "block_coal", "fuelTime": 1600 } } } ================================================ FILE: blocks/tiles/ore_blocks/block_diamond.json ================================================ { "block": { "block_diamond": { "textureData": "block_diamond.png", "color": [ 186, 230, 234 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "IRON", "hardness": 240, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 188, 233, 233 ] } }, "item": { "block_diamond": { "type": "BLOCKS", "iconTextureData": "block_diamond_icon.png", "group": "GROUP_ORE_BLOCK", "blockId": "block_diamond" } } } ================================================ FILE: blocks/tiles/ore_blocks/block_emerald.json ================================================ { "block": { "block_emerald": { "textureData": "block_emerald.png", "color": [ 76, 223, 107 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "IRON", "hardness": 180, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 54, 200, 88 ] } }, "item": { "block_emerald": { "type": "BLOCKS", "iconTextureData": "block_emerald_icon.png", "group": "GROUP_ORE_BLOCK", "blockId": "block_emerald" } } } ================================================ FILE: blocks/tiles/ore_blocks/block_gold.json ================================================ { "block": { "block_gold": { "textureData": "block_gold.png", "color": [ 255, 255, 0 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "IRON", "hardness": 180, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 222, 222, 0 ] } }, "item": { "block_gold": { "type": "BLOCKS", "iconTextureData": "block_gold_icon.png", "group": "GROUP_ORE_BLOCK", "blockId": "block_gold" } } } ================================================ FILE: blocks/tiles/ore_blocks/block_iron.json ================================================ { "block": { "block_iron": { "textureData": "block_iron.png", "color": [ 233, 233, 233 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 222, 222, 222 ] } }, "item": { "block_iron": { "type": "BLOCKS", "iconTextureData": "block_iron_icon.png", "group": "GROUP_ORE_BLOCK", "blockId": "block_iron" } } } ================================================ FILE: blocks/tiles/ore_blocks/block_lapis.json ================================================ { "block": { "block_lapis": { "textureData": "block_lapis.png", "color": [ 12, 18, 55 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 10, 20, 40 ] } }, "item": { "block_lapis": { "type": "BLOCKS", "iconTextureData": "block_lapis_icon.png", "group": "GROUP_ORE_BLOCK", "blockId": "block_lapis" } } } ================================================ FILE: blocks/tiles/ore_blocks/block_netherite.json ================================================ { "block": { "block_netherite": { "textureData": "block_netherite.png", "color": [ 58, 55, 58 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "DIAMOND", "hardness": 320, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 58, 55, 58 ] } }, "item": { "block_netherite": { "type": "BLOCKS", "iconTextureData": "block_netherite_icon.png", "group": "GROUP_ORE_BLOCK", "blockId": "block_netherite", "antiLava": true } } } ================================================ FILE: blocks/tiles/ore_blocks/block_quartz.json ================================================ { "block": { "block_quartz": { "textureData": "block_quartz.png", "color": [ 218, 214, 202 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 218, 214, 202 ] } }, "item": { "block_quartz": { "type": "BLOCKS", "iconTextureData": "block_quartz_icon.png", "group": "GROUP_ORE_BLOCK", "blockId": "block_quartz" } } } ================================================ FILE: blocks/tiles/ore_blocks/block_redstone.json ================================================ { "block": { "block_redstone": { "textureData": "block_redstone.png", "color": [ 222, 2, 2 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "IRON", "hardness": 140, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 66, 0, 0 ] } }, "item": { "block_redstone": { "type": "BLOCKS", "iconTextureData": "block_redstone_icon.png", "group": "GROUP_ORE_BLOCK", "blockId": "block_redstone" } } } ================================================ FILE: blocks/tiles/ores/ore_ancient_debris.json ================================================ { "block": { "ore_ancient_debris": { "textureData": "ore_ancient_debris.png", "color": [ 81, 57, 51 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_GOLD", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "DIAMOND", "hardness": 320, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 81, 57, 51 ], "exParticle": "ore_particle" } }, "item": { "ore_ancient_debris": { "type": "BLOCKS", "iconTextureData": "ore_ancient_debris_icon.png", "group": "GROUP_ORE", "blockId": "ore_ancient_debris", "antiLava": true } } } ================================================ FILE: blocks/tiles/ores/ore_coal.json ================================================ { "block": { "ore_coal": { "textureData": "ore_coal.png", "color": [ 40, 40, 40 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ORE_COAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "isChipCollection": true, "lossyItemId": "coal", "chipCount": 1, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 40, 40, 40 ] } }, "item": { "ore_coal": { "type": "BLOCKS", "iconTextureData": "ore_coal_icon.png", "group": "GROUP_ORE", "blockId": "ore_coal" } } } ================================================ FILE: blocks/tiles/ores/ore_copper.json ================================================ { "block": { "ore_copper": { "textureData": "ore_copper.png", "color": [ 128, 70, 30 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_GOLD", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 180, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 180, 100, 50 ], "exParticle": "ore_particle" } }, "item": { "ore_copper": { "type": "BLOCKS", "iconTextureData": "ore_copper_icon.png", "group": "GROUP_ORE", "blockId": "ore_copper" } } } ================================================ FILE: blocks/tiles/ores/ore_diamond.json ================================================ { "block": { "ore_diamond": { "textureData": "ore_diamond.png", "color": [ 160, 180, 220 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_DIAMOND", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "IRON", "hardness": 240, "isChipCollection": true, "lossyItemId": "diamond", "chipCount": 1, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 130, 150, 250 ], "exParticle": "ore_particle" } }, "item": { "ore_diamond": { "type": "BLOCKS", "iconTextureData": "ore_diamond_icon.png", "group": "GROUP_ORE", "blockId": "ore_diamond" } } } ================================================ FILE: blocks/tiles/ores/ore_emerald.json ================================================ { "block": { "ore_emerald": { "textureData": "ore_emerald.png", "color": [ 85, 149, 94 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_EMERALD", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "IRON", "hardness": 180, "isChipCollection": true, "lossyItemId": "emerald", "chipCount": 1, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 40, 220, 120 ], "exParticle": "ore_particle" } }, "item": { "ore_emerald": { "type": "BLOCKS", "iconTextureData": "ore_emerald_icon.png", "group": "GROUP_ORE", "blockId": "ore_emerald" } } } ================================================ FILE: blocks/tiles/ores/ore_gold.json ================================================ { "block": { "ore_gold": { "textureData": "ore_gold.png", "color": [ 210, 210, 160 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_GOLD", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "IRON", "hardness": 180, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 200, 160 ], "exParticle": "ore_particle" } }, "item": { "ore_gold": { "type": "BLOCKS", "iconTextureData": "ore_gold_icon.png", "group": "GROUP_ORE", "blockId": "ore_gold" } } } ================================================ FILE: blocks/tiles/ores/ore_iron.json ================================================ { "block": { "ore_iron": { "textureData": "ore_iron.png", "color": [ 165, 155, 105 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_IRON", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 160, 140, 120 ], "exParticle": "ore_particle" } }, "item": { "ore_iron": { "type": "BLOCKS", "iconTextureData": "ore_iron_icon.png", "group": "GROUP_ORE", "blockId": "ore_iron" } } } ================================================ FILE: blocks/tiles/ores/ore_lapis.json ================================================ { "block": { "ore_lapis": { "textureData": "ore_lapis.png", "color": [ 49, 106, 133 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 6, "type": "TILE", "group": "ORE_LAPIS", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 160, "isChipCollection": true, "lossyItemId": "lapis_lazuli", "chipCount": 3, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 30, 70, 180 ], "exParticle": "ore_particle" } }, "item": { "ore_lapis": { "type": "BLOCKS", "iconTextureData": "ore_lapis_icon.png", "group": "GROUP_ORE", "blockId": "ore_lapis" } } } ================================================ FILE: blocks/tiles/ores/ore_lead.json ================================================ { "block": { "ore_lead": { "textureData": "ore_lead.png", "color": [ 87, 103, 137 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_GOLD", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 180, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 60, 80, 100 ], "exParticle": "ore_particle" } }, "item": { "ore_lead": { "type": "BLOCKS", "iconTextureData": "ore_lead_icon.png", "group": "GROUP_ORE", "blockId": "ore_lead" } } } ================================================ FILE: blocks/tiles/ores/ore_nether_quartz.json ================================================ { "block": { "ore_nether_quartz": { "textureData": "ore_nether_quartz.png", "color": [ 235, 231, 228 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_LAPIS", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "isChipCollection": true, "lossyItemId": "quartz", "chipCount": 6, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 235, 231, 228 ], "exParticle": "ore_particle" } }, "item": { "ore_nether_quartz": { "type": "BLOCKS", "iconTextureData": "ore_nether_quartz_icon.png", "group": "GROUP_ORE", "blockId": "ore_nether_quartz" } } } ================================================ FILE: blocks/tiles/ores/ore_redstone.json ================================================ { "block": { "ore_redstone": { "textureData": "ore_redstone.png", "color": [ 156, 121, 121 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_REDSTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "IRON", "hardness": 140, "isChipCollection": true, "lossyItemId": "redstone", "chipCount": 4, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 250, 30, 30 ], "exParticle": "ore_particle" } }, "item": { "ore_redstone": { "type": "BLOCKS", "iconTextureData": "ore_redstone_icon.png", "group": "GROUP_ORE", "blockId": "ore_redstone" } } } ================================================ FILE: blocks/tiles/ores/ore_silver.json ================================================ { "block": { "ore_silver": { "textureData": "ore_silver.png", "color": [ 172, 172, 200 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_GOLD", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "IRON", "hardness": 180, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 160, 160, 200 ], "exParticle": "ore_particle" } }, "item": { "ore_silver": { "type": "BLOCKS", "iconTextureData": "ore_silver_icon.png", "group": "GROUP_ORE", "blockId": "ore_silver" } } } ================================================ FILE: blocks/tiles/ores/ore_tin.json ================================================ { "block": { "ore_tin": { "textureData": "ore_tin.png", "color": [ 110, 140, 110 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ORE_GOLD", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 180, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "tink", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 180, 222, 180 ], "exParticle": "ore_particle" } }, "item": { "ore_tin": { "type": "BLOCKS", "iconTextureData": "ore_tin_icon.png", "group": "GROUP_ORE", "blockId": "ore_tin" } } } ================================================ FILE: blocks/tiles/planks/plank_acacia.json ================================================ { "block": { "plank_acacia": { "textureData": "plank_acacia.png", "color": [ 190, 125, 90 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 180, 100, 60 ] } }, "item": { "acacia_plank": { "type": "BLOCKS", "iconTextureData": "plank_acacia_icon.png", "group": "GROUP_WOODEN_PLANK", "oreDictionary": [ "OD_WOODEN_PLANK" ], "blockId": "plank_acacia", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/planks/plank_birch.json ================================================ { "block": { "plank_birch": { "textureData": "plank_birch.png", "color": [ 220, 210, 160 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 200, 130 ] } }, "item": { "birch_plank": { "type": "BLOCKS", "iconTextureData": "plank_birch_icon.png", "group": "GROUP_WOODEN_PLANK", "oreDictionary": [ "OD_WOODEN_PLANK" ], "blockId": "plank_birch", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/planks/plank_dark_oak.json ================================================ { "block": { "plank_dark_oak": { "textureData": "plank_dark_oak.png", "color": [ 106, 86, 66 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 30, 10 ] } }, "item": { "dark_oak_plank": { "type": "BLOCKS", "iconTextureData": "plank_dark_oak_icon.png", "group": "GROUP_WOODEN_PLANK", "oreDictionary": [ "OD_WOODEN_PLANK" ], "blockId": "plank_dark_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/planks/plank_jungle.json ================================================ { "block": { "plank_jungle": { "textureData": "plank_jungle.png", "color": [ 137, 110, 92 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 70, 50 ] } }, "item": { "jungle_plank": { "type": "BLOCKS", "iconTextureData": "plank_jungle_icon.png", "group": "GROUP_WOODEN_PLANK", "oreDictionary": [ "OD_WOODEN_PLANK" ], "blockId": "plank_jungle", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/planks/plank_oak.json ================================================ { "block": { "plank_oak": { "textureData": "plank_oak.png", "color": [ 167, 136, 79 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 173, 137, 80 ] } }, "item": { "oak_plank": { "type": "BLOCKS", "iconTextureData": "plank_oak_icon.png", "group": "GROUP_WOODEN_PLANK", "oreDictionary": [ "OD_WOODEN_PLANK" ], "blockId": "plank_oak", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/planks/plank_palm.json ================================================ { "block": { "plank_palm": { "textureData": "plank_palm.png", "color": [ 182, 141, 86 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 182, 141, 86 ] } }, "item": { "palm_plank": { "type": "BLOCKS", "iconTextureData": "plank_palm_icon.png", "group": "GROUP_WOODEN_PLANK", "oreDictionary": [ "OD_WOODEN_PLANK" ], "blockId": "plank_palm", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/planks/plank_spruce.json ================================================ { "block": { "plank_spruce": { "textureData": "plank_spruce.png", "color": [ 144, 119, 93 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 90, 60 ] } }, "item": { "spruce_plank": { "type": "BLOCKS", "iconTextureData": "plank_spruce_icon.png", "group": "GROUP_WOODEN_PLANK", "oreDictionary": [ "OD_WOODEN_PLANK" ], "blockId": "plank_spruce", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/planks/plank_tainted.json ================================================ { "block": { "plank_tainted": { "textureData": "plank_tainted.png", "color": [ 89, 85, 107 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 89, 85, 107 ] } }, "item": { "tainted_plank": { "type": "BLOCKS", "iconTextureData": "plank_tainted_icon.png", "group": "GROUP_WOODEN_PLANK", "oreDictionary": [ "OD_WOODEN_PLANK" ], "blockId": "plank_tainted", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/planks/plank_volcano.json ================================================ { "block": { "plank_volcano": { "textureData": "plank_volcano.png", "color": [ 200, 60, 60 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 60, 60 ] } }, "item": { "volcano_plank": { "type": "BLOCKS", "iconTextureData": "plank_volcano_icon.png", "group": "GROUP_WOODEN_PLANK", "oreDictionary": [ "OD_WOODEN_PLANK" ], "blockId": "plank_volcano", "fuelTime": 60 } } } ================================================ FILE: blocks/tiles/platforms/platform_acacia.json ================================================ { "block": { "platform_acacia": { "textureData": "platform_acacia.png", "color": [ 190, 125, 90 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 180, 100, 60 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_acacia": { "type": "BLOCKS", "iconTextureData": "platform_acacia_icon.png", "group": "GROUP_WOODEN_PLATFORM", "blockId": "platform_acacia", "fuelTime": 60, "oreDictionary": [ "OD_WOODEN_PLATFORM" ] } } } ================================================ FILE: blocks/tiles/platforms/platform_birch.json ================================================ { "block": { "platform_birch": { "textureData": "platform_birch.png", "color": [ 208, 219, 156 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 200, 130 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_birch": { "type": "BLOCKS", "iconTextureData": "platform_birch_icon.png", "group": "GROUP_WOODEN_PLATFORM", "blockId": "platform_birch", "fuelTime": 60, "oreDictionary": [ "OD_WOODEN_PLATFORM" ] } } } ================================================ FILE: blocks/tiles/platforms/platform_dark_oak.json ================================================ { "block": { "platform_dark_oak": { "textureData": "platform_dark_oak.png", "color": [ 100, 80, 60 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 30, 10 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_dark_oak": { "type": "BLOCKS", "iconTextureData": "platform_dark_oak_icon.png", "group": "GROUP_WOODEN_PLATFORM", "blockId": "platform_dark_oak", "fuelTime": 60, "oreDictionary": [ "OD_WOODEN_PLATFORM" ] } } } ================================================ FILE: blocks/tiles/platforms/platform_end_stone.json ================================================ { "block": { "platform_end_stone": { "textureData": "platform_end_stone.png", "color": [ 223, 223, 209 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 223, 223, 209 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_end_stone": { "type": "BLOCKS", "iconTextureData": "platform_end_stone_icon.png", "group": "GROUP_PLATFORM", "blockId": "platform_end_stone" } } } ================================================ FILE: blocks/tiles/platforms/platform_jungle.json ================================================ { "block": { "platform_jungle": { "textureData": "platform_jungle.png", "color": [ 132, 105, 88 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 70, 50 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_jungle": { "type": "BLOCKS", "iconTextureData": "platform_jungle_icon.png", "group": "GROUP_WOODEN_PLATFORM", "blockId": "platform_jungle", "fuelTime": 60, "oreDictionary": [ "OD_WOODEN_PLATFORM" ] } } } ================================================ FILE: blocks/tiles/platforms/platform_nether_brick.json ================================================ { "block": { "platform_nether_brick": { "textureData": "platform_nether_brick.png", "color": [ 49, 17, 21 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 49, 17, 21 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_nether_brick": { "type": "BLOCKS", "iconTextureData": "platform_nether_brick_icon.png", "group": "GROUP_PLATFORM", "blockId": "platform_nether_brick" } } } ================================================ FILE: blocks/tiles/platforms/platform_oak.json ================================================ { "block": { "platform_oak": { "textureData": "platform_oak.png", "color": [ 159, 132, 77 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 173, 137, 80 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_oak": { "type": "BLOCKS", "iconTextureData": "platform_oak_icon.png", "group": "GROUP_WOODEN_PLATFORM", "blockId": "platform_oak", "fuelTime": 60, "oreDictionary": [ "OD_WOODEN_PLATFORM" ] } } } ================================================ FILE: blocks/tiles/platforms/platform_palm.json ================================================ { "block": { "platform_palm": { "textureData": "platform_palm.png", "color": [ 182, 142, 86 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 182, 142, 86 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_palm": { "type": "BLOCKS", "iconTextureData": "platform_palm_icon.png", "group": "GROUP_WOODEN_PLATFORM", "blockId": "platform_palm", "fuelTime": 60, "oreDictionary": [ "OD_WOODEN_PLATFORM" ] } } } ================================================ FILE: blocks/tiles/platforms/platform_prismarine.json ================================================ { "block": { "platform_prismarine": { "textureData": "platform_prismarine.png", "color": [ 105, 176, 169 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 105, 176, 169 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_prismarine": { "type": "BLOCKS", "iconTextureData": "platform_prismarine_icon.png", "group": "GROUP_PLATFORM", "blockId": "platform_prismarine" } } } ================================================ FILE: blocks/tiles/platforms/platform_prismarine_dark.json ================================================ { "block": { "platform_prismarine_dark": { "textureData": "platform_prismarine_dark.png", "color": [ 72, 112, 97 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 72, 112, 97 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_prismarine_dark": { "type": "BLOCKS", "iconTextureData": "platform_prismarine_dark_icon.png", "group": "GROUP_PLATFORM", "blockId": "platform_prismarine_dark" } } } ================================================ FILE: blocks/tiles/platforms/platform_purpur.json ================================================ { "block": { "platform_purpur": { "textureData": "platform_purpur.png", "color": [ 188, 125, 188 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 188, 125, 188 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_purpur": { "type": "BLOCKS", "iconTextureData": "platform_purpur_icon.png", "group": "GROUP_PLATFORM", "blockId": "platform_purpur" } } } ================================================ FILE: blocks/tiles/platforms/platform_quartz.json ================================================ { "block": { "platform_quartz": { "textureData": "platform_quartz.png", "color": [ 235, 231, 228 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 235, 231, 228 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_quartz": { "type": "BLOCKS", "iconTextureData": "platform_quartz_icon.png", "group": "GROUP_PLATFORM", "blockId": "platform_quartz" } } } ================================================ FILE: blocks/tiles/platforms/platform_red_sand_stone.json ================================================ { "block": { "platform_red_sand_stone": { "textureData": "platform_red_sand_stone.png", "color": [ 200, 100, 100 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 100, 100 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_red_sand_stone": { "type": "BLOCKS", "iconTextureData": "platform_red_sand_stone_icon.png", "group": "GROUP_PLATFORM", "blockId": "platform_red_sand_stone" } } } ================================================ FILE: blocks/tiles/platforms/platform_sandstone.json ================================================ { "block": { "platform_sandstone": { "textureData": "platform_sandstone.png", "color": [ 223, 223, 160 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 223, 223, 160 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_sandstone": { "type": "BLOCKS", "iconTextureData": "platform_sandstone_icon.png", "group": "GROUP_PLATFORM", "blockId": "platform_sandstone" } } } ================================================ FILE: blocks/tiles/platforms/platform_spruce.json ================================================ { "block": { "platform_spruce": { "textureData": "platform_spruce.png", "color": [ 144, 119, 93 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 90, 60 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_spruce": { "type": "BLOCKS", "iconTextureData": "platform_spruce_icon.png", "group": "GROUP_WOODEN_PLATFORM", "blockId": "platform_spruce", "fuelTime": 60, "oreDictionary": [ "OD_WOODEN_PLATFORM" ] } } } ================================================ FILE: blocks/tiles/platforms/platform_stone_brick.json ================================================ { "block": { "platform_stone_brick": { "textureData": "platform_stone_brick.png", "color": [ 122, 122, 122 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 122, 122, 122 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_stone_brick": { "type": "BLOCKS", "iconTextureData": "platform_stone_brick_icon.png", "group": "GROUP_PLATFORM", "blockId": "platform_stone_brick" } } } ================================================ FILE: blocks/tiles/platforms/platform_tainted.json ================================================ { "block": { "platform_tainted": { "textureData": "platform_tainted.png", "color": [ 89, 85, 107 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 89, 85, 107 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_tainted": { "type": "BLOCKS", "iconTextureData": "platform_tainted_icon.png", "group": "GROUP_WOODEN_PLATFORM", "blockId": "platform_tainted", "fuelTime": 60, "oreDictionary": [ "OD_WOODEN_PLATFORM" ] } } } ================================================ FILE: blocks/tiles/platforms/platform_volcano.json ================================================ { "block": { "platform_volcano": { "textureData": "platform_volcano.png", "color": [ 200, 60, 60 ], "renderMode": "RENDER_PLATEFORM", "type": "TILE", "group": "PLATFORM", "collision": "PLATFORM", "lightOpacity": 1, "lightTransparent": true, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 60, 60 ], "isBackground": true, "isNoLinkVertical": true } }, "item": { "platform_volcano": { "type": "BLOCKS", "iconTextureData": "platform_volcano_icon.png", "group": "GROUP_WOODEN_PLATFORM", "blockId": "platform_volcano", "fuelTime": 60, "oreDictionary": [ "OD_WOODEN_PLATFORM" ] } } } ================================================ FILE: blocks/tiles/prismarines/prismarine.json ================================================ { "block": { "prismarine": { "textureData": "prismarine.png", "color": [ 140, 150, 170 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "PRISMARINE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 200, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 150, 170 ] } }, "item": { "prismarine": { "type": "BLOCKS", "iconTextureData": "prismarine_icon.png", "group": "GROUP_PRISMARINE", "blockId": "prismarine" } } } ================================================ FILE: blocks/tiles/prismarines/prismarine_brick.json ================================================ { "block": { "prismarine_brick": { "textureData": "prismarine_brick.png", "color": [ 133, 190, 180 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ANDESITE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 210, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 188, 188 ] } }, "item": { "prismarine_brick": { "type": "BLOCKS", "iconTextureData": "prismarine_brick_icon.png", "group": "GROUP_PRISMARINE", "blockId": "prismarine_brick" } } } ================================================ FILE: blocks/tiles/prismarines/prismarine_dark.json ================================================ { "block": { "prismarine_dark": { "textureData": "prismarine_dark.png", "color": [ 70, 112, 97 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 220, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 144, 144 ] } }, "item": { "prismarine_dark": { "type": "BLOCKS", "iconTextureData": "prismarine_dark_icon.png", "group": "GROUP_PRISMARINE", "blockId": "prismarine_dark" } } } ================================================ FILE: blocks/tiles/prismarines/prismarine_mud.json ================================================ { "block": { "prismarine_mud": { "textureData": "prismarine_mud.png", "color": [ 81, 132, 126 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "PRISMARINE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 200, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 188, 188 ] } }, "item": { "prismarine_mud": { "type": "BLOCKS", "iconTextureData": "prismarine_mud_icon.png", "group": "GROUP_PRISMARINE", "blockId": "prismarine_mud" } } } ================================================ FILE: blocks/tiles/prismarines/sea_lantern.json ================================================ { "block": { "sea_lantern": { "textureData": "sea_lantern.png", "color": [ 210, 220, 210 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 2, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "isLighting": true, "lightColor": [ 32, 0, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "glass", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 200, 200 ] } }, "item": { "sea_lantern": { "type": "BLOCKS", "iconTextureData": "sea_lantern_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "sea_lantern" } } } ================================================ FILE: blocks/tiles/purpurs/purpur_block.json ================================================ { "block": { "purpur_block": { "textureData": "purpur_block.png", "color": [ 177, 105, 177 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 220, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 150, 100, 150 ] } }, "item": { "purpur_block": { "type": "BLOCKS", "iconTextureData": "purpur_block_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "purpur_block" } } } ================================================ FILE: blocks/tiles/red_sands/red_sand.json ================================================ { "block": { "red_sand": { "textureData": "red_sand.png", "color": [ 140, 62, 20 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "REDSAND", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 70, "slipperiness": 1.0, "gravity": true, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "sand", "stepSoundId": "step_sand", "particleColor": [ 255, 200, 120, 50 ] } }, "item": { "red_sand": { "type": "BLOCKS", "iconTextureData": "red_sand_icon.png", "group": "GROUP_RED_SAND", "blockId": "red_sand" } } } ================================================ FILE: blocks/tiles/red_sands/red_sand_carved.json ================================================ { "block": { "red_sand_carved": { "textureData": "red_sand_carved.png", "color": [ 206, 20, 20 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 140, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 255, 40, 40 ] } }, "item": { "red_sand_carved": { "type": "BLOCKS", "iconTextureData": "red_sand_carved_icon.png", "group": "GROUP_RED_SAND", "blockId": "red_sand_carved" } } } ================================================ FILE: blocks/tiles/red_sands/red_sand_smooth.json ================================================ { "block": { "red_sand_smooth": { "textureData": "red_sand_smooth.png", "color": [ 206, 111, 111 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 6, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 140, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 255, 40, 40 ] } }, "item": { "red_sand_smooth": { "type": "BLOCKS", "iconTextureData": "red_sand_smooth_icon.png", "group": "GROUP_RED_SAND", "blockId": "red_sand_smooth" } } } ================================================ FILE: blocks/tiles/red_sands/red_sand_stone.json ================================================ { "block": { "red_sand_stone": { "textureData": "red_sand_stone.png", "color": [ 153, 73, 42 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "RED_SAND_STONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 160, 20, 20 ] } }, "item": { "red_sand_stone": { "type": "BLOCKS", "iconTextureData": "red_sand_stone_icon.png", "group": "GROUP_RED_SAND", "blockId": "red_sand_stone" } } } ================================================ FILE: blocks/tiles/sands/sand.json ================================================ { "block": { "sand": { "textureData": "sand.png", "color": [ 220, 210, 160 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "SAND", "farmGroup": "SAND_GROUP", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": true, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "sand", "stepSoundId": "step_sand", "particleColor": [ 255, 200, 200, 150 ] } }, "item": { "sand": { "type": "BLOCKS", "iconTextureData": "sand_icon.png", "group": "GROUP_SAND", "blockId": "sand" } } } ================================================ FILE: blocks/tiles/sands/sandstone.json ================================================ { "block": { "sandstone": { "textureData": "sandstone.png", "color": [ 167, 157, 114 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "SANDSTONE", "farmGroup": "SAND_GROUP", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 210, 200, 150 ] } }, "item": { "sandstone": { "type": "BLOCKS", "iconTextureData": "sandstone_icon.png", "group": "GROUP_SAND", "blockId": "sandstone" } } } ================================================ FILE: blocks/tiles/sands/sandstone_carved.json ================================================ { "block": { "sandstone_carved": { "textureData": "sandstone_carved.png", "color": [ 216, 208, 155 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 4, "type": "TILE", "group": "SANDSTONE_CARVED", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 140, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 220, 210, 160 ] } }, "item": { "sandstone_carved": { "type": "BLOCKS", "iconTextureData": "sandstone_carved_icon.png", "group": "GROUP_SAND", "blockId": "sandstone_carved" } } } ================================================ FILE: blocks/tiles/sands/sandstone_smooth.json ================================================ { "block": { "sandstone_smooth": { "textureData": "sandstone_smooth.png", "color": [ 229, 222, 176 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 6, "type": "TILE", "group": "SANDSTONE_SMOOTH", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 140, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 220, 210, 160 ] } }, "item": { "sandstone_smooth": { "type": "BLOCKS", "iconTextureData": "sandstone_smooth_icon.png", "group": "GROUP_SAND", "blockId": "sandstone_smooth" } } } ================================================ FILE: blocks/tiles/snows/snow.json ================================================ { "block": { "snow": { "textureData": "snow.png", "color": [ 128, 255, 255 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "SNOW", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "snow", "stepSoundGroupId": "step_snow", "particleColor": [ 255, 170, 255, 255 ] } }, "item": { "snow": { "type": "BLOCKS", "iconTextureData": "snow_icon.png", "group": "GROUP_SNOW", "blockId": "snow" } } } ================================================ FILE: blocks/tiles/snows/snow_brick.json ================================================ { "block": { "snow_brick": { "textureData": "snow_brick.png", "color": [ 210, 233, 233 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 6, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 150, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 111, 255, 255 ] } }, "item": { "snow_brick": { "type": "BLOCKS", "iconTextureData": "snow_brick_icon.png", "group": "GROUP_SNOW_BRICK", "blockId": "snow_brick" } } } ================================================ FILE: blocks/tiles/sponges/sponge.json ================================================ { "block": { "sponge": { "textureData": "sponge.png", "color": [ 207, 207, 148 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "SPONGE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 200, 200, 100 ], "preset": "Sponge" } }, "item": { "sponge": { "type": "BLOCKS", "iconTextureData": "sponge_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "sponge" } } } ================================================ FILE: blocks/tiles/sponges/wet_sponge.json ================================================ { "block": { "wet_sponge": { "textureData": "wet_sponge.png", "color": [ 170, 177, 138 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "SPONGE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 50, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 200, 200, 100 ], "preset": "WetSponge" } }, "item": { "wet_sponge": { "type": "BLOCKS", "iconTextureData": "wet_sponge_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "wet_sponge" } } } ================================================ FILE: blocks/tiles/stones/cobblestone.json ================================================ { "block": { "cobblestone": { "textureData": "cobblestone.png", "color": [ 114, 114, 114 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "COBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "cobblestone": { "type": "BLOCKS", "iconTextureData": "cobblestone_icon.png", "group": "GROUP_COBBLESTONE", "blockId": "cobblestone" } } } ================================================ FILE: blocks/tiles/stones/cobblestone_mossy.json ================================================ { "block": { "cobblestone_mossy": { "textureData": "cobblestone_mossy.png", "color": [ 88, 103, 66 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 180, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 40, 72, 40 ] } }, "item": { "cobblestone_mossy": { "type": "BLOCKS", "iconTextureData": "cobblestone_mossy_icon.png", "group": "GROUP_COBBLESTONE", "blockId": "cobblestone_mossy" } } } ================================================ FILE: blocks/tiles/stones/stone.json ================================================ { "block": { "stone": { "textureData": "stone.png", "color": [ 110, 110, 110 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "STONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "isLossyCollection": true, "lossyItemId": "cobblestone", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "stone": { "type": "BLOCKS", "iconTextureData": "stone_icon.png", "group": "GROUP_STONE", "blockId": "stone" } } } ================================================ FILE: blocks/tiles/stones/stone_brick.json ================================================ { "block": { "stone_brick": { "textureData": "stone_brick.png", "color": [ 118, 118, 118 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 6, "hasThinWall": true, "type": "TILE", "group": "STONE_BRICK", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "stone_brick": { "type": "BLOCKS", "iconTextureData": "stone_brick_icon.png", "group": "GROUP_STONE_BRICK", "blockId": "stone_brick" } } } ================================================ FILE: blocks/tiles/stones/stone_brick_carved.json ================================================ { "block": { "stone_brick_carved": { "textureData": "stone_brick_carved.png", "color": [ 118, 118, 118 ], "renderMode": "RENDER_BLOCK", "renderSortedInterval": 4, "type": "TILE", "group": "STONE_BRICK", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "stone_brick_carved": { "type": "BLOCKS", "iconTextureData": "stone_brick_carved_icon.png", "group": "GROUP_STONE_BRICK", "blockId": "stone_brick_carved" } } } ================================================ FILE: blocks/tiles/stones/stone_brick_cracked.json ================================================ { "block": { "stone_brick_cracked": { "textureData": "stone_brick_cracked.png", "color": [ 118, 118, 118 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 6, "hasThinWall": true, "type": "TILE", "group": "STONE_BRICK", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "stone_brick_cracked": { "type": "BLOCKS", "iconTextureData": "stone_brick_cracked_icon.png", "group": "GROUP_STONE_BRICK", "blockId": "stone_brick_cracked" } } } ================================================ FILE: blocks/tiles/stones/stone_brick_mossy.json ================================================ { "block": { "stone_brick_mossy": { "textureData": "stone_brick_mossy.png", "color": [ 110, 116, 97 ], "renderMode": "RENDER_BORDER_CUT", "renderSortedInterval": 6, "hasThinWall": true, "type": "TILE", "group": "STONE_BRICK", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 200, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "stone_brick_mossy": { "type": "BLOCKS", "iconTextureData": "stone_brick_mossy_icon.png", "group": "GROUP_STONE_BRICK", "blockId": "stone_brick_mossy" } } } ================================================ FILE: blocks/tiles/tainted/tainted_dirt.json ================================================ { "block": { "tainted_dirt": { "textureData": "tainted_dirt.png", "color": [ 60, 30, 90 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "DIRT", "growGroup": "TAINTED_GROUP", "hangGrowGroup": "TAINTED_GROUP", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "hasGrassCover": true, "isRipen": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 91, 64, 44 ], "preset": "GrowGrass", "covers": [ { "modTextureId": "tainted_grass", "offsetX": -8, "offsetY": -8 } ] } }, "item": { "tainted_dirt": { "type": "BLOCKS", "iconTextureData": "tainted_dirt_icon.png", "group": "GROUP_TAINTED", "blockId": "tainted_dirt" } } } ================================================ FILE: blocks/tiles/tainted/tainted_stone.json ================================================ { "block": { "tainted_stone": { "textureData": "tainted_stone.png", "color": [ 75, 52, 108 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "TAINTED_STONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 200, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "tainted_stone": { "type": "BLOCKS", "iconTextureData": "tainted_stone_icon.png", "group": "GROUP_TAINTED", "blockId": "tainted_stone" } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_black.json ================================================ { "block": { "terracotta_black": { "textureData": "terracotta_black.png", "color": [ 80, 80, 80 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 0, 0, 0 ] } }, "item": { "terracotta_black": { "type": "BLOCKS", "iconTextureData": "terracotta_black_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_black", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_blue.json ================================================ { "block": { "terracotta_blue": { "textureData": "terracotta_blue.png", "color": [ 111, 111, 172 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 0, 0, 120 ] } }, "item": { "terracotta_blue": { "type": "BLOCKS", "iconTextureData": "terracotta_blue_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_blue", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_brown.json ================================================ { "block": { "terracotta_brown": { "textureData": "terracotta_brown.png", "color": [ 172, 157, 141 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 130, 100, 50 ] } }, "item": { "terracotta_brown": { "type": "BLOCKS", "iconTextureData": "terracotta_brown_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_brown", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_cyan.json ================================================ { "block": { "terracotta_cyan": { "textureData": "terracotta_cyan.png", "color": [ 101, 168, 168 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 0, 120, 120 ] } }, "item": { "terracotta_cyan": { "type": "BLOCKS", "iconTextureData": "terracotta_cyan_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_cyan", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_gray.json ================================================ { "block": { "terracotta_gray": { "textureData": "terracotta_gray.png", "color": [ 144, 144, 144 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 60, 60, 60 ] } }, "item": { "terracotta_gray": { "type": "BLOCKS", "iconTextureData": "terracotta_gray_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_gray", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_green.json ================================================ { "block": { "terracotta_green": { "textureData": "terracotta_green.png", "color": [ 110, 172, 110 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 0, 120, 0 ] } }, "item": { "terracotta_green": { "type": "BLOCKS", "iconTextureData": "terracotta_green_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_green", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_light_blue.json ================================================ { "block": { "terracotta_light_blue": { "textureData": "terracotta_light_blue.png", "color": [ 141, 157, 172 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 60, 90, 120 ] } }, "item": { "terracotta_light_blue": { "type": "BLOCKS", "iconTextureData": "terracotta_light_blue_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_light_blue", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_light_gray.json ================================================ { "block": { "terracotta_light_gray": { "textureData": "terracotta_light_gray.png", "color": [ 184, 172, 160 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 120, 100 ] } }, "item": { "terracotta_light_gray": { "type": "BLOCKS", "iconTextureData": "terracotta_light_gray_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_light_gray", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_lime.json ================================================ { "block": { "terracotta_lime": { "textureData": "terracotta_lime.png", "color": [ 134, 168, 101 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 50, 100, 0 ] } }, "item": { "terracotta_lime": { "type": "BLOCKS", "iconTextureData": "terracotta_lime_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_lime", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_magenta.json ================================================ { "block": { "terracotta_magenta": { "textureData": "terracotta_magenta.png", "color": [ 168, 134, 168 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 60, 120 ] } }, "item": { "terracotta_magenta": { "type": "BLOCKS", "iconTextureData": "terracotta_magenta_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_magenta", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_orange.json ================================================ { "block": { "terracotta_orange": { "textureData": "terracotta_orange.png", "color": [ 180, 167, 154 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 140, 120, 100 ] } }, "item": { "terracotta_orange": { "type": "BLOCKS", "iconTextureData": "terracotta_orange_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_orange", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_pink.json ================================================ { "block": { "terracotta_pink": { "textureData": "terracotta_pink.png", "color": [ 168, 150, 150 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 130, 100, 100 ] } }, "item": { "terracotta_pink": { "type": "BLOCKS", "iconTextureData": "terracotta_pink_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_pink", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_purple.json ================================================ { "block": { "terracotta_purple": { "textureData": "terracotta_purple.png", "color": [ 141, 125, 172 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 60, 30, 120 ] } }, "item": { "terracotta_purple": { "type": "BLOCKS", "iconTextureData": "terracotta_purple_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_purple", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_red.json ================================================ { "block": { "terracotta_red": { "textureData": "terracotta_red.png", "color": [ 172, 100, 100 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 0, 0 ] } }, "item": { "terracotta_red": { "type": "BLOCKS", "iconTextureData": "terracotta_red_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_red", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_white.json ================================================ { "block": { "terracotta_white": { "note": "各色陶瓦 67:0-15", "textureData": "terracotta_white.png", "color": [ 209, 177, 161 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 200, 170, 150 ] } }, "item": { "terracotta_white": { "type": "BLOCKS", "iconTextureData": "terracotta_white_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_white", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/terracottas/terracotta_yellow.json ================================================ { "block": { "terracotta_yellow": { "textureData": "terracotta_yellow.png", "color": [ 166, 166, 101 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 160, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 120, 120, 0 ] } }, "item": { "terracotta_yellow": { "type": "BLOCKS", "iconTextureData": "terracotta_yellow_icon.png", "group": "GROUP_TERRACOTTA", "blockId": "terracotta_yellow", "oreDictionary": [ "OD_TERRACOTTA" ] } } } ================================================ FILE: blocks/tiles/test/blue_mushroom.json ================================================ { "block": { "blue_mushroom": { "textureData": "blue_mushroom.png", "color": [ 157, 120, 72 ], "type": "FURNITURE", "width": 1, "height": 1, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_BLUE_MUSHROOM_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isLighting": true, "lightColor": [ 12, 0, 0, 4 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 2, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 170, 140, 80 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ], "preset": "RandomDisplay" } }, "item": { "blue_mushroom": { "type": "BLOCKS", "iconTextureData": "blue_mushroom_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "blue_mushroom" } } } ================================================ FILE: blocks/tiles/test/blue_mushroom_dirt.json ================================================ { "block": { "blue_mushroom_dirt": { "textureData": "blue_mushroom_dirt.png", "color": [ 15, 33, 112 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "DIRT", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "hasGrassCover": true, "isRipen": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 123, 100, 100 ], "preset": "GrowGrass", "covers": [ { "modTextureId": "tainted_grass", "offsetX": -8, "offsetY": -8 } ] } }, "item": { "blue_mushroom_dirt": { "type": "BLOCKS", "iconTextureData": "blue_mushroom_dirt_icon.png", "group": "GROUP_MUSHROOM_BLOCK", "blockId": "blue_mushroom_dirt" } } } ================================================ FILE: blocks/tiles/test/blue_mushroom_stem.json ================================================ { "block": { "blue_mushroom_stem": { "textureData": "blue_mushroom_stem.png", "color": [ 2, 7, 91 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "COBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "isLighting": true, "lightColor": [ 10, 0, 0, 5 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "blue_mushroom_stem": { "type": "BLOCKS", "iconTextureData": "blue_mushroom_stem_icon.png", "group": "GROUP_COBBLESTONE", "blockId": "blue_mushroom_stem" } } } ================================================ FILE: blocks/tiles/test/ice_cobblestone_hard.json ================================================ { "block": { "ice_cobblestone_hard": { "textureData": "ice_cobblestone_hard.png", "color": [ 71, 96, 118 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "COBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "ice_cobblestone_hard": { "type": "BLOCKS", "iconTextureData": "ice_cobblestone_hard_icon.png", "group": "GROUP_COBBLESTONE", "blockId": "ice_cobblestone_hard" } } } ================================================ FILE: blocks/tiles/test/large_blue_mushroom.json ================================================ { "block": { "large_blue_mushroom": { "textureData": "large_blue_mushroom.png", "color": [ 157, 120, 72 ], "type": "FURNITURE", "width": 2, "height": 2, "collision": "NONE", "attach": "BOTTOM", "attachable": "NONE", "placeCheck": "PLACE_BLUE_MUSHROOM_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 10, "slipperiness": 1.0, "isKilledByLava": true, "isLighting": true, "lightColor": [ 12, 0, 0, 4 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 2, "isFragile": true, "isDestroyByWeapon": false, "soundGroupId": "grass", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 170, 140, 80 ], "animation": [ { "animationId": 0, "shake": true, "shakeCenterX": 8, "shakeCenterY": 16, "shakePeriod": 128, "shakeAngle": 0.2 } ], "preset": "RandomDisplay" } }, "item": { "large_blue_mushroom": { "type": "BLOCKS", "iconTextureData": "large_blue_mushroom_icon.png", "group": "GROUP_OTHERS_FURNITURE", "blockId": "large_blue_mushroom" } } } ================================================ FILE: blocks/tiles/test/lava_block_pile.json ================================================ { "block": { "lava_block_pile": { "textureData": "lava_block_pile.png", "color": [ 40, 64, 122 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "COBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "lava_block_pile": { "type": "BLOCKS", "iconTextureData": "lava_block_pile_icon.png", "group": "GROUP_COBBLESTONE", "blockId": "lava_block_pile" } } } ================================================ FILE: blocks/tiles/test/pile_cobblestone.json ================================================ { "block": { "pile_cobblestone": { "textureData": "pile_cobblestone.png", "color": [ 40, 64, 122 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "COBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "pile_cobblestone": { "type": "BLOCKS", "iconTextureData": "pile_cobblestone_icon.png", "group": "GROUP_COBBLESTONE", "blockId": "pile_cobblestone" } } } ================================================ FILE: blocks/tiles/test/snow_soft.json ================================================ { "block": { "snow_soft": { "textureData": "snow_soft.png", "color": [ 128, 255, 255 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "SNOW", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "snow", "stepSoundGroupId": "step_snow", "particleColor": [ 255, 170, 255, 255 ] } }, "item": { "snow_soft": { "type": "BLOCKS", "iconTextureData": "snow_soft_icon.png", "group": "GROUP_SNOW", "blockId": "snow_soft" } } } ================================================ FILE: blocks/tiles/test/volcano_burn_stone.json ================================================ { "block": { "volcano_burn_stone": { "textureData": "volcano_burn_stone.png", "color": [ 132, 21, 1 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "COBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "volcano_burn_stone": { "type": "BLOCKS", "iconTextureData": "volcano_burn_stone_icon.png", "group": "GROUP_COBBLESTONE", "blockId": "volcano_burn_stone" } } } ================================================ FILE: blocks/tiles/test/volcano_cobblestone.json ================================================ { "block": { "volcano_cobblestone": { "textureData": "volcano_cobblestone.png", "color": [ 40, 64, 122 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "COBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "NATURE_GENERABLE_ONLY", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 100, 100, 100 ] } }, "item": { "volcano_cobblestone": { "type": "BLOCKS", "iconTextureData": "volcano_cobblestone_icon.png", "group": "GROUP_COBBLESTONE", "blockId": "volcano_cobblestone" } } } ================================================ FILE: blocks/tiles/volcanos/magma_block.json ================================================ { "block": { "magma_block": { "textureData": "magma_block.png", "color": [ 122, 46, 30 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "MAGMA_BLOCK", "collision": "SOLID", "lightOpacity": 3, "isLighting": true, "lightColor": [ 26, 10, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 1, "lightHi": 1, "toolType": "PICKAXE", "mineGrade": "STONE", "hardness": 220, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 230, 140, 70 ], "preset": "MagmaBlock" } }, "item": { "magma_block": { "type": "BLOCKS", "iconTextureData": "magma_block_icon.png", "group": "GROUP_OTHERS_BLOCK", "blockId": "magma_block" } } } ================================================ FILE: blocks/tiles/volcanos/volcano_dirt.json ================================================ { "block": { "volcano_dirt": { "textureData": "volcano_dirt.png", "color": [ 100, 34, 0 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "DIRT", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "hasGrassCover": false, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_grass", "particleColor": [ 255, 100, 34, 0 ] } }, "item": { "volcano_dirt": { "type": "BLOCKS", "iconTextureData": "volcano_dirt_icon.png", "group": "GROUP_VOLCANO", "blockId": "volcano_dirt" } } } ================================================ FILE: blocks/tiles/volcanos/volcano_stone.json ================================================ { "block": { "volcano_stone": { "textureData": "volcano_stone.png", "color": [ 134, 51, 10 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 8, "type": "TILE", "group": "COBBLESTONE", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "WOOD", "hardness": 120, "slipperiness": 1.0, "gravity": false, "allowSlope": true, "isWallDark": true, "wallCheck": "GENERABLE", "soundGroupId": "stone", "stepSoundGroupId": "step_stone", "particleColor": [ 255, 134, 51, 10 ] } }, "item": { "volcano_stone": { "type": "BLOCKS", "iconTextureData": "volcano_stone_icon.png", "group": "GROUP_VOLCANO", "blockId": "volcano_stone" } } } ================================================ FILE: blocks/tiles/woods/wood_acacia.json ================================================ { "block": { "wood_acacia": { "textureData": "wood_acacia.png", "color": [ 77, 77, 77 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "subGroup": "WOOD", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "transformId": "wood_stripped_acacia", "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 180, 100, 60 ] } }, "item": { "wood_acacia": { "type": "BLOCKS", "iconTextureData": "wood_acacia_icon.png", "group": "GROUP_WOOD", "blockId": "wood_acacia", "fuelTime": 60, "oreDictionary": [ "OD_WOOD" ] } } } ================================================ FILE: blocks/tiles/woods/wood_birch.json ================================================ { "block": { "wood_birch": { "textureData": "wood_birch.png", "color": [ 211, 211, 211 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_A", "subGroup": "WOOD", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "transformId": "wood_stripped_birch", "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 200, 130 ] } }, "item": { "wood_birch": { "type": "BLOCKS", "iconTextureData": "wood_birch_icon.png", "group": "GROUP_WOOD", "blockId": "wood_birch", "fuelTime": 60, "oreDictionary": [ "OD_WOOD" ] } } } ================================================ FILE: blocks/tiles/woods/wood_dark_oak.json ================================================ { "block": { "wood_dark_oak": { "textureData": "wood_dark_oak.png", "color": [ 74, 66, 51 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "subGroup": "WOOD", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "transformId": "wood_stripped_dark_oak", "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 30, 10 ] } }, "item": { "wood_dark_oak": { "type": "BLOCKS", "iconTextureData": "wood_dark_oak_icon.png", "group": "GROUP_WOOD", "blockId": "wood_dark_oak", "fuelTime": 60, "oreDictionary": [ "OD_WOOD" ] } } } ================================================ FILE: blocks/tiles/woods/wood_jungle.json ================================================ { "block": { "wood_jungle": { "textureData": "wood_jungle.png", "color": [ 82, 71, 61 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "subGroup": "WOOD", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "transformId": "wood_stripped_jungle", "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 70, 50 ] } }, "item": { "wood_jungle": { "type": "BLOCKS", "iconTextureData": "wood_jungle_icon.png", "group": "GROUP_WOOD", "blockId": "wood_jungle", "fuelTime": 60, "oreDictionary": [ "OD_WOOD" ] } } } ================================================ FILE: blocks/tiles/woods/wood_oak.json ================================================ { "block": { "wood_oak": { "textureData": "wood_oak.png", "color": [ 81, 69, 47 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "subGroup": "WOOD", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "transformId": "wood_stripped_oak", "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 173, 137, 80 ] } }, "item": { "wood_oak": { "type": "BLOCKS", "iconTextureData": "wood_oak_icon.png", "group": "GROUP_WOOD", "blockId": "wood_oak", "fuelTime": 60, "oreDictionary": [ "OD_WOOD" ] } } } ================================================ FILE: blocks/tiles/woods/wood_palm.json ================================================ { "block": { "wood_palm": { "textureData": "wood_palm.png", "color": [ 182, 141, 86 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "subGroup": "WOOD", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "transformId": "wood_stripped_palm", "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 182, 141, 86 ] } }, "item": { "wood_palm": { "type": "BLOCKS", "iconTextureData": "wood_palm_icon.png", "group": "GROUP_WOOD", "blockId": "wood_palm", "fuelTime": 60, "oreDictionary": [ "OD_WOOD" ] } } } ================================================ FILE: blocks/tiles/woods/wood_spruce.json ================================================ { "block": { "wood_spruce": { "textureData": "wood_spruce.png", "color": [ 91, 80, 75 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "subGroup": "WOOD", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "transformId": "wood_stripped_spruce", "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 90, 60 ] } }, "item": { "wood_spruce": { "type": "BLOCKS", "iconTextureData": "wood_spruce_icon.png", "group": "GROUP_WOOD", "blockId": "wood_spruce", "fuelTime": 60, "oreDictionary": [ "OD_WOOD" ] } } } ================================================ FILE: blocks/tiles/woods/wood_stripped_acacia.json ================================================ { "block": { "wood_stripped_acacia": { "textureData": "wood_stripped_acacia.png", "color": [ 208, 150, 130 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 180, 100, 60 ] } }, "item": { "wood_stripped_acacia": { "type": "BLOCKS", "iconTextureData": "wood_stripped_acacia_icon.png", "group": "GROUP_WOOD_STRIPPED", "blockId": "wood_stripped_acacia", "fuelTime": 60, "oreDictionary": ["OD_WOOD_STRIPPED"] } } } ================================================ FILE: blocks/tiles/woods/wood_stripped_birch.json ================================================ { "block": { "wood_stripped_birch": { "textureData": "wood_stripped_birch.png", "color": [ 220, 206, 166 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_A", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 200, 130 ] } }, "item": { "wood_stripped_birch": { "type": "BLOCKS", "iconTextureData": "wood_stripped_birch_icon.png", "group": "GROUP_WOOD_STRIPPED", "blockId": "wood_stripped_birch", "fuelTime": 60, "oreDictionary": ["OD_WOOD_STRIPPED"] } } } ================================================ FILE: blocks/tiles/woods/wood_stripped_dark_oak.json ================================================ { "block": { "wood_stripped_dark_oak": { "textureData": "wood_stripped_dark_oak.png", "color": [ 155, 140, 120 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 60, 30, 10 ] } }, "item": { "wood_stripped_dark_oak": { "type": "BLOCKS", "iconTextureData": "wood_stripped_dark_oak_icon.png", "group": "GROUP_WOOD_STRIPPED", "blockId": "wood_stripped_dark_oak", "fuelTime": 60, "oreDictionary": ["OD_WOOD_STRIPPED"] } } } ================================================ FILE: blocks/tiles/woods/wood_stripped_jungle.json ================================================ { "block": { "wood_stripped_jungle": { "textureData": "wood_stripped_jungle.png", "color": [ 210, 177, 144 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 100, 70, 50 ] } }, "item": { "wood_stripped_jungle": { "type": "BLOCKS", "iconTextureData": "wood_stripped_jungle_icon.png", "group": "GROUP_WOOD_STRIPPED", "blockId": "wood_stripped_jungle", "fuelTime": 60, "oreDictionary": ["OD_WOOD_STRIPPED"] } } } ================================================ FILE: blocks/tiles/woods/wood_stripped_oak.json ================================================ { "block": { "wood_stripped_oak": { "textureData": "wood_stripped_oak.png", "color": [ 166, 152, 134 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 173, 137, 80 ] } }, "item": { "wood_stripped_oak": { "type": "BLOCKS", "iconTextureData": "wood_stripped_oak_icon.png", "group": "GROUP_WOOD_STRIPPED", "blockId": "wood_stripped_oak", "fuelTime": 60, "oreDictionary": ["OD_WOOD_STRIPPED"] } } } ================================================ FILE: blocks/tiles/woods/wood_stripped_palm.json ================================================ { "block": { "wood_stripped_palm": { "textureData": "wood_stripped_palm.png", "color": [ 182, 141, 86 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 182, 141, 86 ] } }, "item": { "wood_stripped_palm": { "type": "BLOCKS", "iconTextureData": "wood_stripped_palm_icon.png", "group": "GROUP_WOOD_STRIPPED", "blockId": "wood_stripped_palm", "fuelTime": 60, "oreDictionary": ["OD_WOOD_STRIPPED"] } } } ================================================ FILE: blocks/tiles/woods/wood_stripped_spruce.json ================================================ { "block": { "wood_stripped_spruce": { "textureData": "wood_stripped_spruce.png", "color": [ 179, 158, 134 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 120, 90, 60 ] } }, "item": { "wood_stripped_spruce": { "type": "BLOCKS", "iconTextureData": "wood_stripped_spruce_icon.png", "group": "GROUP_WOOD_STRIPPED", "blockId": "wood_stripped_spruce", "fuelTime": 60, "oreDictionary": ["OD_WOOD_STRIPPED"] } } } ================================================ FILE: blocks/tiles/woods/wood_stripped_tainted.json ================================================ { "block": { "wood_stripped_tainted": { "textureData": "wood_stripped_tainted.png", "color": [ 89, 85, 107 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 89, 85, 107 ] } }, "item": { "wood_stripped_tainted": { "type": "BLOCKS", "iconTextureData": "wood_stripped_tainted_icon.png", "group": "GROUP_WOOD_STRIPPED", "blockId": "wood_stripped_tainted", "fuelTime": 60, "oreDictionary": ["OD_WOOD_STRIPPED"] } } } ================================================ FILE: blocks/tiles/woods/wood_stripped_volcano.json ================================================ { "block": { "wood_stripped_volcano": { "textureData": "wood_stripped_volcano.png", "color": [ 200, 60, 60 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 60, 60 ] } }, "item": { "wood_stripped_volcano": { "type": "BLOCKS", "iconTextureData": "wood_stripped_volcano_icon.png", "group": "GROUP_WOOD_STRIPPED", "blockId": "wood_stripped_volcano", "fuelTime": 60, "oreDictionary": ["OD_WOOD_STRIPPED"] } } } ================================================ FILE: blocks/tiles/woods/wood_tainted.json ================================================ { "block": { "wood_tainted": { "textureData": "wood_tainted.png", "color": [ 89, 85, 107 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "subGroup": "WOOD", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "transformId": "wood_stripped_tainted", "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 89, 85, 107 ] } }, "item": { "wood_tainted": { "type": "BLOCKS", "iconTextureData": "wood_tainted_icon.png", "group": "GROUP_WOOD", "blockId": "wood_tainted", "fuelTime": 60, "oreDictionary": [ "OD_WOOD" ] } } } ================================================ FILE: blocks/tiles/woods/wood_volcano.json ================================================ { "block": { "wood_volcano": { "textureData": "wood_volcano.png", "color": [ 200, 60, 60 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "WOOD_B", "subGroup": "WOOD", "collision": "SOLID", "lightOpacity": 3, "toolType": "AXE", "mineGrade": "GRASS", "hardness": 100, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "transformId": "wood_stripped_volcano", "wallCheck": "NO_GENERABLE", "soundGroupId": "wood", "stepSoundGroupId": "step_wood", "particleColor": [ 255, 200, 60, 60 ] } }, "item": { "wood_volcano": { "type": "BLOCKS", "iconTextureData": "wood_volcano_icon.png", "group": "GROUP_WOOD", "blockId": "wood_volcano", "fuelTime": 360, "oreDictionary": [ "OD_WOOD" ] } } } ================================================ FILE: blocks/tiles/wools/wool_black.json ================================================ { "block": { "wool_black": { "textureData": "wool_black.png", "color": [ 99, 99, 99 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 0, 0, 0 ] } }, "item": { "wool_black": { "type": "BLOCKS", "iconTextureData": "wool_black_icon.png", "group": "GROUP_WOOL", "blockId": "wool_black", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_blue.json ================================================ { "block": { "wool_blue": { "textureData": "wool_blue.png", "color": [ 119, 129, 188 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 0, 0, 120 ] } }, "item": { "wool_blue": { "type": "BLOCKS", "iconTextureData": "wool_blue_icon.png", "group": "GROUP_WOOL", "blockId": "wool_blue", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_brown.json ================================================ { "block": { "wool_brown": { "textureData": "wool_brown.png", "color": [ 167, 133, 108 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 130, 100, 50 ] } }, "item": { "wool_brown": { "type": "BLOCKS", "iconTextureData": "wool_brown_icon.png", "group": "GROUP_WOOL", "blockId": "wool_brown", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_cyan.json ================================================ { "block": { "wool_cyan": { "textureData": "wool_cyan.png", "color": [ 88, 180, 180 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 0, 120, 120 ] } }, "item": { "wool_cyan": { "type": "BLOCKS", "iconTextureData": "wool_cyan_icon.png", "group": "GROUP_WOOL", "blockId": "wool_cyan", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_gray.json ================================================ { "block": { "wool_gray": { "textureData": "wool_gray.png", "color": [ 125, 125, 128 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 60, 60, 60 ] } }, "item": { "wool_gray": { "type": "BLOCKS", "iconTextureData": "wool_gray_icon.png", "group": "GROUP_WOOL", "blockId": "wool_gray", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_green.json ================================================ { "block": { "wool_green": { "textureData": "wool_green.png", "color": [ 144, 66, 92 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 0, 120, 0 ] } }, "item": { "wool_green": { "type": "BLOCKS", "iconTextureData": "wool_green_icon.png", "group": "GROUP_WOOL", "blockId": "wool_green", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_light_blue.json ================================================ { "block": { "wool_light_blue": { "textureData": "wool_light_blue.png", "color": [ 130, 215, 240 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 60, 90, 120 ] } }, "item": { "wool_light_blue": { "type": "BLOCKS", "iconTextureData": "wool_light_blue_icon.png", "group": "GROUP_WOOL", "blockId": "wool_light_blue", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_light_gray.json ================================================ { "block": { "wool_light_gray": { "textureData": "wool_light_gray.png", "color": [ 160, 166, 169 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 120, 120, 100 ] } }, "item": { "wool_light_gray": { "type": "BLOCKS", "iconTextureData": "wool_light_gray_icon.png", "group": "GROUP_WOOL", "blockId": "wool_light_gray", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_lime.json ================================================ { "block": { "wool_lime": { "textureData": "wool_lime.png", "color": [ 171, 212, 151 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 50, 100, 0 ] } }, "item": { "wool_lime": { "type": "BLOCKS", "iconTextureData": "wool_lime_icon.png", "group": "GROUP_WOOL", "blockId": "wool_lime", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_magenta.json ================================================ { "block": { "wool_magenta": { "textureData": "wool_magenta.png", "color": [ 202, 109, 193 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 120, 60, 120 ] } }, "item": { "wool_magenta": { "type": "BLOCKS", "iconTextureData": "wool_magenta_icon.png", "group": "GROUP_WOOL", "blockId": "wool_magenta", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_orange.json ================================================ { "block": { "wool_orange": { "textureData": "wool_orange.png", "color": [ 248, 116, 93 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 140, 120, 100 ] } }, "item": { "wool_orange": { "type": "BLOCKS", "iconTextureData": "wool_orange_icon.png", "group": "GROUP_WOOL", "blockId": "wool_orange", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_pink.json ================================================ { "block": { "wool_pink": { "textureData": "wool_pink.png", "color": [ 212, 155, 188 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 130, 100, 100 ] } }, "item": { "wool_pink": { "type": "BLOCKS", "iconTextureData": "wool_pink_icon.png", "group": "GROUP_WOOL", "blockId": "wool_pink", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_purple.json ================================================ { "block": { "wool_purple": { "textureData": "wool_purple.png", "color": [ 90, 114, 204 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 60, 30, 120 ] } }, "item": { "wool_purple": { "type": "BLOCKS", "iconTextureData": "wool_purple_icon.png", "group": "GROUP_WOOL", "blockId": "wool_purple", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_red.json ================================================ { "block": { "wool_red": { "textureData": "wool_red.png", "color": [ 186, 100, 97 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 120, 0, 0 ] } }, "item": { "wool_red": { "type": "BLOCKS", "iconTextureData": "wool_red_icon.png", "group": "GROUP_WOOL", "blockId": "wool_red", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_white.json ================================================ { "block": { "wool_white": { "note": "各色羊毛 138:0-15", "textureData": "wool_white.png", "color": [ 201, 208, 208 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 200, 170, 150 ] } }, "item": { "wool_white": { "type": "BLOCKS", "iconTextureData": "wool_white_icon.png", "group": "GROUP_WOOL", "blockId": "wool_white", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: blocks/tiles/wools/wool_yellow.json ================================================ { "block": { "wool_yellow": { "textureData": "wool_yellow.png", "color": [ 252, 218, 96 ], "renderMode": "RENDER_CUT", "renderSortedInterval": 4, "type": "TILE", "group": "ARTIFICAL", "collision": "SOLID", "lightOpacity": 3, "toolType": "PICKAXE", "mineGrade": "GRASS", "hardness": 60, "slipperiness": 1.0, "gravity": false, "allowSlope": false, "isWallDark": false, "wallCheck": "NO_GENERABLE", "soundGroupId": "cloth", "stepSoundId": "step_cloth", "particleColor": [ 255, 120, 120, 0 ] } }, "item": { "wool_yellow": { "type": "BLOCKS", "iconTextureData": "wool_yellow_icon.png", "group": "GROUP_WOOL", "blockId": "wool_yellow", "fuelTime": 20, "oreDictionary": ["OD_WOOL"] } } } ================================================ FILE: bone2d/ItemJointHelper.lua ================================================ local ItemJointHelper = class("ItemJointHelper") ---checkItemChanged ---@param itemSlot Slot ---@param cacheTable table function ItemJointHelper.checkItemChanged(itemSlot, cacheTable) local checking = false if cacheTable.itemID == nil then checking = true else if itemSlot.hasStack then if cacheTable.itemID ~= itemSlot:GetStack():GetItem().id then checking = true end else if cacheTable.itemID ~= 0 then checking = true end end end return checking end ---setItem ---@param itemJoint Joint2D ---@param itemStack ItemStack function ItemJointHelper.setItem(itemJoint, itemStack) local holdX, holdY = 16, 16 local jointWidth, jointHeight = 32, 32 local item = itemStack:GetItem() local usingEntity = item.hasEntity if usingEntity then holdX, holdY = item.handX, item.handY jointWidth, jointHeight = item.entityWidth, item.entityHeight end itemJoint.transform.origin = Vector2.new(holdX, holdY) itemJoint.size = Size.new(jointWidth, jointHeight) itemJoint.visible = true if NetMode.current == NetMode.Client then local texOffsetX, texOffsetY, texWidth, texHeight = 0, 0, 32, 32 local texture = usingEntity and item.entityTextureLocation or item.iconTextureLocation local scale = 1.0 if texture.valid then local cut = TextureManager.getSourceRect(texture) texWidth, texHeight = cut.width, cut.height local modItem = itemStack:GetModItem() if modItem ~= nil and modItem.IsUseTex32 and modItem:IsUseTex32() then texWidth, texHeight = 32, 32 end if usingEntity then texOffsetX, texOffsetY = item.entityOffsetX, item.entityOffsetY texWidth, texHeight = jointWidth, jointHeight else local maxTexSize = math.max(1, math.max(texWidth, texHeight)) scale = 32 / maxTexSize end itemJoint:setTexture("item", texture, Vector2.new(-texOffsetX, -texOffsetY), Rect.new(0, 0, texWidth, texHeight)) else itemJoint:setTexture("item", texture, Vector2.new(0, 0), Rect.new(0, 0, 32, 32)) end itemJoint.transform.rotation = math.pi / 2 itemJoint.transform.scale = Vector2.new(scale, scale) end end ---checkItem ---@param itemJoint Joint2D ---@param itemSlot Slot ---@param cacheTable table function ItemJointHelper.checkItem(itemJoint, itemSlot, cacheTable) local checking = ItemJointHelper.checkItemChanged(itemSlot, cacheTable) if not checking then return end if itemSlot.hasStack then local stack = itemSlot:GetStack() cacheTable.itemID = stack:GetItem().id ItemJointHelper.setItem(itemJoint, stack) else cacheTable.itemID = 0 ItemJointHelper.clearItem(itemJoint) end end ---@param itemJoint Joint2D function ItemJointHelper.clearItem(itemJoint) itemJoint.visible = false end return ItemJointHelper ================================================ FILE: bone2d/NpcHumanAnimator.lua ================================================ local NpcHumanAnimator = class("NpcHumanAnimator") function NpcHumanAnimator.create() local asm = { parameters = { "Float Speed 0.0", "Bool OnGround False", "Float AirSpeed 0.0", "Bool Standard False", "Trigger SwordAttacking False", "Bool HoldingItem False", "Trigger StopAction False" }, layers = { { name = "Base Layer", weight = 1.0, blending = "Override", mask = { disabledJoints = {} }, states = { { name = "StandardIdle", isDefault = true, clipName = "Standard", transitions = { { nextState = "Stand", offset = 0, duration = 0.5, conditions = { "Standard == false" } } } }, { name = "Stand", blendTree = { parameter = "Speed", motions = { { clipName = "Idle", threshold = 0.0 }, { clipName = "Walk", threshold = 1.0 }, } }, transitions = { { nextState = "Jump", offset = 0.0, duration = 0.15, conditions = { "OnGround == false" } }, } }, { name = "Jump", clipName = "Jump", transitions = { { nextState = "Stand", offset = 0, duration = 0.25, hasExitTime = false, conditions = { "OnGround == true" } }, } }, } }, { name = "Body Action Layer", weight = 1.0, blending = "Override", --mask = { --disabledJoints = { "base.body.front_leg", "base.body.back_leg" } --}, states = { { name = "StandardIdle", isDefault = true, clipName = "Standard", transitions = { { nextState = "HoldingItem", offset = 0, duration = 0.2, conditions = { "HoldingItem == true" } }, { nextState = "SwordAttacking", offset = 0, duration = 0, conditions = { "SwordAttacking == true" } } } }, { name = "HoldingItem", clipName = "HoldingItem", transitions = { { nextState = "StandardIdle", offset = 0, duration = 0.2, conditions = { "HoldingItem == false" } }, } }, { name = "SwordAttacking", clipName = "SwordAttacking", transitions = { { nextState = "StandardIdle", offset = 0.99, duration = 0, hasExitTime = false, }, { nextState = "StandardIdle", offset = 0, duration = 0, conditions = { "StopAction == true" } } } }, } } } } return AnimatorData2D.new(asm) end return NpcHumanAnimator ================================================ FILE: bone2d/NpcHumanBoneInfo.lua ================================================ ---@class TC.NpcHumanBoneInfo local NpcHumanBoneInfo = class("NpcHumanBoneInfo") local NpcHumanJoints = require("NpcHumanJoints") local NpcHumanJointsTall = require("NpcHumanJointsTall") local NpcHumanClips = require("NpcHumanClips") local NpcHumanAnimator = require("NpcHumanAnimator") local ItemJointHelper = require("ItemJointHelper") local s_instance ---@return TC.NpcHumanBoneInfo function NpcHumanBoneInfo.getInstance() if s_instance == nil then s_instance = NpcHumanBoneInfo.new() end return s_instance end function NpcHumanBoneInfo:__init() self._pool = {} ---@type JointBody2D[] end ---load ---@param npcID int ---@param texture TextureLocation ---@param sizeIndex int ---@return JointBody2D function NpcHumanBoneInfo:load(npcID, texture, sizeIndex) if sizeIndex == nil then sizeIndex = 0 end local last = self._pool[npcID] if last then return last:clone() end local joints if sizeIndex == 1 then joints = NpcHumanJointsTall.create(texture) else joints = NpcHumanJoints.create(texture) end local reserve = JointBody2D.new(joints) reserve:setAnimator(NpcHumanClips.create(reserve.joints), NpcHumanAnimator.create()) self._pool[npcID] = reserve return reserve:clone() end ---checkHandItem ---@param itemJoint Joint2D ---@param itemSlot Slot ---@param cacheTable table function NpcHumanBoneInfo.checkHandItem(itemJoint, itemSlot, cacheTable) ItemJointHelper.checkItem(itemJoint, itemSlot, cacheTable) end ---@param jointBody JointBody2D ---@param isBackHand boolean function NpcHumanBoneInfo.getItemJoint(jointBody, isBackHand) return isBackHand and jointBody.joints:getJoint("base.body.back_arm.back_item") or jointBody.joints:getJoint("base.body.front_arm.front_item") end return NpcHumanBoneInfo ================================================ FILE: bone2d/NpcHumanClips.lua ================================================ local NpcHumanClips = class("NpcHumanClips") ---getClips ---@param joints JointCollection2D ---@return ClipCollection2D function NpcHumanClips.create(joints) local clips = ClipCollection2D.new(joints) clips:addClip({ name = "Idle", time = 1.5, loop = true, jointClips = { { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.25, value = 0.0584 }, { time = 0.5, value = 0.0 }, { time = 0.7, value = -0.0425 }, { time = 0.9, value = 0.0 }, } } } }, { jointName = "base.body.head", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.25, value = -0.0584 }, { time = 0.5, value = 0.0 }, { time = 0.7, value = 0.0425 }, { time = 0.9, value = 0.0 }, } } } }, { jointName = "base.body.back_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.25, value = -0.0584 }, { time = 0.5, value = 0.0 }, { time = 0.7, value = 0.0425 }, { time = 0.9, value = 0.0 }, } } } }, { jointName = "base.body.front_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.25, value = -0.0584 }, { time = 0.5, value = 0.0 }, { time = 0.7, value = 0.0425 }, { time = 0.9, value = 0.0 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = -0.15 }, { time = 1.0, value = 0.0 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = 0.15 }, { time = 1.0, value = 0.0 }, } } } }, } }) clips:addClip({ name = "Walk", time = 0.6, loop = true, jointClips = { { jointName = "base.body.back_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.75 }, { time = 0.5, value = 0.5 }, { time = 1.0, value = -0.75 }, } } } }, { jointName = "base.body.front_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.5 }, { time = 0.5, value = -0.85 }, { time = 1.0, value = 0.5 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.5 }, { time = 0.5, value = 0.5 }, { time = 1.0, value = -0.5 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.25 }, { time = 0.5, value = -0.5 }, { time = 1.0, value = 0.25 }, } } } }, { jointName = "base.body.head", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.015 }, { time = 0.5, value = -0.015 }, { time = 1.0, value = 0.015 }, } } } }, { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = 0.05 }, { time = 1.0, value = 0.0 }, } } } }, } }) clips:addClip({ name = "Jump", time = 1.79, loop = true, jointClips = { { jointName = "base.body.back_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.75 }, { time = 0.5, value = -0.65 }, { time = 1.0, value = -0.75 }, } } } }, { jointName = "base.body.front_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.75 }, { time = 0.5, value = 0.85 }, { time = 1.0, value = 0.75 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -1.0 }, { time = 0.5, value = -0.9 }, { time = 1.0, value = -1.0 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 1.0 }, { time = 0.5, value = 0.9 }, { time = 1.0, value = 1.0 }, } } } }, { jointName = "base.body.head", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.02 }, { time = 0.5, value = -0.05 }, { time = 1.0, value = -0.02 }, } } } }, { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.00 }, { time = 0.5, value = -0.03 }, { time = 1.0, value = -0.00 }, } } } }, } }) clips:addClip({ name = "HoldingItem", time = 0.51, loop = true, jointClips = { { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -1.0 }, { time = 0.5, value = -1.02 }, { time = 1.0, value = -1.0 }, } } } }, { jointName = "base.body.back_arm.back_item", data = { { variable = "Angle", samples = { { time = 0.0, value = math.pi / 2 }, } } } }, } }) clips:addClip({ name = "SwordAttacking", time = 1.0, loop = false, jointClips = { { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -3.2 }, { time = 1.0, value = -0.3 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, value = 0.0 }, } } } }, { jointName = "base.body.back_arm.back_item", data = { { variable = "Angle", samples = { { time = 0.0, value = 2.4 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, value = 1.0 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, value = -0.5 }, } } } }, } }) clips:addClip({ name = "Standard", time = 1.0, loop = true, jointClips = { { jointName = "base.body.back_arm.back_item", data = { { variable = "Angle", samples = { { time = 0.0, value = math.pi / 2 }, } } } }, } }) return clips end return NpcHumanClips ================================================ FILE: bone2d/NpcHumanJoints.lua ================================================ local NpcHumanJoints = class("NpcHumanJoints") ---setSkin ---@param joints JointCollection2D ---@param textureLocation TextureLocation function NpcHumanJoints.setSkin(joints, textureLocation) if not textureLocation then return end local body = joints:getJoint("base.body") body:setTexture("skin", textureLocation, Vector2.new(-16, -18), Rect.new(48, 0, 48, 48)) local head = body:getChild("head") head:setTexture("skin", textureLocation, Vector2.new(-14, -14), Rect.new(0, 0, 48, 48)) local front_arm = body:getChild("front_arm") front_arm:setTexture("skin", textureLocation, Vector2.new(-20, -12), Rect.new(96, 0, 48, 48)) local back_arm = body:getChild("back_arm") back_arm:setTexture("skin", textureLocation, Vector2.new(-20, -12), Rect.new(96, 0, 48, 48)) local front_leg = body:getChild("front_leg") front_leg:setTexture("skin", textureLocation, Vector2.new(-20, -20), Rect.new(144, 0, 48, 48)) local back_leg = body:getChild("back_leg") back_leg:setTexture("skin", textureLocation, Vector2.new(-20, -20), Rect.new(144, 0, 48, 48)) end function NpcHumanJoints.create(textureLocation) local joints = JointCollection2D.new() joints.root = Joint2D.new("base", Vector2.new(8, 48), Size.new(16, 48)) local body = Joint2D.new("body", Vector2.new(6, 15), Size.new(8, 26)) joints.root:addChild(Vector2.new(8, 29), body) local back_arm = Joint2D.new("back_arm", Vector2.new(4, 4), Size.new(8, 26)) body:addChild(Vector2.new(12, 4), back_arm, false) local back_item = Joint2D.new("back_item", Vector2.new(0, 0), Size.new(32, 8)) back_arm:addChild(Vector2.new(4, 20), back_item, true) back_item.visible = false local head = Joint2D.new("head", Vector2.new(12, 19), Size.new(24, 22)) body:addChild(Vector2.new(8, -3), head, false) local back_leg = Joint2D.new("back_leg", Vector2.new(3, -1), Size.new(10, 18)) body:addChild(Vector2.new(8, 17), back_leg, false) local front_leg = Joint2D.new("front_leg", Vector2.new(3, -1), Size.new(10, 18)) body:addChild(Vector2.new(1, 17), front_leg, false) local front_arm = Joint2D.new("front_arm", Vector2.new(4, 4), Size.new(8, 26)) body:addChild(Vector2.new(1, 4), front_arm) local front_item = Joint2D.new("front_item", Vector2.new(0, 0), Size.new(32, 8)) front_arm:addChild(Vector2.new(4, 20), front_item, false) front_item.visible = false NpcHumanJoints.setSkin(joints, textureLocation) return joints end return NpcHumanJoints ================================================ FILE: bone2d/NpcHumanJointsTall.lua ================================================ local NpcHumanJointsTall = class("NpcHumanJointsTall") ---setSkin ---@param joints JointCollection2D ---@param textureLocation TextureLocation function NpcHumanJointsTall.setSkin(joints, textureLocation) if not textureLocation then return end local body = joints:getJoint("base.body") body:setTexture("skin", textureLocation, Vector2.new(-16, -18), Rect.new(48, 0, 48, 48)) local head = body:getChild("head") head:setTexture("skin", textureLocation, Vector2.new(-14, -14), Rect.new(0, 0, 48, 48)) local front_arm = body:getChild("front_arm") front_arm:setTexture("skin", textureLocation, Vector2.new(-20, -12), Rect.new(96, 0, 48, 48)) local back_arm = body:getChild("back_arm") back_arm:setTexture("skin", textureLocation, Vector2.new(-20, -12), Rect.new(96, 0, 48, 48)) local front_leg = body:getChild("front_leg") front_leg:setTexture("skin", textureLocation, Vector2.new(-20, -20), Rect.new(144, 0, 48, 48)) local back_leg = body:getChild("back_leg") back_leg:setTexture("skin", textureLocation, Vector2.new(-20, -20), Rect.new(144, 0, 48, 48)) end function NpcHumanJointsTall.create(textureLocation) local joints = JointCollection2D.new() joints.root = Joint2D.new("base", Vector2.new(8, 48), Size.new(16, 48)) local body = Joint2D.new("body", Vector2.new(6, 15), Size.new(16, 26)) joints.root:addChild(Vector2.new(8, 10), body) local back_arm = Joint2D.new("back_arm", Vector2.new(4, 4), Size.new(8, 26)) body:addChild(Vector2.new(14, 4), back_arm, false) local back_item = Joint2D.new("back_item", Vector2.new(0, 0), Size.new(32, 8)) back_arm:addChild(Vector2.new(4, 28), back_item, true) back_item.visible = false local head = Joint2D.new("head", Vector2.new(12, 19), Size.new(24, 22)) body:addChild(Vector2.new(8, -3), head, false) local back_leg = Joint2D.new("back_leg", Vector2.new(5, -1), Size.new(10, 28)) body:addChild(Vector2.new(11, 24), back_leg, false) local front_leg = Joint2D.new("front_leg", Vector2.new(5, -1), Size.new(10, 28)) body:addChild(Vector2.new(4, 24), front_leg, false) local front_arm = Joint2D.new("front_arm", Vector2.new(4, 4), Size.new(8, 26)) body:addChild(Vector2.new(3, 4), front_arm) local front_item = Joint2D.new("front_item", Vector2.new(0, 0), Size.new(32, 8)) front_arm:addChild(Vector2.new(4, 20), front_item, false) front_item.visible = false NpcHumanJointsTall.setSkin(joints, textureLocation) return joints end return NpcHumanJointsTall ================================================ FILE: bone2d/PlayerAnimator.lua ================================================ local PlayerAnimator = class("PlayerAnimator") function PlayerAnimator.create() local asm = { parameters = { "Float Speed 0.0", "Bool OnGround False", "Float AirSpeed 0.0", "Bool Death False", "Bool Standard False", "Trigger Placing False", "Trigger Eating False", "Trigger SwordAttacking False", "Bool HoldingItem False", "Trigger StopAction False" }, layers = { { name = "Base Layer", weight = 1.0, blending = "Override", mask = { disabledJoints = {} }, states = { { name = "StandardIdle", isDefault = true, clipName = "Standard", transitions = { { nextState = "Stand", offset = 0, duration = 0.5, conditions = { "Standard == false" } } } }, { name = "Idle", clipName = "Idle", transitions = { { nextState = "Walk", offset = 0, duration = 0.95, hasExitTime = false, conditions = { "Speed > 0.5" } } } }, { name = "Walk", clipName = "Walk", transitions = { { nextState = "Idle", offset = 0.0, duration = 0.95, conditions = { "Speed < 0.5" } } } }, { name = "Stand", blendTree = { parameter = "Speed", motions = { { clipName = "Idle", threshold = 0.0 }, { clipName = "Walk", threshold = 0.5 }, { clipName = "Run", threshold = 1.0 } } }, transitions = { { nextState = "JumpUp", offset = 0.0, duration = 0.15, conditions = { "OnGround == false", "AirSpeed < 0.0" } }, { nextState = "JumpDown", offset = 0.0, duration = 0.15, conditions = { "OnGround == false", "AirSpeed >= 0.0" } }, { nextState = "Death", offset = 0.0, duration = 0.55, conditions = { "Death == true" } } } }, { name = "JumpUp", clipName = "JumpUp", transitions = { { nextState = "JumpDown", offset = 0, duration = 0.15, hasExitTime = false, conditions = { "AirSpeed >= 0.0" } }, { nextState = "JustOnGround", offset = 0, duration = 0.25, hasExitTime = false, conditions = { "OnGround == true" } }, { nextState = "Death", offset = 0.0, duration = 0.55, conditions = { "Death == true" } } } }, { name = "JumpDown", clipName = "JumpDown", transitions = { { nextState = "JumpUp", offset = 0, duration = 0.15, hasExitTime = false, conditions = { "AirSpeed < 0.0" } }, { nextState = "JustOnGround", offset = 0, duration = 0.05, hasExitTime = false, conditions = { "OnGround == true" } }, { nextState = "Death", offset = 0.0, duration = 0.55, conditions = { "Death == true" } } } }, { name = "JustOnGround", clipName = "JustOnGround", transitions = { { nextState = "Stand", offset = 0.0, duration = 0.15, hasExitTime = false, }, { nextState = "Death", offset = 0.0, duration = 0.55, conditions = { "Death == true" } } } }, { name = "Death", clipName = "Death", transitions = { { nextState = "Stand", offset = 0.0, duration = 0.15, conditions = { "Death == false" } } } }, --{ -- name = "Standard", -- clipName = "Standard", -- isDefault = true, -- transitions = { -- } --}, } }, { name = "Body Action Layer", weight = 1.0, blending = "Override", --mask = { --disabledJoints = { "base.body.front_leg", "base.body.back_leg" } --}, states = { { name = "StandardIdle", isDefault = true, clipName = "Standard", transitions = { { nextState = "Placing", offset = 0, duration = 0, conditions = { "Placing == true" } }, { nextState = "Eating", offset = 0, duration = 0, conditions = { "Eating == true" } }, { nextState = "HoldingItem", offset = 0, duration = 0.2, conditions = { "HoldingItem == true" } }, { nextState = "SwordAttacking", offset = 0, duration = 0, conditions = { "SwordAttacking == true" } } } }, { name = "HoldingItem", clipName = "HoldingItem", transitions = { { nextState = "Placing", offset = 0, duration = 0, conditions = { "Placing == true" } }, { nextState = "Eating", offset = 0, duration = 0, conditions = { "Eating == true" } }, { nextState = "StandardIdle", offset = 0, duration = 0.2, conditions = { "HoldingItem == false" } }, } }, { name = "Placing", clipName = "Placing", transitions = { { nextState = "HoldingItem", offset = 0.2499, duration = 0, conditions = { "HoldingItem == true" } }, { nextState = "StandardIdle", offset = 0.2499, duration = 0, }, { nextState = "StandardIdle", offset = 0, duration = 0, conditions = { "StopAction == true" } } } }, { name = "Eating", clipName = "Eating", transitions = { { nextState = "HoldingItem", offset = 0.2499, duration = 0, conditions = { "HoldingItem == true" } }, { nextState = "StandardIdle", offset = 0.2499, duration = 0, }, { nextState = "StandardIdle", offset = 0, duration = 0, conditions = { "StopAction == true" } } } }, { name = "SwordAttacking", clipName = "SwordAttacking", transitions = { { nextState = "StandardIdle", offset = 0.99, duration = 0, hasExitTime = false, }, { nextState = "StandardIdle", offset = 0, duration = 0, conditions = { "StopAction == true" } } } }, } } } } return AnimatorData2D.new(asm) end return PlayerAnimator ================================================ FILE: bone2d/PlayerBoneInfo.lua ================================================ ---@class TC.PlayerBoneInfo local PlayerBoneInfo = class("PlayerJointBody") local PlayerJoints = require("PlayerJoints") local PlayerClips = require("PlayerClips") local PlayerAnimator = require("PlayerAnimator") local ItemJointHelper = require("ItemJointHelper") local s_instance ---@return TC.PlayerBoneInfo function PlayerBoneInfo.getInstance() if s_instance == nil then s_instance = PlayerBoneInfo.new() end return s_instance end function PlayerBoneInfo:__init() self.body = JointBody2D.new(PlayerJoints.create()) self.body:setAnimator(PlayerClips.create(self.body.joints), PlayerAnimator.create()) end function PlayerBoneInfo:reload() self.body = JointBody2D.new(PlayerJoints.create()) self.body:setAnimator(PlayerClips.create(self.body.joints), PlayerAnimator.create()) end ---create ---@param skinTable table ---@return JointBody2D function PlayerBoneInfo.create(skinTable) local body = PlayerBoneInfo.getInstance().body:clone() PlayerBoneInfo.setSkin(body, skinTable) return body end function PlayerBoneInfo.getSkinTableByID(skinID) local skin = SkinUtils.GetSkin(skinID) return { head = skin.headTexture, body = skin.bodyTexture, leg = skin.legTexture, cloth = skin.clothTexture, hair = skin.hairTexture, pant = skin.pantTexture, } end function PlayerBoneInfo.createBySkinID(skinID) return PlayerBoneInfo.create(PlayerBoneInfo.getSkinTableByID(skinID)) end ---setSkin ---@param jointBody JointBody2D ---@param skinTable table function PlayerBoneInfo.setSkin(jointBody, skinTable) PlayerJoints.setSkin(jointBody.joints, skinTable) end function PlayerBoneInfo.setSkinByID(jointBody, skinID) PlayerBoneInfo.setSkin(jointBody, PlayerBoneInfo.getSkinTableByID(skinID)) end ---checkHandItem ---@param itemJoint Joint2D ---@param itemSlot Slot ---@param cacheTable table function PlayerBoneInfo.checkHandItem(itemJoint, itemSlot, cacheTable) ItemJointHelper.checkItem(itemJoint, itemSlot, cacheTable) end ---@param jointBody JointBody2D ---@param isBackHand boolean function PlayerBoneInfo.getItemJoint(jointBody, isBackHand) return isBackHand and jointBody.joints:getJoint("base.body.back_arm.back_hand.back_item") or jointBody.joints:getJoint("base.body.front_arm.front_hand.front_item") end return PlayerBoneInfo ================================================ FILE: bone2d/PlayerClips.lua ================================================ local PlayerClips = class("PlayerClips") ---getClips ---@param joints JointCollection2D ---@return ClipCollection2D function PlayerClips.create(joints) local clips = ClipCollection2D.new(joints) clips:addClip({ name = "Idle", time = 1.5, loop = true, jointClips = { { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.25, value = 0.0584 }, { time = 0.5, value = 0.0 }, { time = 0.7, value = -0.0425 }, { time = 0.9, value = 0.0 }, } } } }, { jointName = "base.body.head", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.25, value = -0.0584 }, { time = 0.5, value = 0.0 }, { time = 0.7, value = 0.0425 }, { time = 0.9, value = 0.0 }, } } } }, { jointName = "base.body.back_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.25, value = -0.0584 }, { time = 0.5, value = 0.0 }, { time = 0.7, value = 0.0425 }, { time = 0.9, value = 0.0 }, } } } }, { jointName = "base.body.back_leg.back_feet", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, } } } }, { jointName = "base.body.front_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.25, value = -0.0584 }, { time = 0.5, value = 0.0 }, { time = 0.7, value = 0.0425 }, { time = 0.9, value = 0.0 }, } } } }, { jointName = "base.body.front_leg.front_feet", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = -0.15 }, { time = 1.0, value = 0.0 }, } } } }, { jointName = "base.body.back_arm.back_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = 0.15 }, { time = 1.0, value = 0.0 }, } } } }, { jointName = "base.body.front_arm.front_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, } } } }, } }) clips:addClip({ name = "Walk", time = 0.6, loop = true, jointClips = { { jointName = "base.body.back_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.75 }, { time = 0.5, value = 0.5 }, { time = 1.0, value = -0.75 }, } } } }, { jointName = "base.body.back_leg.back_feet", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.25 }, { time = 0.5, value = 0.75 }, { time = 1.0, value = 0.25 }, } } } }, { jointName = "base.body.front_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.5 }, { time = 0.5, value = -0.85 }, { time = 1.0, value = 0.5 }, } } } }, { jointName = "base.body.front_leg.front_feet", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.75 }, { time = 0.5, value = 0.25 }, { time = 1.0, value = 0.75 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.5 }, { time = 0.5, value = 0.5 }, { time = 1.0, value = -0.5 }, } } } }, { jointName = "base.body.front_arm.front_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.5 }, { time = 0.5, value = 0.0 }, { time = 1.0, value = -0.5 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.25 }, { time = 0.5, value = -0.5 }, { time = 1.0, value = 0.25 }, } } } }, { jointName = "base.body.back_arm.back_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = -0.5 }, { time = 1.0, value = 0.0 }, } } } }, { jointName = "base.body.head", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.015 }, { time = 0.5, value = -0.015 }, { time = 1.0, value = 0.015 }, } } } }, { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = 0.05 }, { time = 1.0, value = 0.0 }, } } } }, } }) clips:addClip({ name = "Run", time = 0.69, loop = true, jointClips = { { jointName = "base.body.back_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.85 }, { time = 0.5, value = 0.5 }, { time = 1.0, value = -0.85 }, } } } }, { jointName = "base.body.back_leg.back_feet", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.05 }, { time = 0.5, value = 0.95 }, { time = 1.0, value = 0.05 }, } } } }, { jointName = "base.body.front_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.5 }, { time = 0.5, value = -0.85 }, { time = 1.0, value = 0.5 }, } } } }, { jointName = "base.body.front_leg.front_feet", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.95 }, { time = 0.5, value = 0.05 }, { time = 1.0, value = 0.95 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.5 }, { time = 0.5, value = 0.75 }, { time = 1.0, value = -0.5 }, } } } }, { jointName = "base.body.front_arm.front_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -1.25 }, { time = 0.5, value = -0.60 }, { time = 1.0, value = -1.25 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.25 }, { time = 0.5, value = -0.95 }, { time = 1.0, value = 0.25 }, } } } }, { jointName = "base.body.back_arm.back_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.4 }, { time = 0.5, value = -1.0 }, { time = 1.0, value = -0.4 }, } } } }, { jointName = "base.body.head", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.015 }, { time = 0.5, value = -0.015 }, { time = 1.0, value = 0.015 }, } } } }, { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = 0.1 }, { time = 1.0, value = 0.0 }, } } } }, } }) clips:addClip({ name = "JumpUp", time = 1.79, loop = true, jointClips = { { jointName = "base.body.back_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.75 }, { time = 0.5, value = -0.65 }, { time = 1.0, value = -0.75 }, } } } }, { jointName = "base.body.back_leg.back_feet", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.5 }, { time = 0.5, value = 0.6 }, { time = 1.0, value = 0.5 }, } } } }, { jointName = "base.body.front_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.15 }, { time = 0.5, value = 0.05 }, { time = 1.0, value = 0.15 }, } } } }, { jointName = "base.body.front_leg.front_feet", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.6 }, { time = 0.5, value = 0.5 }, { time = 1.0, value = 0.6 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -1.2 }, { time = 0.5, value = -1.1 }, { time = 1.0, value = -1.2 }, } } } }, { jointName = "base.body.back_arm.back_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.7 }, { time = 0.5, value = -0.8 }, { time = 1.0, value = -0.7 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 1.1 }, { time = 0.5, value = 1.0 }, { time = 1.0, value = 1.1 }, } } } }, { jointName = "base.body.front_arm.front_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.70 }, { time = 0.5, value = -0.60 }, { time = 1.0, value = -0.70 }, } } } }, { jointName = "base.body.head", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.05 }, { time = 0.5, value = -0.1 }, { time = 1.0, value = -0.05 }, } } } }, { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.10 }, { time = 0.5, value = -0.08 }, { time = 1.0, value = -0.10 }, } } } }, } }) clips:addClip({ name = "JumpDown", time = 1.79, loop = true, jointClips = { { jointName = "base.body.back_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.95 }, { time = 0.5, value = -0.85 }, { time = 1.0, value = -0.95 }, } } } }, { jointName = "base.body.back_leg.back_feet", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.5 }, { time = 0.5, value = 0.6 }, { time = 1.0, value = 0.5 }, } } } }, { jointName = "base.body.front_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.15 }, { time = 0.5, value = -0.05 }, { time = 1.0, value = -0.15 }, } } } }, { jointName = "base.body.front_leg.front_feet", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.16 }, { time = 0.5, value = 0.15 }, { time = 1.0, value = 0.16 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -2.4 }, { time = 0.5, value = -2.5 }, { time = 1.0, value = -2.4 }, } } } }, { jointName = "base.body.back_arm.back_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.0 }, { time = 0.5, value = -0.0 }, { time = 1.0, value = -0.0 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 1.2 }, { time = 0.5, value = 1.1 }, { time = 1.0, value = 1.2 }, } } } }, { jointName = "base.body.front_arm.front_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.50 }, { time = 0.5, value = -0.40 }, { time = 1.0, value = -0.50 }, } } } }, { jointName = "base.body.head", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.05 }, { time = 0.5, value = -0.1 }, { time = 1.0, value = -0.05 }, } } } }, { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.10 }, { time = 0.5, value = 0.08 }, { time = 1.0, value = 0.10 }, } } } }, } }) clips:addClip({ name = "JustOnGround", time = 0.5, loop = false, jointClips = { { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = 0.284 }, { time = 1.0, value = 0.0 }, } } } }, { jointName = "base.body.head", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.25, value = -0.0584 }, { time = 0.5, value = 0.0 }, { time = 0.7, value = 0.0425 }, { time = 0.9, value = 0.0 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -1.2 }, { time = 0.5, value = -1.1 }, { time = 1.0, value = -1.2 }, } } } }, { jointName = "base.body.back_arm.back_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.7 }, { time = 0.5, value = -0.8 }, { time = 1.0, value = -0.7 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 1.1 }, { time = 0.5, value = 1.0 }, { time = 1.0, value = 1.1 }, } } } }, { jointName = "base.body.front_arm.front_hand", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.70 }, { time = 0.5, value = -0.60 }, { time = 1.0, value = -0.70 }, } } } }, { jointName = "base.body.back_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = -0.284 }, { time = 1.0, value = 0.0 }, } } } }, { jointName = "base.body.front_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = -0.284 }, { time = 1.0, value = 0.0 }, } } } }, } }) clips:addClip({ name = "Death", time = 0.5, loop = false, jointClips = { { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineIn", value = 0.0 }, { time = 0.9, value = -1.57 }, } } } }, { jointName = "base.body.head", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineIn", value = 0.0 }, { time = 0.5, value = 0.5 }, { time = 0.9, value = -0.2 }, { time = 1.0, value = 0.0 }, } } } }, { jointName = "base.body.back_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = -1.3284 }, { time = 1.0, value = 0.0 }, } } } }, { jointName = "base.body.front_leg", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, value = -0.9284 }, { time = 0.9, value = 0.0 }, } } } }, { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, interpolation = "SineIn", value = -1.9284 }, { time = 1.0, value = 0.0 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 0.5, interpolation = "SineIn", value = -1.4284 }, { time = 1.0, value = 0.0 }, } } } }, } }) clips:addClip({ name = "HoldingItem", time = 0.51, loop = true, jointClips = { { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -1.0 }, { time = 0.5, value = -1.02 }, { time = 1.0, value = -1.0 }, } } } }, { jointName = "base.body.back_arm.back_hand.back_item", data = { { variable = "Angle", samples = { { time = 0.0, value = math.pi / 2 }, } } } }, } }) clips:addClip({ name = "SwordAttacking", time = 1.0, loop = false, jointClips = { { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -3.2 }, { time = 1.0, value = -0.3 }, } } } }, { jointName = "base.body.back_arm.back_hand", data = { { variable = "Angle", samples = { { time = 0.0, value = 0.0 }, } } } }, { jointName = "base.body.back_arm.back_hand.back_item", data = { { variable = "Angle", samples = { { time = 0.0, value = 2.4 }, } } } }, { jointName = "base.body.front_arm", data = { { variable = "Angle", samples = { { time = 0.0, value = 1.0 }, } } } }, { jointName = "base.body.front_arm.front_hand", data = { { variable = "Angle", samples = { { time = 0.0, value = -0.5 }, } } } }, { jointName = "base.body", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = 0.0 }, { time = 1.0, value = 0.1 }, } } } }, --{ -- jointName = "base.body.back_leg", -- data = { -- { -- variable = "Angle", -- samples = { -- { time = 0.0, interpolation = "SineInOut", value = 0.0 }, -- { time = 0.5, value = -0.1 }, -- { time = 1.0, value = 0.0 }, -- } -- } -- } --}, --{ -- jointName = "base.body.front_leg", -- data = { -- { -- variable = "Angle", -- samples = { -- { time = 0.0, interpolation = "SineInOut", value = 0.0 }, -- { time = 0.5, value = 0.1 }, -- { time = 0.9, value = 0.0 }, -- } -- } -- } --}, } }) clips:addClip({ name = "Placing", time = 0.25, loop = false, jointClips = { { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -4.0 }, { time = 1.0, value = -0.8 }, } } } } } }) clips:addClip({ name = "Eating", time = 0.25, loop = false, jointClips = { { jointName = "base.body.back_arm", data = { { variable = "Angle", samples = { { time = 0.0, interpolation = "SineInOut", value = -0.8 }, { time = 1.0, value = -4.0 }, } } } } } }) clips:addClip({ name = "Standard", time = 1.0, loop = true, jointClips = { { jointName = "base.body.back_arm.back_hand.back_item", data = { { variable = "Angle", samples = { { time = 0.0, value = math.pi / 2 }, } } } }, } }) return clips end return PlayerClips ================================================ FILE: bone2d/PlayerJoints.lua ================================================ local PlayerJoints = class("PlayerJoints") ---setSkin ---@param joints JointCollection2D ---@param textureTable table function PlayerJoints.setSkin(joints, textureTable) if not textureTable then return end local body = joints:getJoint("base.body") local head = body:getChild("head") local back_arm = body:getChild("back_arm") local back_hand = back_arm:getChild("back_hand") local front_arm = body:getChild("front_arm") local front_hand = front_arm:getChild("front_hand") local back_leg = body:getChild("back_leg") local back_feet = back_leg:getChild("back_feet") local front_leg = body:getChild("front_leg") local front_feet = front_leg:getChild("front_feet") head:clearTexture("skin") head:clearTexture("hair") head:clearTexture("hat") if textureTable.head ~= nil then head:setTexture("skin", textureTable.head, Vector2.new(-16, -14), Rect.new(0, 0, 48, 48)) end if textureTable.hair ~= nil then head:setTexture("hair", textureTable.hair, Vector2.new(-16, -14), Rect.new(0, 0, 48, 48)) end if textureTable.hat ~= nil then head:setTexture("hat", textureTable.hat, Vector2.new(-16, -14), Rect.new(0, 0, 48, 48)) end body:clearTexture("skin") body:clearTexture("cloth") if textureTable.body ~= nil then body:setTexture("skin", textureTable.body, Vector2.new(-16, -14), Rect.new(0, 0, 48, 48)) back_arm:setTexture("skin", textureTable.body, Vector2.new(-22, -14), Rect.new(144, 0, 48, 48)) back_hand:setTexture("skin", textureTable.body, Vector2.new(-22, -22), Rect.new(192, 0, 48, 48)) front_arm:setTexture("skin", textureTable.body, Vector2.new(-12, -16), Rect.new(48, 0, 48, 48)) front_hand:setTexture("skin", textureTable.body, Vector2.new(-14, -24), Rect.new(96, 0, 48, 48)) end if textureTable.cloth ~= nil then body:setTexture("cloth", textureTable.cloth, Vector2.new(-16, -14), Rect.new(0, 0, 48, 48)) back_arm:setTexture("cloth", textureTable.cloth, Vector2.new(-22, -14), Rect.new(144, 0, 48, 48)) back_hand:setTexture("cloth", textureTable.cloth, Vector2.new(-22, -22), Rect.new(192, 0, 48, 48)) front_arm:setTexture("cloth", textureTable.cloth, Vector2.new(-12, -16), Rect.new(48, 0, 48, 48)) front_hand:setTexture("cloth", textureTable.cloth, Vector2.new(-14, -24), Rect.new(96, 0, 48, 48)) end back_leg:clearTexture("skin") back_leg:clearTexture("pant") front_leg:clearTexture("skin") front_leg:clearTexture("pant") back_feet:clearTexture("skin") back_feet:clearTexture("shoe") front_feet:clearTexture("skin") front_feet:clearTexture("shoe") if textureTable.leg ~= nil then back_leg:setTexture("skin", textureTable.leg, Vector2.new(-20, -16), Rect.new(0, 0, 48, 48)) back_feet:setTexture("skin", textureTable.leg, Vector2.new(-20, -22), Rect.new(48, 0, 48, 48)) front_leg:setTexture("skin", textureTable.leg, Vector2.new(-20, -16), Rect.new(0, 0, 48, 48)) front_feet:setTexture("skin", textureTable.leg, Vector2.new(-20, -22), Rect.new(48, 0, 48, 48)) end if textureTable.pant ~= nil then back_leg:setTexture("pant", textureTable.pant, Vector2.new(-20, -16), Rect.new(0, 0, 48, 48)) back_feet:setTexture("shoe", textureTable.pant, Vector2.new(-20, -22), Rect.new(48, 0, 48, 48)) front_leg:setTexture("pant", textureTable.pant, Vector2.new(-20, -16), Rect.new(0, 0, 48, 48)) front_feet:setTexture("shoe", textureTable.pant, Vector2.new(-20, -22), Rect.new(48, 0, 48, 48)) end end function PlayerJoints.create(textureTable) local joints = JointCollection2D.new() joints.root = Joint2D.new("base", Vector2.new(8, 48), Size.new(16, 48)) local body = Joint2D.new("body", Vector2.new(6, 15), Size.new(12, 16)) joints.root:addChild(Vector2.new(8, 29), body) local backpack = Joint2D.new("backpack", Vector2.new(8, 8), Size.new(16, 16)) body:addChild(Vector2.new(0, 8), backpack, false) local back_arm = Joint2D.new("back_arm", Vector2.new(4, 4), Size.new(8, 10)) body:addChild(Vector2.new(10, 6), back_arm, false) local back_hand = Joint2D.new("back_hand", Vector2.new(3, 1), Size.new(8, 14)) back_arm:addChild(Vector2.new(3, 7), back_hand, false) local back_item = Joint2D.new("back_item", Vector2.new(8, 4), Size.new(32, 8)) back_hand:addChild(Vector2.new(4, 10), back_item, true) back_item.visible = false local head = Joint2D.new("head", Vector2.new(8, 13), Size.new(16, 16)) body:addChild(Vector2.new(6, -3), head, false) local back_leg = Joint2D.new("back_leg", Vector2.new(3, -1), Size.new(8, 8)) body:addChild(Vector2.new(7, 15), back_leg, false) local back_feet = Joint2D.new("back_feet", Vector2.new(7, 0), Size.new(10, 12)) back_leg:addChild(Vector2.new(7, 6), back_feet) local front_leg = Joint2D.new("front_leg", Vector2.new(3, -1), Size.new(8, 8)) body:addChild(Vector2.new(3, 15), front_leg, false) local front_feet = Joint2D.new("front_feet", Vector2.new(7, 0), Size.new(10, 12)) front_leg:addChild(Vector2.new(7, 6), front_feet) local front_arm = Joint2D.new("front_arm", Vector2.new(5, 4), Size.new(8, 10)) body:addChild(Vector2.new(1, 6), front_arm) local front_hand = Joint2D.new("front_hand", Vector2.new(3, 1), Size.new(8, 14)) front_arm:addChild(Vector2.new(5, 7), front_hand, false) local front_item = Joint2D.new("front_item", Vector2.new(8, 4), Size.new(32, 8)) front_hand:addChild(Vector2.new(4, 10), front_item, false) front_item.visible = false PlayerJoints.setSkin(joints, textureTable) return joints end return PlayerJoints ================================================ FILE: buffs/BaseBuffProxy.lua ================================================ ---@class TC.BaseBuffProxy local BaseBuffProxy = class("BaseBuffProxy") ---OnUpdatePlayer ---@param player Player ---@param buffRemainTime int function BaseBuffProxy.OnUpdatePlayer(player, buffRemainTime) end return BaseBuffProxy ================================================ FILE: buffs/BuffBlindness.lua ================================================ ---@class TC.BuffBlindness:TC.BaseBuffProxy local BuffBlindness = class("BuffBlindness", require("BaseBuffProxy")) function BuffBlindness.OnUpdatePlayer(player, _) -- Client effect only. if NetMode.current == NetMode.Server then return end if player.isCurrentClientPlayer then LightingUtils.SetState(LightingUtils.LIGHTING_STATE_BLINDNESS) end end return BuffBlindness ================================================ FILE: buffs/BuffFire.lua ================================================ ---@class TC.BuffFire:TC.BaseBuffProxy local BuffFire = class("BuffFire", require("BaseBuffProxy")) function BuffFire.OnUpdatePlayer(player, _) if not player:HasBuff(Reg.BuffID("fire_defense")) then local fireDefense = player.baseDefense.flameDefense local interval = 16 * (1 + fireDefense) if interval > 0 then if player.tickTime % interval == 0 then player:Strike(DeathReason.BURN, Attack.new(1, 0, 0), 0, false, false) end end end if NetMode.current == NetMode.Client then if player.tickTime % 8 == 0 then EffectUtils.Create(Reg.EffectID("flame_star"), player.randX, player.randY, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1) ) EffectUtils.Create(Reg.EffectID("fire_flame"), player.randX, player.randY, Utils.RandSym(1), -Utils.RandDouble(2), 0, Utils.RandDoubleArea(0.5, 0.5) ) end end end return BuffFire ================================================ FILE: buffs/BuffGlowing.lua ================================================ ---@class TC.BuffGlowing:TC.BaseBuffProxy local BuffGlowing = class("BuffGlowing", require("BaseBuffProxy")) function BuffGlowing.OnUpdatePlayer(player, _) -- Client effect only. if NetMode.current == NetMode.Server then return end if player.tickTime % 16 == 0 then EffectUtils.Create(Reg.EffectID("chip"), player.randX, player.randY, Utils.RandSym(2), Utils.RandDoubleArea(-4, 2), 0, Utils.RandDoubleArea(1, 2), 1.0, Color.Yellow ) end LightingUtils.AddDelay(player.centerXi, player.centerYi, 32, 28) end return BuffGlowing ================================================ FILE: buffs/BuffHappiness.lua ================================================ ---@class TC.BuffHappiness:TC.BaseBuffProxy local BuffHappiness = class("BuffHappiness", require("BaseBuffProxy")) function BuffHappiness.OnUpdatePlayer(player, _) if player.tickTime % 64 == 0 then EffectUtils.Create(Reg.EffectID("heal"), player.randX, player.randY, Utils.RandSym(1), Utils.RandDoubleArea(-2, 2), 0.0, 1.0, 1.0, Color.Red ) player:Heal(1, false) end end return BuffHappiness ================================================ FILE: buffs/BuffHealthBoost.lua ================================================ ---@class TC.BuffHealthBoost:TC.BaseBuffProxy local BuffHealthBoost = class("BuffHealthBoost", require("BaseBuffProxy")) function BuffHealthBoost.OnUpdatePlayer(player, _) if player.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("heal"), player.randX, player.randY, Utils.RandSym(1), Utils.RandDoubleArea(-2, 2), 0, 1.0, 1.0, Color.Red) player:Heal(1, false) end end return BuffHealthBoost ================================================ FILE: buffs/BuffHunger.lua ================================================ ---@class TC.BuffHunger:TC.BaseBuffProxy local BuffHunger = class("BuffHunger", require("BaseBuffProxy")) function BuffHunger.OnUpdatePlayer(player, _) if player.tickTime % 128 == 0 then player:DecFood(1) end if player.tickTime % 64 == 0 then EffectUtils.Create(Reg.EffectID("chip"), player.randX, player.y, Utils.RandSym(1), Utils.RandDoubleArea(-2, 2), Utils.RandSym(0.1), 2, 0.6, Color.new(32, 32, 32) ) end end return BuffHunger ================================================ FILE: buffs/BuffHurt.lua ================================================ ---@class TC.BuffHurt:TC.BaseBuffProxy local BuffHurt = class("BuffHurt", require("BaseBuffProxy")) function BuffHurt.OnUpdatePlayer(player, _) if player.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("chip"), player.randX, player.y, Utils.RandSym(1), Utils.RandDoubleArea(-2, 1), 0, 1, 0.5, Color.new(32, 32, 32) ) end if player.tickTime % 16 == 0 then player:Strike(DeathReason.BUFF, Attack.new(1, 0, 0), 0, false, false) end end return BuffHurt ================================================ FILE: buffs/BuffInvisibility.lua ================================================ ---@class TC.BuffInvisibility:TC.BaseBuffProxy local BuffInvisibility = class("BuffInvisibility", require("BaseBuffProxy")) function BuffInvisibility.OnUpdatePlayer(player, _) player.isInvisibility = true if player.tickTime % 16 == 0 then EffectUtils.Create(Reg.EffectID("chip"), player.randX, player.randY, Utils.RandSym(1), Utils.RandDoubleArea(-3, 3), Utils.RandSym(0.1), 2, 1.0, Color.new(100, 100, 200) ) end end return BuffInvisibility ================================================ FILE: buffs/BuffJumpBoost.lua ================================================ ---@class TC.BuffJumpBoost:TC.BaseBuffProxy local BuffJumpBoost = class("BuffJumpBoost", require("BaseBuffProxy")) function BuffJumpBoost.OnUpdatePlayer(player, _) player.jumpRate = player.jumpRate + 0.5 end return BuffJumpBoost ================================================ FILE: buffs/BuffLevitation.lua ================================================ ---@class TC.BuffLevitation:TC.BaseBuffProxy local BuffLevitation = class("BuffLevitation", require("BaseBuffProxy")) function BuffLevitation.OnUpdatePlayer(player, _) if not player.stand then if player.speedY > -1 then player.speedY = player.speedY - 0.2 else player.speedY = -1 end end if player.tickTime % 8 == 0 then EffectUtils.Create(Reg.EffectID("smoke"), player.randX, player.bottomY, Utils.RandSym(1), Utils.RandDouble(2), Utils.RandSym(0.1), 0.5) end end return BuffLevitation ================================================ FILE: buffs/BuffMiningFatigue.lua ================================================ ---@class TC.BuffMiningFatigue:TC.BaseBuffProxy local BuffMiningFatigue = class("BuffMiningFatigue", require("BaseBuffProxy")) function BuffMiningFatigue.OnUpdatePlayer(player, _) player.digSpeedRate = player.digSpeedRate + 0.5 if player.tickTime % 32 == 0 then EffectUtils.Create(Reg.EffectID("heal"), player.randX, player.randY, Utils.RandSym(1), Utils.RandDoubleArea(-2, 2), 0, 1.0, 1.0, Color.Yellow) end end return BuffMiningFatigue ================================================ FILE: buffs/BuffPoison.lua ================================================ ---@class TC.BuffPoison:TC.BaseBuffProxy local BuffPoison = class("BuffPoison", require("BaseBuffProxy")) function BuffPoison.OnUpdatePlayer(player, _) if player.tickTime % 16 == 0 then EffectUtils.Create(Reg.EffectID("poison"), player.randX, player.y, Utils.RandSym(1), Utils.RandDoubleArea(-2, 1), 0, 1, 0.5) end if player.tickTime % 16 == 0 then player:Strike(DeathReason.POISON, Attack.new(1, 0, 0), 0, false, false) end end return BuffPoison ================================================ FILE: buffs/BuffProxies.lua ================================================ ---@class TC.BuffProxies local BuffProxies = class("BuffProxies") local s_instance ---@return TC.BuffProxies function BuffProxies.getInstance() if s_instance == nil then s_instance = BuffProxies.new() end return s_instance end function BuffProxies:__init() ---@type TC.BaseBuffProxy[] self._proxies = {} end ---@param player Player function BuffProxies:OnUpdatePlayer(player) if not player:HasAnyBuff() then return end local buffs = player:GetBuffList() ---@param buff Buff for _, buff in each(buffs) do if buff.time > 0 then local proxy = self._proxies[buff.id] if proxy then proxy.OnUpdatePlayer(player, buff.time) end end end end ---@param npc Npc function BuffProxies:OnUpdateNpc(npc) end function BuffProxies:Register(idName, proxy) local id = Reg.BuffID(idName) self._proxies[id] = proxy end function BuffProxies:RegisterAll() self:Register("tc:fire", require("BuffFire")) self:Register("tc:blindness", require("BuffBlindness")) self:Register("tc:glowing", require("BuffGlowing")) self:Register("tc:happiness", require("BuffHappiness")) self:Register("tc:health_boost", require("BuffHealthBoost")) self:Register("tc:hunger", require("BuffHunger")) self:Register("tc:hurt", require("BuffHurt")) self:Register("tc:invisibility", require("BuffInvisibility")) self:Register("tc:jump_boost", require("BuffJumpBoost")) self:Register("tc:levitation", require("BuffLevitation")) self:Register("tc:mining_fatique", require("BuffMiningFatigue")) self:Register("tc:poison", require("BuffPoison")) self:Register("tc:regeneration", require("BuffRegeneration")) self:Register("tc:resistance", require("BuffResistance")) self:Register("tc:sadness", require("BuffSadness")) self:Register("tc:slow_falling", require("BuffSlowFalling")) self:Register("tc:slow_mining", require("BuffSlowMining")) self:Register("tc:slowness", require("BuffSlowness")) self:Register("tc:speed", require("BuffSpeed")) self:Register("tc:strength", require("BuffStrength")) self:Register("tc:weak", require("BuffWeak")) self:Register("tc:wither", require("BuffWither")) self:Register("tc:vision", require("BuffVision")) end return BuffProxies ================================================ FILE: buffs/BuffRegeneration.lua ================================================ ---@class TC.BuffRegeneration:TC.BaseBuffProxy local BuffRegeneration = class("BuffRegeneration", require("BaseBuffProxy")) function BuffRegeneration.OnUpdatePlayer(player, _) if player.tickTime % 8 == 0 then EffectUtils.Create(Reg.EffectID("heal"), player.randX, player.randY, Utils.RandSym(1), Utils.RandDoubleArea(-2, 2), 0, 1, 1, Color.Red) player:Heal(1, false) end end return BuffRegeneration ================================================ FILE: buffs/BuffResistance.lua ================================================ ---@class TC.BuffResistance:TC.BaseBuffProxy local BuffResistance = class("BuffResistance", require("BaseBuffProxy")) function BuffResistance.OnUpdatePlayer(player, _) player.baseDefense.defense = player.baseDefense.defense + 4 end return BuffResistance ================================================ FILE: buffs/BuffSadness.lua ================================================ ---@class TC.BuffSadness:TC.BaseBuffProxy local BuffSadness = class("BuffSadness", require("BaseBuffProxy")) function BuffSadness.OnUpdatePlayer(player, _) player.baseDefense.defense = math.max(player.baseDefense.defense - 2, 0) end return BuffSadness ================================================ FILE: buffs/BuffSlowFalling.lua ================================================ ---@class TC.BuffSlowFalling:TC.BaseBuffProxy local BuffSlowFalling = class("BuffSlowFalling", require("BaseBuffProxy")) function BuffSlowFalling.OnUpdatePlayer(player, _) player.fallSpeedRate = player.fallSpeedRate - 0.75 if player.speedY > 1 then if player.tickTime % 8 == 0 then EffectUtils.Create(Reg.EffectID("chip"), player.randX, player.bottomY, Utils.RandSym(1), Utils.RandDoubleArea(2, 2), Utils.RandSym(0.1), 2, 0.6, Color.new(200, 200, 200) ) end end end return BuffSlowFalling ================================================ FILE: buffs/BuffSlowMining.lua ================================================ ---@class TC.BuffSlowMining:TC.BaseBuffProxy local BuffSlowMining = class("BuffSlowMining", require("BaseBuffProxy")) function BuffSlowMining.OnUpdatePlayer(player, _) player.digSpeedRate = player.digSpeedRate - 0.5 if player.tickTime % 32 == 0 then EffectUtils.Create(Reg.EffectID("heal"), player.randX, player.randY, Utils.RandSym(1), Utils.RandDoubleArea(-2, 2), 0, 1, 1, Color.new(32, 32, 32)) end end return BuffSlowMining ================================================ FILE: buffs/BuffSlowness.lua ================================================ ---@class TC.BuffSlowness:TC.BaseBuffProxy local BuffSlowness = class("BuffSlowness", require("BaseBuffProxy")) function BuffSlowness.OnUpdatePlayer(player, _) player.speedRate = player.speedRate - 0.4 end return BuffSlowness ================================================ FILE: buffs/BuffSpeed.lua ================================================ ---@class TC.BuffSpeed:TC.BaseBuffProxy local BuffSpeed = class("BuffSpeed", require("BaseBuffProxy")) function BuffSpeed.OnUpdatePlayer(player, _) player.speedRate = player.speedRate + 0.6 if math.abs(player.speedX) > 2 then if player.tickTime % 4 == 0 then if player.stand then EffectUtils.Create(Reg.EffectID("smoke"), player.randX, player.bottomY, Utils.RandSym(0.25), Utils.RandSym(0.25), Utils.RandSym(0.1), 0.25) else EffectUtils.Create(Reg.EffectID("smoke"), player.randX, player.randY, -player.speedX / 8 + Utils.RandSym(0.5), -player.speedY / 8 + Utils.RandSym(0.5), Utils.RandSym(0.1), 0.5) end end end end return BuffSpeed ================================================ FILE: buffs/BuffStrength.lua ================================================ ---@class TC.BuffStrength:TC.BaseBuffProxy local BuffStrength = class("BuffStrength", require("BaseBuffProxy")) function BuffStrength.OnUpdatePlayer(player, _) player.baseAttack.attack = player.baseAttack.attack + 3 end return BuffStrength ================================================ FILE: buffs/BuffVision.lua ================================================ ---@class TC.BuffVision:TC.BaseBuffProxy local BuffVision = class("BuffVision", require("BaseBuffProxy")) function BuffVision.OnUpdatePlayer(player, _) if player.isCurrentClientPlayer then LightingUtils.SetState(LightingUtils.LIGHTING_STATE_NIGHT_VISION) end end return BuffVision ================================================ FILE: buffs/BuffWeak.lua ================================================ ---@class TC.BuffWeak:TC.BaseBuffProxy local BuffWeak = class("BuffWeak", require("BaseBuffProxy")) function BuffWeak.OnUpdatePlayer(player, _) player.baseAttack.attack = math.max(player.baseAttack.attack - 8, 0) end return BuffWeak ================================================ FILE: buffs/BuffWither.lua ================================================ ---@class TC.BuffWither:TC.BaseBuffProxy local BuffWither = class("BuffWither", require("BaseBuffProxy")) function BuffWither.OnUpdatePlayer(player, _) if player.tickTime % 16 == 0 then EffectUtils.Create(Reg.EffectID("chip"), player.randX, player.y, Utils.RandSym(1), Utils.RandDoubleArea(-2, 1), 0, 1, 0.5, Color.new(32, 32, 32)) player:Strike(DeathReason.BUFF, Attack.new(1, 0, 0), 0, false, false) end end return BuffWither ================================================ FILE: buffs/absorption.json ================================================ { "absorption": { "textureData": "absorption.png" } } ================================================ FILE: buffs/blindness.json ================================================ { "blindness": { "textureData": "blindness.png" } } ================================================ FILE: buffs/fire.json ================================================ { "fire": { "textureData": "fire.png" } } ================================================ FILE: buffs/fire_defense.json ================================================ { "fire_defense": { "textureData": "fire_defense.png" } } ================================================ FILE: buffs/glowing.json ================================================ { "glowing": { "textureData": "glowing.png" } } ================================================ FILE: buffs/happiness.json ================================================ { "happiness": { "textureData": "happiness.png" } } ================================================ FILE: buffs/health_boost.json ================================================ { "health_boost": { "textureData": "health_boost.png" } } ================================================ FILE: buffs/health_cold.json ================================================ { "health_cold": { "textureData": "health_cold.png" } } ================================================ FILE: buffs/hunger.json ================================================ { "hunger": { "textureData": "hunger.png" } } ================================================ FILE: buffs/hurt.json ================================================ { "hurt": { "textureData": "hurt.png" } } ================================================ FILE: buffs/invisibility.json ================================================ { "invisibility": { "textureData": "invisibility.png" } } ================================================ FILE: buffs/jump_boost.json ================================================ { "jump_boost": { "textureData": "jump_boost.png" } } ================================================ FILE: buffs/levitation.json ================================================ { "levitation": { "textureData": "levitation.png" } } ================================================ FILE: buffs/luck.json ================================================ { "luck": { "textureData": "luck.png" } } ================================================ FILE: buffs/mining_fatique.json ================================================ { "mining_fatique": { "textureData": "mining_fatique.png" } } ================================================ FILE: buffs/nausea.json ================================================ { "nausea": { "textureData": "nausea.png" } } ================================================ FILE: buffs/poison.json ================================================ { "poison": { "textureData": "poison.png" } } ================================================ FILE: buffs/regeneration.json ================================================ { "regeneration": { "textureData": "regeneration.png" } } ================================================ FILE: buffs/resistance.json ================================================ { "resistance": { "textureData": "resistance.png" } } ================================================ FILE: buffs/sadness.json ================================================ { "sadness": { "textureData": "sadness.png" } } ================================================ FILE: buffs/slow_falling.json ================================================ { "slow_falling": { "textureData": "slow_falling.png", "script": { "path": "slow_falling.lua" } } } ================================================ FILE: buffs/slow_mining.json ================================================ { "slow_mining": { "textureData": "slow_mining.png", "script": { "path": "slow_mining.lua" } } } ================================================ FILE: buffs/slowness.json ================================================ { "slowness": { "textureData": "slowness.png", "script": { "path": "slowness.lua" } } } ================================================ FILE: buffs/speed.json ================================================ { "speed": { "textureData": "speed.png", "script": { "path": "speed.lua" } } } ================================================ FILE: buffs/strength.json ================================================ { "strength": { "textureData": "strength.png", "script": { "path": "strength.lua" } } } ================================================ FILE: buffs/vision.json ================================================ { "vision": { "textureData": "vision.png", "script": { "path": "vision.lua" } } } ================================================ FILE: buffs/water_breathing.json ================================================ { "water_breathing": { "textureData": "water_breathing.png" } } ================================================ FILE: buffs/weak.json ================================================ { "weak": { "textureData": "weak.png", "script": { "path": "weak.lua" } } } ================================================ FILE: buffs/wither.json ================================================ { "wither": { "textureData": "wither.png", "script": { "path": "wither.lua" } } } ================================================ FILE: buildings/aurora_palace/aurora_palace.json ================================================ { "aurora_palace": { "maxGenPartCount": 40, "limitSize": 1000, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 0 ] ] }, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [ { "itemId": "rocket_boost", "count": 1 }, { "itemId": "strange_eye", "count": 1 }, { "itemId": "ender_mirror", "count": 1 }, { "itemId": "wooden_sword", "count": 1 }, { "itemId": "stone_sword", "count": 1 }, { "itemId": "wooden_axe", "count": 1 }, { "itemId": "stone_axe", "count": 1 }, { "itemId": "wooden_pickaxe", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 }, { "itemId": "wooden_bow", "count": 1 }, { "itemId": "wooden_boomerang", "count": 1 }, { "itemId": "torch", "count": 24 }, { "itemId": "glow_bomb", "count": 2 }, { "itemId": "glow_ball", "count": 6 }, { "itemId": "book", "count": 3 }, { "itemId": "grenade", "count": 3 }, { "itemId": "amethyst_staff", "count": 1 }, { "itemId": "water_staff", "count": 1 } ], "normals": [ { "itemIds": [ "ender_pearl" ], "rate": 0.3, "min": 1, "max": 2 }, { "itemIds": [ "sand" ], "rate": 0.5, "min": 1, "max": 4 }, { "itemIds": [ "sugar_cane" ], "rate": 0.5, "min": 1, "max": 3 }, { "itemIds": [ "ice" ], "rate": 0.4, "min": 1, "max": 2 }, { "itemIds": [ "blue_ice" ], "rate": 0.3, "min": 1, "max": 3 }, { "itemIds": [ "stick" ], "rate": 0.3, "min": 1, "max": 12 }, { "itemIds": [ "glowstone_dust" ], "rate": 0.3, "min": 3, "max": 12 }, { "itemIds": [ "coal", "charcoal" ], "rate": 0.26, "min": 1, "max": 12 }, { "itemIds": [ "redstone" ], "rate": 0.26, "min": 1, "max": 4 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 1, "max": 4 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.1, "min": 1, "max": 4 }, { "itemIds": [ "wooden_arrow" ], "rate": 0.4, "min": 2, "max": 7 }, { "itemIds": [ "ice_arrow" ], "rate": 0.4, "min": 2, "max": 7 }, { "itemIds": [ "ice_bow" ], "rate": 0.3, "min": 1, "max": 1 } ] } } }, "rewards": [ ], "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "aurora_block" ], [ "BC_PLACE_FURNITURE", "chest", 0, "normal_reward" ] ] }, { "color": [ 255, 244, 0, 0 ], "note": "女王球", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "aurora_block" ], [ "BC_PLACE_FURNITURE", "snow_glass_ball" ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "主方块前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "aurora_block" ], [ "BC_PLACE_TILE", "aurora_block" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "主方块后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "aurora_block" ] ] }, { "color": [ 255, 188, 188, 188 ], "note": "柱前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "aurora_pillar" ], [ "BC_PLACE_TILE", "aurora_pillar" ] ] }, { "color": [ 255, 144, 144, 144 ], "note": "柱后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "aurora_pillar" ] ] }, { "color": [ 255, 188, 144, 144 ], "note": "木板前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "aurora_block" ], [ "BC_PLACE_TILE", "plank_birch" ] ] }, { "color": [ 255, 0, 0, 222 ], "note": "浮冰", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "aurora_block" ], [ "BC_PLACE_TILE", "ice_packed" ] ] }, { "color": [ 255, 0, 0, 122 ], "note": "冰", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "aurora_block" ], [ "BC_PLACE_TILE", "ice" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1" ], "type": "PT_START", "hotX": 60, "hotY": 50, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r1", "image": [ "r1", "r1_o1", "r1_o2", "r1_o3", "r1_o4", "r1_o5", "r1_o6" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r2", "image": [ "r2", "r2_o1", "r2_o2", "r2_o3", "r2_o4", "r2_o5" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r3", "image": [ "r3", "r3_o1", "r3_o2", "r3_o3", "r3_o4", "r3_o5" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r4", "image": [ "r4", "r4_o1", "r4_o2", "r4_o3" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r5", "image": [ "r5", "r5_o1", "r5_o2", "r5_o3" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r6", "image": [ "r6", "r4_o1", "r4_o2", "r4_o3" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r7", "image": [ "r7", "r5_o1", "r5_o2", "r5_o3" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r8", "image": [ "r8" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r9", "image": [ "r9" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "e1", "image": [ "e1", "e1_o1", "e1_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e2", "image": [ "e2", "e1_o1", "e1_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 } ] } } ================================================ FILE: buildings/by_house/by_house.json ================================================ { "by_house": { "maxGenPartCount": 50, "limitSize": 300, "rewards": [ { "name": "normal_reward", "rareGenCount": 1, "rares": [ { "itemId": "stone_sword", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 }, { "itemId": "wooden_bow", "count": 1 }, { "itemId": "cross_bow", "count": 1 } ], "normals": [ { "itemIds": [ "wood_dark_oak" ], "rate": 0.9, "min": 3, "max": 5 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 3, "max": 10 }, { "itemIds": [ "potato" ], "rate": 0.5, "min": 3, "max": 6 }, { "itemIds": [ "wheat" ], "rate": 0.7, "min": 3, "max": 6 }, { "itemIds": [ "carrot" ], "rate": 0.5, "min": 3, "max": 6 }, { "itemIds": [ "string" ], "rate": 0.4, "min": 2, "max": 7 }, { "itemIds": [ "wooden_arrow" ], "rate": 0.4, "min": 2, "max": 7 } ] } ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "note": "箱子", "command": [ ] }, { "color": [ 255, 102, 102, 204 ], "note": "橡木门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_oak" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "橡木平台", "command": [ [ "BC_PLACE_TILE", "platform_oak" ] ] }, { "color": [ 255, 50, 50, 100 ], "note": "有空气就放水", "command": [ [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 54, 40, 27 ], "note": "有空气就放泥土", "command": [ [ "BC_CLEAR_FURNITURE" ], [ "BC_PLACE_TILE", "dirt" ] ] }, { "color": [ 255, 54, 100, 27 ], "note": "有空气就放草泥土", "command": [ [ "BC_CLEAR_FURNITURE" ], [ "BC_PLACE_TILE", "dirt", 1 ] ] }, { "color": [ 255, 40, 30, 20 ], "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "wood_dark_oak" ], [ "BC_PLACE_TILE", "wood_dark_oak" ] ] }, { "color": [ 255, 20, 15, 11 ], "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "wood_dark_oak" ] ] }, { "color": [ 255, 70, 50, 20 ], "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_dark_oak" ], [ "BC_PLACE_TILE", "plank_dark_oak" ] ] }, { "color": [ 255, 44, 32, 13 ], "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_dark_oak" ] ] }, { "color": [ 255, 120, 98, 60 ], "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "wood_stripped_oak" ] ] }, { "color": [ 255, 130, 70, 50 ], "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "brick" ], [ "BC_PLACE_TILE", "brick" ] ] }, { "color": [ 255, 88, 49, 37 ], "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "brick" ] ] }, { "color": [ 255, 222, 222, 244 ], "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "glass" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance" ], "type": "PT_START", "hotX": 100, "hotY": 94, "unlinkParts": [ "entrance" ], "weight": 10 } ] } } ================================================ FILE: buildings/desert_house/desert_house.json ================================================ { "desert_house": { "maxGenPartCount": 1, "limitSize": 100, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [], "normals": [ { "itemIds": [ "water_staff", "amethyst_staff" ], "rate": 0.54, "min": 1, "max": 1 }, { "itemIds": [ "ender_pearl" ], "rate": 0.3, "min": 1, "max": 2 }, { "itemIds": [ "bread" ], "rate": 0.40, "min": 1, "max": 4 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.2, "min": 1, "max": 3 }, { "itemIds": [ "emerald" ], "rate": 0.15, "min": 1, "max": 1 }, { "itemIds": [ "iron_helmet" ], "rate": 0.15, "min": 1, "max": 1 }, { "itemIds": [ "iron_chestplate" ], "rate": 0.15, "min": 1, "max": 1 }, { "itemIds": [ "iron_leggings" ], "rate": 0.15, "min": 1, "max": 1 }, { "itemIds": [ "raw_porkchop" ], "rate": 0.24, "min": 1, "max": 3 }, { "itemIds": [ "raw_mutton" ], "rate": 0.24, "min": 1, "max": 3 }, { "itemIds": [ "raw_beef" ], "rate": 0.24, "min": 1, "max": 3 }, { "itemIds": [ "wheat" ], "rate": 0.24, "min": 1, "max": 3 }, { "itemIds": [ "coal", "charcoal" ], "rate": 0.13, "min": 1, "max": 3 }, { "itemIds": [ "paper", "book" ], "rate": 0.3, "min": 1, "max": 5 }, { "itemIds": [ "stick" ], "rate": 0.3, "min": 1, "max": 2 }, { "itemIds": [ "sapling_oak" ], "rate": 0.2, "min": 1, "max": 2 }, { "itemIds": [ "raw_salmon" ], "rate": 0.2, "min": 1, "max": 3 }, { "itemIds": [ "raw_cod" ], "rate": 0.2, "min": 1, "max": 3 }, { "itemIds": [ "bucket_water" ], "rate": 0.2, "min": 1, "max": 3 }, { "itemIds": [ "feather" ], "rate": 0.25, "min": 1, "max": 3 }, { "itemIds": [ "wooden_arrow" ], "rate": 0.12, "min": 1, "max": 3 }, { "itemIds": [ "dye_yellow" ], "rate": 0.12, "min": 1, "max": 1 }, { "itemIds": [ "dye_green" ], "rate": 0.12, "min": 1, "max": 1 } ] } } }, "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 130, 0, 0 ], "note": "桶", "command": [ [ "BC_PLACE_FURNITURE", "barrel", 0, "normal_reward" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 2 ] ] }, { "color": [ 255, 0, 255, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "chest", 0, "normal_reward" ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "橡木门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_birch" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_sandstone" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "fire_lamp" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_birch" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_birch", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_birch", 0 ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_birch", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_birch", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_birch" ] ] }, { "color": [ 255, 50, 50, 100 ], "note": "有空气就放水", "command": [ [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 54, 40, 27 ], "note": "有空气就放沙石", "command": [ [ "BC_CLEAR_FURNITURE" ], [ "BC_PLACE_TILE", "sandstone" ] ] }, { "color": [ 255, 120, 30, 30 ], "note": "主前景1", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "sandstone_smooth", 1 ], [ "BC_PLACE_TILE", "sandstone_smooth" ] ] }, { "color": [ 255, 40, 0, 0 ], "note": "主后景1", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "sandstone_smooth", 1 ] ] }, { "color": [ 255, 100, 100, 100 ], "note": "木板前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_spruce", 1 ], [ "BC_PLACE_TILE", "plank_spruce" ] ] }, { "color": [ 255, 10, 10, 10 ], "note": "木板后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "fence_spruce", 1 ] ] }, { "color": [ 255, 222, 222, 244 ], "note": "玻璃后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "glass", 1 ] ] }, { "color": [ 255, 128, 64, 64 ], "note": "木头前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_dark_oak", 1 ], [ "BC_PLACE_TILE", "plank_dark_oak" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance2" ], "weight": 100 }, { "name": "entrance3", "image": [ "entrance3", "entrance3_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance3" ], "weight": 10 }, { "name": "entrance4", "image": [ "entrance4", "entrance4_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance4" ], "weight": 10 } ] } } ================================================ FILE: buildings/end_outpost/end_outpost.json ================================================ { "end_outpost": { "maxGenPartCount": 1, "limitSize": 100, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [ { "itemId": "iron_sword", "count": 1 }, { "itemId": "iron_axe", "count": 1 }, { "itemId": "iron_pickaxe", "count": 1 } ], "normals": [ { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.4, "min": 4, "max": 8 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.5, "min": 2, "max": 6 }, { "itemIds": [ "ender_pearl" ], "rate": 0.7, "min": 1, "max": 2 }, { "itemIds": [ "diamond" ], "rate": 0.2, "min": 1, "max": 2 }, { "itemIds": [ "emerald" ], "rate": 0.1, "min": 2, "max": 6 }, { "itemIds": [ "iron_helmet", "iron_chestplate", "iron_leggings" ], "rate": 0.1, "min": 1, "max": 1 } ] } } }, "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "end_rod", 0 ] ] }, { "color": [ 255, 0, 160, 255 ], "note": "潜影盒", "command": [ [ "BC_PLACE_FURNITURE", "shulker_box", 0, "normal_reward" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_purpur" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 50, 50, 100 ], "note": "有空气就放水", "command": [ [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 54, 40, 27 ], "note": "有空气就放腐化石", "command": [ [ "BC_CLEAR_FURNITURE" ], [ "BC_PLACE_TILE", "tainted_stone" ] ] }, { "color": [ 255, 120, 30, 30 ], "note": "主前景1", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "purpur_block" ], [ "BC_PLACE_TILE", "purpur_block" ] ] }, { "color": [ 255, 40, 0, 0 ], "note": "主后景1", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "purpur_block" ] ] }, { "color": [ 255, 100, 100, 100 ], "note": "末地砖前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "end_stone_brick" ], [ "BC_PLACE_TILE", "end_stone_brick" ] ] }, { "color": [ 255, 10, 10, 10 ], "note": "末地砖后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "end_stone_brick" ] ] }, { "color": [ 255, 222, 222, 244 ], "note": "玻璃后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stained_glass_magenta" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance2" ], "weight": 10 }, { "name": "entrance3", "image": [ "entrance3", "entrance3_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance3" ], "weight": 10 }, { "name": "entrance4", "image": [ "entrance4", "entrance4_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance4" ], "weight": 10 }, { "name": "entrance5", "image": [ "entrance5", "entrance5_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance5" ], "weight": 10 } ] } } ================================================ FILE: buildings/forest_house/forest_house.json ================================================ { "forest_house": { "maxGenPartCount": 50, "limitSize": 300, "rewards": [ { "name": "normal_reward", "rareGenCount": 1, "rares": [ { "itemId": "stone_sword", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 }, { "itemId": "wooden_bow", "count": 1 }, { "itemId": "cross_bow", "count": 1 } ], "normals": [ { "itemIds": [ "wood_dark_oak" ], "rate": 0.9, "min": 3, "max": 5 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 3, "max": 10 }, { "itemIds": [ "potato" ], "rate": 0.5, "min": 3, "max": 6 }, { "itemIds": [ "wheat" ], "rate": 0.7, "min": 3, "max": 6 }, { "itemIds": [ "carrot" ], "rate": 0.5, "min": 3, "max": 6 }, { "itemIds": [ "string" ], "rate": 0.4, "min": 2, "max": 7 }, { "itemIds": [ "wooden_arrow" ], "rate": 0.4, "min": 2, "max": 7 } ] } ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "note": "箱子", "command": [ ] }, { "color": [ 255, 102, 102, 204 ], "note": "橡木门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_oak" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "橡木平台", "command": [ [ "BC_PLACE_TILE", "platform_oak" ] ] }, { "color": [ 255, 50, 50, 100 ], "note": "有空气就放水", "command": [ [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 54, 40, 27 ], "note": "有空气就放泥土", "command": [ [ "BC_CLEAR_FURNITURE" ], [ "BC_PLACE_TILE", "dirt" ] ] }, { "color": [ 255, 54, 100, 27 ], "note": "有空气就放草泥土", "command": [ [ "BC_CLEAR_FURNITURE" ], [ "BC_PLACE_TILE", "dirt", 1 ] ] }, { "color": [ 255, 120, 30, 30 ], "note": "木板前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_oak" ], [ "BC_PLACE_TILE", "plank_oak" ] ] }, { "color": [ 255, 40, 0, 0 ], "note": "木板后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_oak" ] ] }, { "color": [ 255, 100, 100, 100 ], "note": "石砖前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick" ], [ "BC_PLACE_TILE", "stone_brick" ] ] }, { "color": [ 255, 100, 0, 0 ], "note": "红砖前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "brick" ], [ "BC_PLACE_TILE", "brick" ] ] }, { "color": [ 255, 100, 66, 66 ], "note": "木板前景石砖后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick" ], [ "BC_PLACE_TILE", "plank_oak" ] ] }, { "color": [ 255, 10, 10, 10 ], "note": "石砖后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick" ] ] }, { "color": [ 255, 222, 222, 244 ], "note": "玻璃后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "glass" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1" ], "type": "PT_START", "hotX": 50, "hotY": 43, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h1", "image": "h1", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h2", "image": "h2", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h3", "image": "h3", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h4", "image": "h4", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h5", "image": "h5", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h6", "image": "h6", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h7", "image": "h7", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h8", "image": "h8", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h9", "image": "h9", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h10", "image": "h10", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h11", "image": "h11", "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h12", "image": "h12", "type": "PT_END", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h13", "image": "h13", "type": "PT_END", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h14", "image": "h14", "type": "PT_END", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "h15", "image": "h15", "type": "PT_END", "unlinkParts": [ "entrance" ], "weight": 10 } ] } } ================================================ FILE: buildings/fossils/fossils.json ================================================ { "fossils": { "maxGenPartCount": 1, "limitSize": 15, "rewards": [], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 150, 150, 150 ], "note": "后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "bone_block" ] ] }, { "color": [ 255, 200, 200, 200 ], "note": "前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_TILE", "bone_block" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance3", "image": [ "entrance3" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance4", "image": [ "entrance4" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance5", "image": [ "entrance5" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance6", "image": [ "entrance6" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance7", "image": [ "entrance7" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance8", "image": [ "entrance8" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance9", "image": [ "entrance9" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance10", "image": [ "entrance10" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance11", "image": [ "entrance11" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance12", "image": [ "entrance12" ], "type": "PT_START", "hotX": 7, "hotY": 7, "unlinkParts": [ "entrance" ], "weight": 10 } ] } } ================================================ FILE: buildings/heart/heart.json ================================================ { "heart": { "maxGenPartCount": 1, "limitSize": 15, "rewards": [], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR_FRONT" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 255, 255, 0 ], "note": "", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_FURNITURE", "health_crystal", 0 ] ] }, { "color": [ 255, 120, 30, 30 ], "note": "前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick_cracked" ], [ "BC_PLACE_TILE", "stone_brick_cracked" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance" ], "type": "PT_START", "hotX": 7, "hotY": 12, "unlinkParts": [ "entrance" ], "weight": 10 } ] } } ================================================ FILE: buildings/jungle_temple/jungle_temple.json ================================================ { "jungle_temple": { "maxGenPartCount": 1, "limitSize": 200, "rewards": [ { "name": "normal_reward", "rareGenCount": 1, "rares": [ { "itemId": "stone_sword", "count": 1 }, { "itemId": "stone_axe", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 }, { "itemId": "wooden_bow", "count": 1 }, { "itemId": "book", "count": 8 }, { "itemId": "amethyst_staff", "count": 1 }, { "itemId": "water_staff", "count": 1 } ], "normals": [ { "itemIds": [ "ender_pearl" ], "rate": 0.3, "min": 1, "max": 2 }, { "itemIds": [ "bone" ], "rate": 0.6, "min": 4, "max": 6 }, { "itemIds": [ "rotten_flesh" ], "rate": 0.5, "min": 3, "max": 8 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.4, "min": 1, "max": 5 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.5, "min": 2, "max": 7 }, { "itemIds": [ "stick" ], "rate": 0.5, "min": 1, "max": 3 }, { "itemIds": [ "diamond" ], "rate": 0.12, "min": 1, "max": 3 }, { "itemIds": [ "emerald" ], "rate": 0.1, "min": 1, "max": 3 } ] }, { "name": "trap", "rareGenCount": 0, "rares": [], "normals": [ { "itemIds": [ "wooden_arrow", "blood_arrow" ], "rate": 1.0, "min": 8, "max": 16 } ] } ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "陷阱箱(砍了)", "command": [ [ "BC_PLACE_CHEST", "trapped_chest", "normal_reward" ], [ "BC_PLACE_WIRE", 1, 0 ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "发射器左", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "cobblestone" ], ] }, { "color": [ 255, 255, 255, 0 ], "note": "发射器右", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "cobblestone" ], ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 0 ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_stone_brick" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 0, 168 ], "note": "踏板", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "cobblestone" ], [ "BC_PLACE_FURNITURE", "pressure_plate_stone" ] ] }, { "color": [ 255, 255, 50, 50 ], "note": "红石线", "command": [ [ "BC_PLACE_WIRE", 1, 0 ] ] }, { "color": [ 255, 50, 50, 100 ], "note": "有空气就放水", "command": [ [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 54, 40, 27 ], "note": "有空气就放泥", "command": [ [ "BC_CLEAR_FURNITURE" ], [ "BC_PLACE_TILE", "coarse_dirt" ] ] }, { "color": [ 255, 120, 30, 30 ], "note": "主前景1", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "cobblestone" ], [ "BC_PLACE_TILE", "cobblestone" ] ] }, { "color": [ 255, 40, 0, 0 ], "note": "主后景1", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "cobblestone" ] ] }, { "color": [ 255, 100, 100, 100 ], "note": "前景2", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "cobblestone_mossy" ], [ "BC_PLACE_TILE", "cobblestone_mossy" ] ] }, { "color": [ 255, 10, 10, 10 ], "note": "后景2", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "cobblestone_mossy" ] ] }, { "color": [ 255, 222, 222, 244 ], "note": "玻璃后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stained_glass_magenta" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1" ], "type": "PT_START", "hotX": 95, "hotY": 45, "unlinkParts": [ "entrance" ], "weight": 10 } ] } } ================================================ FILE: buildings/mineshaft/mineshaft.json ================================================ { "mineshaft": { "maxGenPartCount": 2, "limitSize": 350, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 0 ] ] }, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [ { "itemId": "stone_sword", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 }, { "itemId": "iron_pickaxe", "count": 1 }, { "itemId": "torch", "count": 12 }, { "itemId": "yellow_torch", "count": 6 } ], "normals": [ { "itemIds": [ "bread" ], "rate": 0.44, "min": 1, "max": 3 }, { "itemIds": [ "coal", "charcoal" ], "rate": 0.3, "min": 3, "max": 8 }, { "itemIds": [ "pumpkin_seed" ], "rate": 0.3, "min": 2, "max": 4 }, { "itemIds": [ "melon_seed" ], "rate": 0.3, "min": 2, "max": 4 }, { "itemIds": [ "golden_apple" ], "rate": 0.2, "min": 1, "max": 1 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 1, "max": 5 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.1, "min": 1, "max": 3 }, { "itemIds": [ "lapis_lazuli" ], "rate": 0.2, "min": 4, "max": 9 }, { "itemIds": [ "redstone" ], "rate": 0.2, "min": 4, "max": 9 }, { "itemIds": [ "diamond" ], "rate": 0.1, "min": 1, "max": 2 } ] } }, "desk_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [ { "itemId": "rocket_boost", "count": 1 }, { "itemId": "stone_sword", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 } ], "normals": [ { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 3, "max": 10 }, { "itemIds": [ "book" ], "rate": 0.5, "min": 3, "max": 10 }, { "itemIds": [ "paper" ], "rate": 0.75, "min": 12, "max": 18 } ] } } }, "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "chest", 0, "normal_reward" ] ] }, { "color": [ 255, 130, 0, 0 ], "note": "桶", "command": [ [ "BC_PLACE_FURNITURE", "barrel", 0, "normal_reward" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 0 ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_dark_oak" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_dark_oak" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "fire_lamp" ] ] }, { "color": [ 255, 0, 0, 130 ], "note": "合成台", "command": [ [ "BC_PLACE_FURNITURE", "crafting_table" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_dark_oak" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_dark_oak", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_dark_oak", 0 ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_dark_oak" ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_dark_oak", 0, "desk_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_dark_oak", 0, "desk_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 130 ], "note": "蜡烛台", "command": [ [ "BC_PLACE_FURNITURE", "candle_holder" ] ] }, { "color": [ 255, 130, 0, 130 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot" ] ] }, { "color": [ 255, 150, 0, 0 ], "note": "缸", "command": [ [ "BC_PLACE_FURNITURE", "cauldron" ] ] }, { "color": [ 255, 150, 150, 0 ], "note": "水晶灯", "command": [ [ "BC_PLACE_FURNITURE", "chandeliers" ] ] }, { "color": [ 255, 150, 150, 150 ], "note": "蜘蛛网", "command": [ [ "BC_PLACE_FURNITURE", "cobweb" ] ] }, { "color": [ 255, 150, 0, 150 ], "note": "藤蔓", "command": [ [ "BC_PLACE_FURNITURE", "vine" ] ] }, { "color": [ 255, 150, 255, 0 ], "note": "树苗", "command": [ [ "BC_PLACE_FURNITURE", "sapling_dark_oak" ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "主方块前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_dark_oak" ], [ "BC_PLACE_TILE", "plank_dark_oak" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "主方块后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_dark_oak" ] ] }, { "color": [ 255, 83, 83, 83 ], "note": "主方块后景2", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "fence_dark_oak" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1", "entrance_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1", "entrance2_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance2" ], "weight": 10 }, { "name": "r1", "image": [ "r1", "r1_o1", "r1_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r2", "image": [ "r2", "r2_o1", "r2_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r3", "image": [ "r3" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r4", "image": [ "r4" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r5", "image": [ "r5", "r5_o1", "r5_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "e1", "image": [ "e1", "e1_o1", "e1_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e2", "image": [ "e2", "e2_o1", "e2_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 } ] } } ================================================ FILE: buildings/mini_house/mini_house.json ================================================ { "mini_house": { "maxGenPartCount": 1, "limitSize": 100, "blockEntityFormat": { "furnaceData": { "formatId": "tc:empty_furnace", "data": {} }, "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 2, "rares": [ { "itemId": "stone_sword", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 }, { "itemId": "stone_axe", "count": 1 }, { "itemId": "wooden_bow", "count": 1 }, { "itemId": "cross_bow", "count": 1 } ], "normals": [ { "itemIds": [ "ender_pearl" ], "rate": 0.5, "min": 1, "max": 2 }, { "itemIds": [ "wood_dark_oak" ], "rate": 0.9, "min": 3, "max": 5 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 3, "max": 10 }, { "itemIds": [ "potato" ], "rate": 0.5, "min": 3, "max": 6 }, { "itemIds": [ "wheat" ], "rate": 0.7, "min": 3, "max": 6 }, { "itemIds": [ "carrot" ], "rate": 0.5, "min": 3, "max": 6 }, { "itemIds": [ "string" ], "rate": 0.4, "min": 2, "max": 7 }, { "itemIds": [ "bread" ], "rate": 0.4, "min": 7, "max": 12 }, { "itemIds": [ "wooden_arrow" ], "rate": 0.4, "min": 2, "max": 7 } ] } } }, "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 0, 255, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "chest", 0, "normal_reward" ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "橡木门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_oak" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "橡木平台", "command": [ [ "BC_PLACE_TILE", "platform_oak" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "fire_lamp" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace", 0, "furnaceData" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_oak" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_oak", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_oak", 0 ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_oak", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_oak", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 50, 50, 100 ], "note": "有空气就放水", "command": [ [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 54, 40, 27 ], "note": "有空气就放泥土", "command": [ [ "BC_CLEAR_FURNITURE" ], [ "BC_PLACE_TILE", "dirt" ] ] }, { "color": [ 255, 54, 100, 27 ], "note": "有空气就放草泥土", "command": [ [ "BC_CLEAR_FURNITURE" ], [ "BC_PLACE_TILE", "dirt", 1 ] ] }, { "color": [ 255, 120, 30, 30 ], "note": "橡木木板前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_oak", 1 ], [ "BC_PLACE_TILE", "plank_oak" ] ] }, { "color": [ 255, 40, 0, 0 ], "note": "橡木木板后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_oak", 1 ] ] }, { "color": [ 255, 100, 100, 100 ], "note": "石砖前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick", 1 ], [ "BC_PLACE_TILE", "stone_brick" ] ] }, { "color": [ 255, 100, 66, 66 ], "note": "橡木木板前景石砖后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick", 1 ], [ "BC_PLACE_TILE", "plank_oak" ] ] }, { "color": [ 255, 10, 10, 10 ], "note": "石砖后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick", 1 ] ] }, { "color": [ 255, 222, 222, 244 ], "note": "玻璃后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "glass", 1 ] ] }, { "color": [ 255, 128, 64, 64 ], "note": "木头前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "hay_bale", 1 ], [ "BC_PLACE_TILE", "hay_bale" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance2" ], "weight": 10 }, { "name": "entrance3", "image": [ "entrance3", "entrance3_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance3" ], "weight": 10 }, { "name": "entrance4", "image": [ "entrance4", "entrance4_o1" ], "type": "PT_START", "hotX": 50, "hotY": 55, "unlinkParts": [ "entrance4" ], "weight": 10 } ] } } ================================================ FILE: buildings/monument_ocean/monument_ocean.json ================================================ { "monument_ocean": { "noGenSubBiome": true, "maxGenPartCount": 16, "limitSize": 500, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 2000 ] ] }, "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "水", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "note": "箱子", "command": [ ] }, { "color": [ 255, 204, 153, 0 ], "note": "水草", "command": [ [ "BC_PLACE_FURNITURE", "kelp" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 0 ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "海晶石前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "prismarine" ], [ "BC_PLACE_TILE", "prismarine" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "海晶石后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "prismarine" ], [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "海晶石砖前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "prismarine_brick" ], [ "BC_PLACE_TILE", "prismarine_brick" ] ] }, { "color": [ 255, 66, 0, 0 ], "note": "海晶石砖后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "prismarine_brick" ], [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "暗海晶石前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "prismarine_dark" ], [ "BC_PLACE_TILE", "prismarine_dark" ] ] }, { "color": [ 255, 100, 0, 100 ], "note": "暗海晶石后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "prismarine_dark" ], [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "海晶灯", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_TILE", "sea_lantern" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "湿海绵", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "prismarine_dark" ], [ "BC_PLACE_TILE", "wet_sponge" ] ] }, { "color": [ 255, 255, 204, 0 ], "note": "金块", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "prismarine_dark" ], [ "BC_PLACE_TILE", "block_gold" ] ] }, { "color": [ 255, 100, 66, 66 ], "note": "木板前景石砖后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick" ], [ "BC_PLACE_TILE", "plank_oak" ] ] }, { "color": [ 255, 10, 10, 10 ], "note": "石砖后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick" ], [ "BC_PLACE_LIQUID", "water" ] ] }, { "color": [ 255, 222, 222, 244 ], "note": "玻璃后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "glass" ], [ "BC_PLACE_LIQUID", "water" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1" ], "type": "PT_START", "hotX": 50, "hotY": 43, "unlinkParts": [ "entrance" ], "weight": 10 } ] } } ================================================ FILE: buildings/nether_fortress/nether_fortress.json ================================================ { "nether_fortress": { "maxGenPartCount": 16, "limitSize": 500, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 2000 ] ] }, "blockEntityFormat": { "desk_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [], "normals": [ { "itemIds": [ "ender_pearl" ], "rate": 0.1, "min": 1, "max": 1 }, { "itemIds": [ "book" ], "rate": 0.5, "min": 3, "max": 10 }, { "itemIds": [ "paper" ], "rate": 0.5, "min": 3, "max": 10 }, { "itemIds": [ "obsidian" ], "rate": 0.35, "min": 2, "max": 4 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.5, "min": 1, "max": 3 } ] } }, "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [ { "itemId": "strange_eye", "count": 1 }, { "itemId": "golden_sword", "count": 1 }, { "itemId": "golden_axe", "count": 1 }, { "itemId": "iron_axe", "count": 1 }, { "itemId": "iron_pickaxe", "count": 1 }, { "itemId": "iron_chestplate", "count": 1 }, { "itemId": "handgun", "count": 1 }, { "itemId": "shotgun", "count": 1 }, { "itemId": "ghost_sword", "count": 1 }, { "itemId": "air_sword", "count": 1 } ], "normals": [ { "itemIds": [ "rifle", "rocket_launcher" ], "rate": 0.05, "min": 1, "max": 1 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.75, "min": 3, "max": 10 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.6, "min": 1, "max": 4 }, { "itemIds": [ "diamond" ], "rate": 0.4, "min": 1, "max": 2 }, { "itemIds": [ "obsidian" ], "rate": 0.45, "min": 2, "max": 4 } ] } } }, "rewards": [ ], "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 144, 144, 0 ], "note": "传送门", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_FURNITURE", "portal:nether_portal_door", 0 ] ] }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "nether_chest", 0, "normal_reward" ] ] }, { "color": [ 255, 150, 0, 0 ], "note": "祭坛", "command": [ [ "BC_PLACE_FURNITURE", "nether_altar" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 5 ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "门", "command": [ [ "BC_PLACE_FURNITURE", "door_nether" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_nether_brick" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "nether_lamp" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_nether" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_nether", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_nether", 0 ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_nether" ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_nether", 0, "desk_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_nether", 0, "desk_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 130 ], "note": "蜡烛台", "command": [ [ "BC_PLACE_FURNITURE", "candle_holder" ] ] }, { "color": [ 255, 255, 255, 55 ], "note": "地狱疣", "command": [ [ "BC_PLACE_FURNITURE", "nether_wart", 2 ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "地狱砖前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "nether_brick" ], [ "BC_PLACE_TILE", "nether_brick" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "地狱砖后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "nether_brick" ] ] }, { "color": [ 255, 133, 0, 0 ], "note": "灵魂沙前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "soul_sand" ], [ "BC_PLACE_TILE", "soul_sand" ] ] }, { "color": [ 255, 255, 0, 200 ], "note": "黑曜石前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "obsidian" ], [ "BC_PLACE_TILE", "obsidian" ] ] }, { "color": [ 255, 100, 0, 100 ], "note": "黑曜石后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "obsidian" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1", "entrance_o2" ], "type": "PT_START", "hotX": 50, "hotY": 43, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r1", "image": [ "r1", "r1_o1", "r1_o2" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r2", "image": [ "r2", "r2_o1", "r2_o2", "r2_o3", "r2_o4", "r2_o5", "r2_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r3", "image": [ "r3", "r3_o1", "r3_o2", "r3_o3", "r3_o4", "r3_o5", "r3_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r4", "image": [ "r4", "r4_o1", "r4_o2", "r4_o3", "r4_o4", "r4_o5", "r4_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r5", "image": [ "r5", "r5_o1", "r5_o2", "r5_o3", "r5_o4", "r5_o5", "r5_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r6", "image": [ "r6", "r6_o1", "r6_o2", "r6_o3", "r6_o4", "r6_o5", "r6_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r7", "image": [ "r7", "r7_o1", "r7_o2", "r7_o3", "r7_o4", "r7_o5", "r7_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r8", "image": [ "r8", "r8_o1", "r8_o2", "r8_o3", "r8_o4", "r8_o5", "r8_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r9", "image": [ "r9", "r9_o1", "r9_o2" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r10", "image": [ "r10", "r10_o1", "r10_o2" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r11", "image": [ "r11", "r11_o1", "r11_o2", "r11_o3", "r11_o4", "r11_o5", "r11_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r12", "image": [ "r12", "r12_o1", "r12_o2", "r12_o3", "r12_o4", "r12_o5", "r12_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r13", "image": [ "r13", "r13_o1", "r13_o2", "r13_o3", "r13_o4", "r13_o5", "r13_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r14", "image": [ "r14", "r14_o1", "r14_o2", "r14_o3", "r14_o4", "r14_o5", "r14_o6" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r15", "image": [ "r15", "r15_o1", "r15_o2" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance", "r15" ], "weight": 10 }, { "name": "r16", "image": [ "r16" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "r17", "image": [ "r17" ], "type": "PT_NORMAL", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "e1", "image": [ "e1", "e1_o1", "e1_o2", "e1_o3", "e1_o4", "e1_o5", "e1_o6" ], "type": "PT_END", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "e2", "image": [ "e2", "e2_o1", "e2_o2", "e2_o3", "e2_o4", "e2_o5", "e2_o6" ], "type": "PT_END", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "e3", "image": [ "e3", "e3_o1", "e3_o2", "e3_o3", "e3_o4", "e3_o5", "e3_o6" ], "type": "PT_END", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "e4", "image": [ "e4", "e4_o1", "e4_o2", "e4_o3" ], "type": "PT_END", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "e5", "image": [ "e5", "e5_o1", "e5_o2", "e5_o3", "e5_o4" ], "type": "PT_END", "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "e6", "image": [ "e6", "e6_o1", "e6_o2", "e6_o3", "e6_o4" ], "type": "PT_END", "unlinkParts": [ "entrance" ], "weight": 10 } ] } } ================================================ FILE: buildings/pyramid/pyramid.json ================================================ { "pyramid": { "maxGenPartCount": 1, "limitSize": 200, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 0 ] ] }, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [], "normals": [ { "itemIds": [ "bone" ], "rate": 0.7, "min": 4, "max": 6 }, { "itemIds": [ "rotten_flesh" ], "rate": 0.7, "min": 1, "max": 8 }, { "itemIds": [ "gunpowder" ], "rate": 0.6, "min": 1, "max": 8 }, { "itemIds": [ "sand" ], "rate": 0.6, "min": 1, "max": 8 }, { "itemIds": [ "string" ], "rate": 0.6, "min": 1, "max": 8 }, { "itemIds": [ "spider_eye" ], "rate": 0.3, "min": 1, "max": 3 }, { "itemIds": [ "book" ], "rate": 0.3, "min": 1, "max": 3 }, { "itemIds": [ "golden_apple" ], "rate": 0.23, "min": 1, "max": 1 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.18, "min": 1, "max": 5 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.18, "min": 2, "max": 5 }, { "itemIds": [ "emerald" ], "rate": 0.18, "min": 1, "max": 3 }, { "itemIds": [ "diamond" ], "rate": 0.18, "min": 1, "max": 3 } ] } } }, "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "chest", 0, "normal_reward" ] ] }, { "color": [ 255, 130, 0, 0 ], "note": "桶", "command": [ [ "BC_PLACE_FURNITURE", "barrel", 0, "normal_reward" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 2 ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_dark_oak" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_sandstone" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "fire_lamp" ] ] }, { "color": [ 255, 0, 0, 130 ], "note": "合成台", "command": [ [ "BC_PLACE_FURNITURE", "crafting_table" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_dark_oak" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_dark_oak", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_dark_oak", 0 ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_dark_oak" ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_dark_oak", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_dark_oak", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 130 ], "note": "蜡烛台", "command": [ [ "BC_PLACE_FURNITURE", "candle_holder" ] ] }, { "color": [ 255, 130, 0, 130 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot" ] ] }, { "color": [ 255, 130, 0, 180 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot_large" ] ] }, { "color": [ 255, 150, 0, 0 ], "note": "缸", "command": [ [ "BC_PLACE_FURNITURE", "cauldron" ] ] }, { "color": [ 255, 150, 150, 0 ], "note": "水晶灯", "command": [ [ "BC_PLACE_FURNITURE", "chandeliers" ] ] }, { "color": [ 255, 150, 150, 150 ], "note": "蜘蛛网", "command": [ [ "BC_PLACE_FURNITURE", "cobweb" ] ] }, { "color": [ 255, 150, 0, 150 ], "note": "藤蔓", "command": [ [ "BC_PLACE_FURNITURE", "vine" ] ] }, { "color": [ 255, 150, 255, 0 ], "note": "树苗", "command": [ [ "BC_PLACE_FURNITURE", "sapling_cactus" ] ] }, { "color": [ 255, 0, 0, 168 ], "note": "踏板", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "sandstone_smooth" ], [ "BC_PLACE_FURNITURE", "pressure_plate_stone" ] ] }, { "color": [ 255, 255, 50, 50 ], "note": "红石线", "command": [ [ "BC_PLACE_WIRE", 1, 0 ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "主方块前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "sandstone_smooth" ], [ "BC_PLACE_TILE", "sandstone_smooth" ] ] }, { "color": [ 255, 202, 202, 202 ], "note": "主方块前景2", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "sandstone_carved" ], [ "BC_PLACE_TILE", "sandstone_carved" ] ] }, { "color": [ 255, 130, 70, 40 ], "note": "主方块前景3", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "terracotta_orange" ], [ "BC_PLACE_TILE", "terracotta_orange" ] ] }, { "color": [ 255, 0, 0, 240 ], "note": "主方块前景4", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "terracotta_blue" ], [ "BC_PLACE_TILE", "terracotta_blue" ] ] }, { "color": [ 255, 250, 0, 0 ], "note": "TNT", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "sandstone_smooth" ], [ "BC_PLACE_TILE", "tnt" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "主方块后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "sandstone_smooth" ] ] }, { "color": [ 255, 133, 133, 133 ], "note": "主方块后景2", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "sandstone_carved" ] ] }, { "color": [ 255, 100, 100, 240 ], "note": "主方块后景3", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "terracotta_blue" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1" ], "type": "PT_START", "hotX": 100, "hotY": 72, "unlinkParts": [ "entrance" ], "weight": 10 } ] } } ================================================ FILE: buildings/under_dark_oak_cabin/under_dark_oak_cabin.json ================================================ { "under_dark_oak_cabin": { "maxGenPartCount": 2, "limitSize": 50, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 0 ] ] }, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [ { "itemId": "rocket_boost", "count": 1 }, { "itemId": "red_crystal", "count": 2 }, { "itemId": "blue_crystal", "count": 2 }, { "itemId": "white_crystal", "count": 2 }, { "itemId": "yellow_crystal", "count": 2 }, { "itemId": "strange_eye", "count": 1 }, { "itemId": "ender_mirror", "count": 1 }, { "itemId": "wooden_sword", "count": 1 }, { "itemId": "stone_sword", "count": 1 }, { "itemId": "wooden_axe", "count": 1 }, { "itemId": "stone_axe", "count": 1 }, { "itemId": "wooden_pickaxe", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 }, { "itemId": "wooden_bow", "count": 1 }, { "itemId": "wooden_boomerang", "count": 1 }, { "itemId": "torch", "count": 24 }, { "itemId": "glow_bomb", "count": 2 }, { "itemId": "glow_ball", "count": 6 }, { "itemId": "book", "count": 3 }, { "itemId": "grenade", "count": 3 }, { "itemId": "amethyst_staff", "count": 1 }, { "itemId": "water_staff", "count": 1 } ], "normals": [ { "itemIds": [ "ender_pearl" ], "rate": 0.3, "min": 1, "max": 2 }, { "itemIds": [ "bone" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "gunpowder" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "rotten_flesh" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "string" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "wheat" ], "rate": 0.34, "min": 1, "max": 4 }, { "itemIds": [ "coal", "charcoal" ], "rate": 0.26, "min": 1, "max": 4 }, { "itemIds": [ "redstone" ], "rate": 0.26, "min": 1, "max": 4 }, { "itemIds": [ "golden_apple" ], "rate": 0.20, "min": 1, "max": 1 }, { "itemIds": [ "pumpkin_seed" ], "rate": 0.18, "min": 2, "max": 4 }, { "itemIds": [ "melon_seed" ], "rate": 0.18, "min": 2, "max": 4 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 1, "max": 4 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.1, "min": 1, "max": 4 }, { "itemIds": [ "bucket_empty" ], "rate": 0.18, "min": 1, "max": 1 }, { "itemIds": [ "wooden_arrow" ], "rate": 0.4, "min": 2, "max": 7 }, { "itemIds": [ "lighting_arrow" ], "rate": 0.4, "min": 2, "max": 7 } ] } } }, "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "chest", 0, "normal_reward" ] ] }, { "color": [ 255, 130, 0, 0 ], "note": "桶", "command": [ [ "BC_PLACE_FURNITURE", "barrel", 0, "normal_reward" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 0 ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_dark_oak" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_dark_oak" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "fire_lamp" ] ] }, { "color": [ 255, 0, 0, 130 ], "note": "合成台", "command": [ [ "BC_PLACE_FURNITURE", "crafting_table" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_dark_oak" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_dark_oak", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_dark_oak", 0 ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_dark_oak" ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_dark_oak", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_dark_oak", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 130 ], "note": "蜡烛台", "command": [ [ "BC_PLACE_FURNITURE", "candle_holder" ] ] }, { "color": [ 255, 130, 0, 130 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot" ] ] }, { "color": [ 255, 150, 0, 0 ], "note": "缸", "command": [ [ "BC_PLACE_FURNITURE", "cauldron" ] ] }, { "color": [ 255, 150, 150, 0 ], "note": "水晶灯", "command": [ [ "BC_PLACE_FURNITURE", "chandeliers" ] ] }, { "color": [ 255, 150, 150, 150 ], "note": "蜘蛛网", "command": [ [ "BC_PLACE_FURNITURE", "cobweb" ] ] }, { "color": [ 255, 150, 0, 150 ], "note": "藤蔓", "command": [ [ "BC_PLACE_FURNITURE", "vine" ] ] }, { "color": [ 255, 150, 255, 0 ], "note": "树苗", "command": [ [ "BC_PLACE_FURNITURE", "sapling_dark_oak" ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "主方块前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_dark_oak" ], [ "BC_PLACE_TILE", "plank_dark_oak" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "主方块后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_dark_oak" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1", "entrance_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance2" ], "weight": 10 }, { "name": "entrance3", "image": [ "entrance3", "entrance3_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance3" ], "weight": 10 }, { "name": "entrance4", "image": [ "entrance4", "entrance4_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance4" ], "weight": 10 }, { "name": "r1", "image": [ "r1", "r1_o1", "r1_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r2", "image": [ "r2", "r2_o1", "r2_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r3", "image": [ "r3", "r3_o1", "r3_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r4", "image": [ "r4", "r4_o1" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "e1", "image": [ "e1", "e1_o1", "e1_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e2", "image": [ "e2", "e2_o1", "e2_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e3", "image": [ "e3", "e3_o1" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e4", "image": [ "e4", "e4_o1" ], "type": "PT_END", "unlinkParts": [], "weight": 10 } ] } } ================================================ FILE: buildings/under_desert_cabin/under_desert_cabin.json ================================================ { "under_desert_cabin": { "maxGenPartCount": 2, "limitSize": 50, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 0 ] ] }, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [], "normals": [ { "itemIds": [ "bone" ], "rate": 0.7, "min": 4, "max": 6 }, { "itemIds": [ "rotten_flesh" ], "rate": 0.7, "min": 1, "max": 8 }, { "itemIds": [ "gunpowder" ], "rate": 0.6, "min": 1, "max": 8 }, { "itemIds": [ "sand" ], "rate": 0.6, "min": 1, "max": 8 }, { "itemIds": [ "string" ], "rate": 0.6, "min": 1, "max": 8 }, { "itemIds": [ "spider_eye" ], "rate": 0.3, "min": 1, "max": 3 }, { "itemIds": [ "book" ], "rate": 0.3, "min": 1, "max": 3 }, { "itemIds": [ "golden_apple" ], "rate": 0.23, "min": 1, "max": 1 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.18, "min": 1, "max": 5 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.18, "min": 2, "max": 5 }, { "itemIds": [ "emerald" ], "rate": 0.18, "min": 1, "max": 3 }, { "itemIds": [ "diamond" ], "rate": 0.18, "min": 1, "max": 3 } ] } } }, "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "stone_chest", 0, "normal_reward" ] ] }, { "color": [ 255, 130, 0, 0 ], "note": "桶", "command": [ [ "BC_PLACE_FURNITURE", "barrel", 0, "normal_reward" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 0 ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_birch" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_birch" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "fire_lamp" ] ] }, { "color": [ 255, 0, 0, 130 ], "note": "合成台", "command": [ [ "BC_PLACE_FURNITURE", "crafting_table" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_birch" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_birch", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_birch", 0 ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_birch" ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_birch", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_birch", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 130 ], "note": "蜡烛台", "command": [ [ "BC_PLACE_FURNITURE", "candle_holder" ] ] }, { "color": [ 255, 130, 0, 130 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot" ] ] }, { "color": [ 255, 130, 0, 180 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot_large" ] ] }, { "color": [ 255, 150, 0, 0 ], "note": "缸", "command": [ [ "BC_PLACE_FURNITURE", "cauldron" ] ] }, { "color": [ 255, 150, 150, 0 ], "note": "水晶灯", "command": [ [ "BC_PLACE_FURNITURE", "chandeliers" ] ] }, { "color": [ 255, 150, 150, 150 ], "note": "蜘蛛网", "command": [ [ "BC_PLACE_FURNITURE", "cobweb" ] ] }, { "color": [ 255, 150, 255, 0 ], "note": "树苗", "command": [ [ "BC_PLACE_FURNITURE", "sapling_cactus" ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "主方块前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "terracotta_yellow" ], [ "BC_PLACE_TILE", "terracotta_yellow" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "主方块后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "terracotta_yellow" ] ] }, { "color": [ 255, 97, 97, 97 ], "note": "主方块后景2", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "sandstone" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1", "entrance_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance2" ], "weight": 10 }, { "name": "entrance3", "image": [ "entrance3", "entrance3_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance3" ], "weight": 10 }, { "name": "entrance4", "image": [ "entrance4", "entrance4_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance4" ], "weight": 10 } ] } } ================================================ FILE: buildings/under_jungle_cabin/under_jungle_cabin.json ================================================ { "under_jungle_cabin": { "maxGenPartCount": 2, "limitSize": 50, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 0 ] ] }, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [ { "itemId": "rocket_boost", "count": 1 }, { "itemId": "red_crystal", "count": 2 }, { "itemId": "blue_crystal", "count": 2 }, { "itemId": "white_crystal", "count": 2 }, { "itemId": "yellow_crystal", "count": 2 }, { "itemId": "ender_mirror", "count": 1 }, { "itemId": "wooden_sword", "count": 1 }, { "itemId": "stone_sword", "count": 1 }, { "itemId": "wooden_axe", "count": 1 }, { "itemId": "stone_axe", "count": 1 }, { "itemId": "wooden_pickaxe", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 }, { "itemId": "wooden_bow", "count": 1 }, { "itemId": "wooden_boomerang", "count": 1 }, { "itemId": "torch", "count": 24 }, { "itemId": "glow_bomb", "count": 2 }, { "itemId": "glow_ball", "count": 6 }, { "itemId": "book", "count": 3 }, { "itemId": "grenade", "count": 3 }, { "itemId": "amethyst_staff", "count": 1 }, { "itemId": "water_staff", "count": 1 } ], "normals": [ { "itemIds": [ "ender_pearl" ], "rate": 0.3, "min": 1, "max": 2 }, { "itemIds": [ "bone" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "gunpowder" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "rotten_flesh" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "string" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "wheat" ], "rate": 0.34, "min": 1, "max": 4 }, { "itemIds": [ "coal", "charcoal" ], "rate": 0.26, "min": 1, "max": 4 }, { "itemIds": [ "redstone" ], "rate": 0.26, "min": 1, "max": 4 }, { "itemIds": [ "golden_apple" ], "rate": 0.20, "min": 1, "max": 1 }, { "itemIds": [ "pumpkin_seed" ], "rate": 0.18, "min": 2, "max": 4 }, { "itemIds": [ "melon_seed" ], "rate": 0.18, "min": 2, "max": 4 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 1, "max": 4 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.1, "min": 1, "max": 4 }, { "itemIds": [ "bucket_empty" ], "rate": 0.18, "min": 1, "max": 1 }, { "itemIds": [ "wooden_arrow" ], "rate": 0.4, "min": 2, "max": 7 }, { "itemIds": [ "lighting_arrow" ], "rate": 0.4, "min": 2, "max": 7 } ] } } }, "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "chest", 0, "normal_reward" ] ] }, { "color": [ 255, 130, 0, 0 ], "note": "桶", "command": [ [ "BC_PLACE_FURNITURE", "barrel", 0, "normal_reward" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 0 ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_jungle" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_jungle" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "fire_lamp" ] ] }, { "color": [ 255, 0, 0, 130 ], "note": "合成台", "command": [ [ "BC_PLACE_FURNITURE", "crafting_table" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_jungle" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_jungle", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_jungle", 0 ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_jungle" ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_jungle", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_jungle", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 130 ], "note": "蜡烛台", "command": [ [ "BC_PLACE_FURNITURE", "candle_holder" ] ] }, { "color": [ 255, 130, 0, 130 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot" ] ] }, { "color": [ 255, 130, 0, 180 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot_large" ] ] }, { "color": [ 255, 150, 0, 0 ], "note": "缸", "command": [ [ "BC_PLACE_FURNITURE", "cauldron" ] ] }, { "color": [ 255, 150, 150, 0 ], "note": "水晶灯", "command": [ [ "BC_PLACE_FURNITURE", "chandeliers" ] ] }, { "color": [ 255, 150, 150, 150 ], "note": "蜘蛛网", "command": [ [ "BC_PLACE_FURNITURE", "cobweb" ] ] }, { "color": [ 255, 150, 0, 150 ], "note": "藤蔓", "command": [ [ "BC_PLACE_FURNITURE", "vine" ] ] }, { "color": [ 255, 150, 255, 0 ], "note": "树苗", "command": [ [ "BC_PLACE_FURNITURE", "sapling_jungle" ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "主方块前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_jungle" ], [ "BC_PLACE_TILE", "plank_jungle" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "主方块后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_jungle" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1", "entrance_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance2" ], "weight": 10 }, { "name": "entrance3", "image": [ "entrance3", "entrance3_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance3" ], "weight": 10 }, { "name": "entrance4", "image": [ "entrance4", "entrance4_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance4" ], "weight": 10 }, { "name": "r1", "image": [ "r1", "r1_o1", "r1_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r2", "image": [ "r2", "r2_o1", "r2_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r3", "image": [ "r3", "r3_o1", "r3_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r4", "image": [ "r4", "r4_o1" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "e1", "image": [ "e1", "e1_o1", "e1_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e2", "image": [ "e2", "e2_o1", "e2_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e3", "image": [ "e3", "e3_o1" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e4", "image": [ "e4", "e4_o1" ], "type": "PT_END", "unlinkParts": [], "weight": 10 } ] } } ================================================ FILE: buildings/under_oak_cabin/under_oak_cabin.json ================================================ { "under_oak_cabin": { "maxGenPartCount": 2, "limitSize": 34, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 0 ] ] }, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "name": "normal_reward", "rareGenCount": 1, "rares": [ { "itemId": "rocket_boost", "count": 1 }, { "itemId": "strange_eye", "count": 1 }, { "itemId": "ender_mirror", "count": 1 }, { "itemId": "wooden_sword", "count": 1 }, { "itemId": "stone_sword", "count": 1 }, { "itemId": "wooden_axe", "count": 1 }, { "itemId": "stone_axe", "count": 1 }, { "itemId": "wooden_pickaxe", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 }, { "itemId": "wooden_bow", "count": 1 }, { "itemId": "wooden_boomerang", "count": 1 }, { "itemId": "torch", "count": 24 }, { "itemId": "glow_bomb", "count": 2 }, { "itemId": "glow_ball", "count": 6 }, { "itemId": "book", "count": 3 }, { "itemId": "grenade", "count": 3 }, { "itemId": "amethyst_staff", "count": 1 }, { "itemId": "water_staff", "count": 1 } ], "normals": [ { "itemIds": [ "ender_pearl" ], "rate": 0.3, "min": 1, "max": 2 }, { "itemIds": [ "bone" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "gunpowder" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "rotten_flesh" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "string" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "wheat" ], "rate": 0.34, "min": 1, "max": 4 }, { "itemIds": [ "coal", "charcoal" ], "rate": 0.26, "min": 1, "max": 4 }, { "itemIds": [ "redstone" ], "rate": 0.26, "min": 1, "max": 4 }, { "itemIds": [ "golden_apple" ], "rate": 0.20, "min": 1, "max": 1 }, { "itemIds": [ "pumpkin_seed" ], "rate": 0.18, "min": 2, "max": 4 }, { "itemIds": [ "melon_seed" ], "rate": 0.18, "min": 2, "max": 4 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 1, "max": 4 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.1, "min": 1, "max": 4 }, { "itemIds": [ "bucket_empty" ], "rate": 0.18, "min": 1, "max": 1 }, { "itemIds": [ "wooden_arrow" ], "rate": 0.4, "min": 2, "max": 7 }, { "itemIds": [ "lighting_arrow" ], "rate": 0.4, "min": 2, "max": 7 } ] } } }, "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "chest", 0, "normal_reward" ] ] }, { "color": [ 255, 130, 0, 0 ], "note": "桶", "command": [ [ "BC_PLACE_FURNITURE", "barrel", 0, "normal_reward" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 0 ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_oak" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_oak" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "fire_lamp" ] ] }, { "color": [ 255, 0, 0, 130 ], "note": "合成台", "command": [ [ "BC_PLACE_FURNITURE", "crafting_table" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_oak" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_oak", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_oak", 0 ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_oak" ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_oak", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_oak", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 130 ], "note": "蜡烛台", "command": [ [ "BC_PLACE_FURNITURE", "candle_holder" ] ] }, { "color": [ 255, 130, 0, 130 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot" ] ] }, { "color": [ 255, 150, 0, 0 ], "note": "缸", "command": [ [ "BC_PLACE_FURNITURE", "cauldron" ] ] }, { "color": [ 255, 150, 150, 0 ], "note": "水晶灯", "command": [ [ "BC_PLACE_FURNITURE", "chandeliers" ] ] }, { "color": [ 255, 150, 150, 150 ], "note": "蜘蛛网", "command": [ [ "BC_PLACE_FURNITURE", "cobweb" ] ] }, { "color": [ 255, 150, 0, 150 ], "note": "藤蔓", "command": [ [ "BC_PLACE_FURNITURE", "vine" ] ] }, { "color": [ 255, 150, 255, 0 ], "note": "树苗", "command": [ [ "BC_PLACE_FURNITURE", "sapling_oak" ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "主方块前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_oak" ], [ "BC_PLACE_TILE", "plank_oak" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "主方块后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_oak" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1", "entrance_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance2" ], "weight": 10 }, { "name": "entrance3", "image": [ "entrance3", "entrance3_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance3" ], "weight": 10 }, { "name": "entrance4", "image": [ "entrance4", "entrance4_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance4" ], "weight": 10 }, { "name": "r1", "image": [ "r1", "r1_o1", "r1_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r2", "image": [ "r2", "r2_o1", "r2_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r3", "image": [ "r3", "r3_o1", "r3_o2" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "r4", "image": [ "r4", "r4_o1" ], "type": "PT_NORMAL", "unlinkParts": [], "weight": 10 }, { "name": "e1", "image": [ "e1", "e1_o1", "e1_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e2", "image": [ "e2", "e2_o1", "e2_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e3", "image": [ "e3", "e3_o1" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e4", "image": [ "e4", "e4_o1" ], "type": "PT_END", "unlinkParts": [], "weight": 10 } ] } } ================================================ FILE: buildings/under_spruce_cabin/under_spruce_cabin.json ================================================ { "under_spruce_cabin": { "maxGenPartCount": 2, "limitSize": 50, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 0 ] ] }, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "rareGenCount": 1, "rares": [ { "itemId": "rocket_boost", "count": 1 }, { "itemId": "red_crystal", "count": 2 }, { "itemId": "blue_crystal", "count": 2 }, { "itemId": "white_crystal", "count": 2 }, { "itemId": "yellow_crystal", "count": 2 }, { "itemId": "iron_sword", "count": 1 }, { "itemId": "lead_sword", "count": 1 }, { "itemId": "copper_axe", "count": 1 }, { "itemId": "silver_pickaxe", "count": 1 }, { "itemId": "tin_pickaxe", "count": 1 }, { "itemId": "torch", "count": 36 }, { "itemId": "glow_bomb", "count": 8 }, { "itemId": "glow_ball", "count": 12 }, { "itemId": "book", "count": 8 }, { "itemId": "grenade", "count": 6 }, { "itemId": "ghost_sword", "count": 1 } ], "normals": [ { "itemIds": [ "ender_pearl" ], "rate": 0.3, "min": 1, "max": 2 }, { "itemIds": [ "bone" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "gunpowder" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "rotten_flesh" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "string" ], "rate": 0.5, "min": 1, "max": 8 }, { "itemIds": [ "wheat" ], "rate": 0.34, "min": 1, "max": 4 }, { "itemIds": [ "coal", "charcoal" ], "rate": 0.26, "min": 1, "max": 4 }, { "itemIds": [ "redstone" ], "rate": 0.26, "min": 1, "max": 4 }, { "itemIds": [ "golden_apple" ], "rate": 0.20, "min": 1, "max": 1 }, { "itemIds": [ "pumpkin_seed" ], "rate": 0.18, "min": 2, "max": 4 }, { "itemIds": [ "melon_seed" ], "rate": 0.18, "min": 2, "max": 4 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 1, "max": 4 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.1, "min": 1, "max": 4 }, { "itemIds": [ "bucket_empty" ], "rate": 0.18, "min": 1, "max": 1 }, { "itemIds": [ "wooden_arrow" ], "rate": 0.4, "min": 2, "max": 7 }, { "itemIds": [ "lighting_arrow" ], "rate": 0.4, "min": 2, "max": 7 } ] } } }, "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "chest", 0, "normal_reward" ] ] }, { "color": [ 255, 130, 0, 0 ], "note": "桶", "command": [ [ "BC_PLACE_FURNITURE", "barrel", 0, "normal_reward" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 0 ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_spruce" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_spruce" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "fire_lamp" ] ] }, { "color": [ 255, 0, 0, 130 ], "note": "合成台", "command": [ [ "BC_PLACE_FURNITURE", "crafting_table" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_spruce" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_spruce", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_spruce", 0 ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_spruce" ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_spruce", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_spruce", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 130 ], "note": "蜡烛台", "command": [ [ "BC_PLACE_FURNITURE", "candle_holder" ] ] }, { "color": [ 255, 130, 0, 130 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot" ] ] }, { "color": [ 255, 130, 0, 180 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot_large" ] ] }, { "color": [ 255, 150, 0, 0 ], "note": "缸", "command": [ [ "BC_PLACE_FURNITURE", "cauldron" ] ] }, { "color": [ 255, 150, 150, 0 ], "note": "水晶灯", "command": [ [ "BC_PLACE_FURNITURE", "chandeliers" ] ] }, { "color": [ 255, 150, 150, 150 ], "note": "蜘蛛网", "command": [ [ "BC_PLACE_FURNITURE", "cobweb" ] ] }, { "color": [ 255, 150, 0, 150 ], "note": "藤蔓", "command": [ [ "BC_PLACE_FURNITURE", "vine" ] ] }, { "color": [ 255, 150, 255, 0 ], "note": "树苗", "command": [ [ "BC_PLACE_FURNITURE", "sapling_spruce" ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "主方块前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_spruce" ], [ "BC_PLACE_TILE", "plank_spruce" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "主方块后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_spruce" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1", "entrance_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1", "entrance2_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance3", "image": [ "entrance3", "entrance3_o1", "entrance3_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "e1", "image": [ "e1", "e1_o1", "e1_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e2", "image": [ "e2", "e2_o1", "e2_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e3", "image": [ "e3", "e3_o1" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e4", "image": [ "e4", "e4_o1" ], "type": "PT_END", "unlinkParts": [], "weight": 10 } ] } } ================================================ FILE: buildings/under_stone_cabin/under_stone_cabin.json ================================================ { "under_stone_cabin": { "maxGenPartCount": 2, "limitSize": 50, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 0 ] ] }, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "name": "normal_reward", "rareGenCount": 1, "rares": [ { "itemId": "rocket_boost", "count": 1 }, { "itemId": "red_crystal", "count": 2 }, { "itemId": "blue_crystal", "count": 2 }, { "itemId": "white_crystal", "count": 2 }, { "itemId": "yellow_crystal", "count": 2 }, { "itemId": "strange_eye", "count": 1 }, { "itemId": "ender_mirror", "count": 1 }, { "itemId": "iron_sword", "count": 1 }, { "itemId": "stone_sword", "count": 1 }, { "itemId": "iron_axe", "count": 1 }, { "itemId": "stone_axe", "count": 1 }, { "itemId": "stone_pickaxe", "count": 1 }, { "itemId": "torch", "count": 8 }, { "itemId": "glow_bomb", "count": 2 }, { "itemId": "bomb", "count": 2 }, { "itemId": "grenade", "count": 3 }, { "itemId": "ghost_sword", "count": 1 }, { "itemId": "amethyst_staff", "count": 1 }, { "itemId": "water_staff", "count": 1 } ], "normals": [ { "itemIds": [ "ender_pearl" ], "rate": 0.5, "min": 1, "max": 2 }, { "itemIds": [ "apple" ], "rate": 0.5, "min": 1, "max": 3 }, { "itemIds": [ "bread" ], "rate": 0.5, "min": 1, "max": 3 }, { "itemIds": [ "coal", "charcoal" ], "rate": 0.34, "min": 3, "max": 8 }, { "itemIds": [ "redstone" ], "rate": 0.26, "min": 4, "max": 9 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 1, "max": 4 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.1, "min": 1, "max": 3 } ] } } }, "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "stone_chest", 0, "normal_reward" ] ] }, { "color": [ 255, 130, 0, 0 ], "note": "桶", "command": [ [ "BC_PLACE_FURNITURE", "barrel", 0, "normal_reward" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 0 ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_jungle" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_jungle" ] ] }, { "color": [ 255, 0, 255, 0 ], "note": "吊灯", "command": [ [ "BC_PLACE_FURNITURE", "fire_lamp" ] ] }, { "color": [ 255, 0, 0, 130 ], "note": "合成台", "command": [ [ "BC_PLACE_FURNITURE", "crafting_table" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_jungle" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_jungle", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_jungle", 0 ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_jungle" ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_jungle", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_jungle", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 130 ], "note": "蜡烛台", "command": [ [ "BC_PLACE_FURNITURE", "candle_holder" ] ] }, { "color": [ 255, 130, 0, 130 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot" ] ] }, { "color": [ 255, 130, 0, 180 ], "note": "花盆", "command": [ [ "BC_PLACE_FURNITURE", "flower_pot_large" ] ] }, { "color": [ 255, 150, 0, 0 ], "note": "缸", "command": [ [ "BC_PLACE_FURNITURE", "cauldron" ] ] }, { "color": [ 255, 150, 150, 0 ], "note": "水晶灯", "command": [ [ "BC_PLACE_FURNITURE", "chandeliers" ] ] }, { "color": [ 255, 150, 150, 150 ], "note": "蜘蛛网", "command": [ [ "BC_PLACE_FURNITURE", "cobweb" ] ] }, { "color": [ 255, 150, 0, 150 ], "note": "藤蔓", "command": [ [ "BC_PLACE_FURNITURE", "vine" ] ] }, { "color": [ 255, 150, 255, 0 ], "note": "树苗", "command": [ [ "BC_PLACE_FURNITURE", "sapling_jungle" ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "主方块前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick" ], [ "BC_PLACE_TILE", "stone_brick" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "主方块后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "stone_brick" ] ] }, { "color": [ 255, 97, 97, 97 ], "note": "主方块后景2", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "cobblestone" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1", "entrance_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance2" ], "weight": 10 }, { "name": "entrance3", "image": [ "entrance3", "entrance3_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance3" ], "weight": 10 }, { "name": "entrance4", "image": [ "entrance4", "entrance4_o1" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance4" ], "weight": 10 } ] } } ================================================ FILE: buildings/under_tainted_cabin/under_tainted_cabin.json ================================================ { "under_tainted_cabin": { "maxGenPartCount": 2, "limitSize": 50, "mainRestraint": { "checks": [ [ "IS_CENTER_Y_GREATER_OR_EQUAL_TO", 0 ] ] }, "blockEntityFormat": { "normal_reward": { "formatId": "tc:common_rewards", "data": { "name": "normal_reward", "rareGenCount": 1, "rares": [ { "itemId": "rocket_boost", "count": 1 }, { "itemId": "red_crystal", "count": 2 }, { "itemId": "blue_crystal", "count": 2 }, { "itemId": "white_crystal", "count": 2 }, { "itemId": "yellow_crystal", "count": 2 }, { "itemId": "red_crystal", "count": 2 }, { "itemId": "blue_crystal", "count": 2 }, { "itemId": "white_crystal", "count": 2 }, { "itemId": "yellow_crystal", "count": 2 }, { "itemId": "ender_mirror", "count": 1 }, { "itemId": "iron_sword", "count": 1 }, { "itemId": "iron_axe", "count": 1 }, { "itemId": "iron_pickaxe", "count": 1 }, { "itemId": "iron_helmet", "count": 1 }, { "itemId": "iron_chestplate", "count": 1 }, { "itemId": "iron_leggings", "count": 1 }, { "itemId": "iron_helmet", "count": 1 }, { "itemId": "copper_chestplate", "count": 1 }, { "itemId": "tin_leggings", "count": 1 }, { "itemId": "tin_chestplate", "count": 1 }, { "itemId": "tin_leggings", "count": 1 }, { "itemId": "ghost_sword", "count": 1 } ], "normals": [ { "itemIds": [ "ender_pearl" ], "rate": 0.3, "min": 1, "max": 2 }, { "itemIds": [ "apple" ], "rate": 0.3, "min": 1, "max": 3 }, { "itemIds": [ "redstone" ], "rate": 0.23, "min": 4, "max": 9 }, { "itemIds": [ "golden_apple" ], "rate": 0.20, "min": 1, "max": 1 }, { "itemIds": [ "pumpkin_seed" ], "rate": 0.18, "min": 2, "max": 4 }, { "itemIds": [ "melon_seed" ], "rate": 0.18, "min": 2, "max": 4 }, { "itemIds": [ "iron_ingot", "copper_ingot", "tin_ingot", "lead_ingot" ], "rate": 0.3, "min": 1, "max": 4 }, { "itemIds": [ "gold_ingot", "silver_ingot", "bronze_ingot", "steel_ingot" ], "rate": 0.1, "min": 1, "max": 3 }, { "itemIds": [ "diamond" ], "rate": 0.1, "min": 1, "max": 2 }, { "itemIds": [ "emerald" ], "rate": 0.1, "min": 1, "max": 3 } ] } } }, "restraints": [ ], "commandColors": [ { "color": [ 255, 64, 64, 64 ], "note": "无操作", "command": [ [ "BC_NO_OP" ] ] }, { "color": [ 255, 192, 192, 192 ], "note": "前景记号" }, { "color": [ 255, 0, 0, 0 ], "note": "空气", "command": [ [ "BC_CLEAR_LAKE" ], [ "BC_CLEAR" ] ] }, { "color": [ 255, 0, 64, 255 ], "pipe": true }, { "color": [ 255, 0, 255, 255 ], "pipe": true }, { "color": [ 255, 0, 160, 255 ], "note": "箱子", "command": [ [ "BC_PLACE_FURNITURE", "chest", 0, "normal_reward" ] ] }, { "color": [ 255, 130, 0, 0 ], "note": "桶", "command": [ [ "BC_PLACE_FURNITURE", "barrel", 0, "normal_reward" ] ] }, { "color": [ 255, 0, 200, 0 ], "note": "罐子", "command": [ [ "BC_PLACE_FURNITURE", "pot", 3 ] ] }, { "color": [ 255, 255, 255, 0 ], "note": "火把", "command": [ [ "BC_PLACE_FURNITURE", "torch", 0 ] ] }, { "color": [ 255, 102, 102, 204 ], "note": "门", "command": [ [ "BC_PLACE_FURNITURE", "wooden_door_tainted" ] ] }, { "color": [ 255, 255, 0, 255 ], "note": "平台", "command": [ [ "BC_PLACE_TILE", "platform_tainted" ] ] }, { "color": [ 255, 128, 64, 32 ], "note": "熔炉", "command": [ [ "BC_PLACE_FURNITURE", "furnace" ] ] }, { "color": [ 255, 255, 0, 0 ], "note": "桌子", "command": [ [ "BC_PLACE_FURNITURE", "table_tainted" ] ] }, { "color": [ 255, 128, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_tainted", 1 ] ] }, { "color": [ 255, 160, 0, 0 ], "note": "椅子", "command": [ [ "BC_PLACE_FURNITURE", "chair_tainted", 0 ] ] }, { "color": [ 255, 0, 130, 0 ], "note": "长凳", "command": [ [ "BC_PLACE_FURNITURE", "bench_tainted" ] ] }, { "color": [ 255, 0, 128, 255 ], "note": "床", "command": [ [ "BC_PLACE_FURNITURE", "wooden_bed_red", 0 ] ] }, { "color": [ 255, 100, 100, 0 ], "note": "书架", "command": [ [ "BC_PLACE_FURNITURE", "bookcase_tainted", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 0 ], "note": "桌柜", "command": [ [ "BC_PLACE_FURNITURE", "cabinet_tainted", 0, "normal_reward" ] ] }, { "color": [ 255, 200, 200, 120 ], "note": "蜡烛", "command": [ [ "BC_PLACE_FURNITURE", "candle" ] ] }, { "color": [ 255, 0, 130, 130 ], "note": "蜡烛台", "command": [ [ "BC_PLACE_FURNITURE", "candle_holder" ] ] }, { "color": [ 255, 150, 0, 0 ], "note": "缸", "command": [ [ "BC_PLACE_FURNITURE", "cauldron" ] ] }, { "color": [ 255, 150, 150, 0 ], "note": "水晶灯", "command": [ [ "BC_PLACE_FURNITURE", "chandeliers" ] ] }, { "color": [ 255, 150, 150, 150 ], "note": "蜘蛛网", "command": [ [ "BC_PLACE_FURNITURE", "cobweb" ] ] }, { "color": [ 255, 150, 0, 150 ], "note": "藤蔓", "command": [ [ "BC_PLACE_FURNITURE", "tainted_vine" ] ] }, { "color": [ 255, 150, 255, 0 ], "note": "树苗", "command": [ [ "BC_PLACE_FURNITURE", "sapling_tainted" ] ] }, { "color": [ 255, 168, 168, 168 ], "note": "主方块前景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "plank_tainted" ], [ "BC_PLACE_TILE", "plank_tainted" ] ] }, { "color": [ 255, 114, 114, 114 ], "note": "主方块后景", "command": [ [ "BC_CLEAR" ], [ "BC_PLACE_BACK", "wood_tainted" ] ] } ], "parts": [ { "name": "entrance", "image": [ "entrance", "entrance_o1", "entrance_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance2", "image": [ "entrance2", "entrance2_o1", "entrance2_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "entrance3", "image": [ "entrance3", "entrance3_o1", "entrance3_o2" ], "type": "PT_START", "hotX": 25, "hotY": 25, "unlinkParts": [ "entrance" ], "weight": 10 }, { "name": "e1", "image": [ "e1", "e1_o1", "e1_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e2", "image": [ "e2", "e2_o1", "e2_o2" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e3", "image": [ "e3", "e3_o1" ], "type": "PT_END", "unlinkParts": [], "weight": 10 }, { "name": "e4", "image": [ "e4", "e4_o1" ], "type": "PT_END", "unlinkParts": [], "weight": 10 } ] } } ================================================ FILE: client/CameraInGame.lua ================================================ ---@class TC.CameraInGame local CameraInGame = class("CameraInGame") local s_instance ---@return TC.CameraInGame function CameraInGame.getInstance() if s_instance == nil then s_instance = CameraInGame.new() end return s_instance end function CameraInGame:__init() ---@type CameraComponentWrapper self.camera = nil end function CameraInGame:setCamera(camera) self.camera = camera end return CameraInGame ================================================ FILE: client/ControlAimMode.lua ================================================ local ControlAimMode = { PressOnly = 0, LookDirectionOrShoot = 1, LookPositionOrUse = 2 } return ControlAimMode ================================================ FILE: client/InputControl.lua ================================================ local ControlAimMode = require("client.ControlAimMode") ---@class TC.InputControl local InputControl = class("InputControl") local SettingsData = require("settings.SettingsData") local s_instance ---@return TC.InputControl function InputControl.getInstance() if s_instance == nil then s_instance = InputControl.new() end return s_instance end function InputControl:__init() self.keyMap = { left = Keys.A, right = Keys.D, up = Keys.W, down = Keys.S, jump = Keys.Space, Drop = Keys.Q, Backpack = Keys.E, Task = Keys.F, Nei = Keys.R, Esc = Keys.Escape, Ctrl = Keys.LeftControl, Shift = Keys.LeftShift, } self.joystickKeyStates = { left = false, right = false, up = false, down = false, jump = false, } self.operatingWall = false self.isSmart = false self.usingVirtualJoystick = false ---@type UIJoystick self.virtualJoystickLeftNode = nil ---@type UIJoystick self.virtualJoystickRightNode = nil ---@type UIJoystick self.virtualJoystickCenterNode = nil self.aimMode = ControlAimMode.PressOnly self.aimAngle = 0 self.aimDistance = 0 self.aimInstanceClicked = false self.aimPressing = false self.aimTriggerUsing = false self.isMapClicking = false self.touchMapPosition = Vector2.new() self._lastRightJoystickPressed = false self._lastCenterJoystickPressed = false self._lastWriteVirtualJoystickLeft = false self._lastWriteVirtualJoystickRight = false self.isPcMouseAtMap = false self.pcMouseAtMapX = 0 self.pcMouseAtMapY = 0 self.pcMouseAtMapXi = 0 self.pcMouseAtMapYi = 0 self.pcMouseScrollDeltaY = 0 self.isPcMouseLeftInstantDown = false self.isPcMouseLeftInstantDownAtMap = false self.isPcMouseLeftPressing = false self.isPcMouseLeftPressingAtMap = false self.isPcMouseLeftInstantUp = false self.isPcMouseLeftInstantUpAtMap = false self.isPcMouseRightInstantDown = false self.isPcMouseRightInstantDownAtMap = false self.isPcMouseRightPressing = false self.isPcMouseRightPressingAtMap = false self.isPcMouseRightInstantUp = false self.isPcMouseRightInstantUpAtMap = false self._pressingKeys = {} self._instantPressedKeys = {} for k, _ in pairs(self.keyMap) do self._pressingKeys[k] = false self._instantPressedKeys[k] = false end Input.mouse:addScrollListener({ InputControl._onMouseScroll, self }) end function InputControl:_onMouseScroll(_, deltaY) if deltaY == 0 then return end self.pcMouseScrollDeltaY = deltaY end function InputControl.isPressing(keyName) local instance = InputControl.getInstance() local key = instance.keyMap[keyName] if key ~= nil then if Input.keyboard:isKeyPressed(key) then return true end end local joystickState = instance.joystickKeyStates[keyName] if joystickState ~= nil then return joystickState end return false end function InputControl.isInstantPressing(keyName) local instance = InputControl.getInstance() return instance._instantPressedKeys[keyName] == true end function InputControl.isNumKeyPressing(num) return Input.keyboard:isKeyPressed(Keys.D0 + num) end function InputControl.getCurrentPressingKeyNum() for i = 0, 9 do if InputControl.isNumKeyPressing(i) then return i end end return -1 end function InputControl:updateMovementByAxis(x, y) self.joystickKeyStates.left = x < -0.3 self.joystickKeyStates.right = x > 0.3 self.joystickKeyStates.up = y < -0.3 self.joystickKeyStates.down = y > 0.3 self.joystickKeyStates.jump = self.joystickKeyStates.up end function InputControl:update() self.joystickKeyStates.left = false self.joystickKeyStates.right = false self.joystickKeyStates.up = false self.joystickKeyStates.down = false self.joystickKeyStates.jump = false self.aimPressing = false self.aimInstanceClicked = false self.aimTriggerUsing = false self.isPcMouseLeftInstantUp = false self.isPcMouseLeftInstantDown = false self.isPcMouseLeftInstantDownAtMap = false self.isPcMouseRightInstantUp = false self.isPcMouseRightInstantDown = false self.isPcMouseRightInstantDownAtMap = false self.pcMouseAtMapX = 0 self.pcMouseAtMapY = 0 self.pcMouseAtMapXi = 0 self.pcMouseAtMapYi = 0 local checkMovingByVirtualJoystick = false local checkAimingByVirtualJoystick = false for k, v in pairs(self.keyMap) do self._instantPressedKeys[k] = false local pressed = Input.keyboard:isKeyPressed(v) if pressed and not self._pressingKeys[k] then self._pressingKeys[k] = true self._instantPressedKeys[k] = true elseif not pressed and self._pressingKeys[k] then self._pressingKeys[k] = false end end if SettingsData.isMobileOperation then self.usingVirtualJoystick = (self.virtualJoystickCenterNode ~= nil) if self.usingVirtualJoystick then self.virtualJoystickCenterNode.visible = self.aimMode == ControlAimMode.LookPositionOrUse -- movement if self.virtualJoystickLeftNode.isTouching then local u, d, l, r = self.virtualJoystickLeftNode:getControlledFourDirection() if u or d or l or r then self.joystickKeyStates.left = l self.joystickKeyStates.right = r self.joystickKeyStates.up = u self.joystickKeyStates.down = d self.joystickKeyStates.jump = u checkMovingByVirtualJoystick = true end end -- aim if self.virtualJoystickRightNode.isTouching then local angle = self.virtualJoystickRightNode.controlledAngle local distance = self.virtualJoystickRightNode.controlledDistanceRate self.aimAngle = angle self.aimDistance = distance if not self._lastRightJoystickPressed then self.aimInstanceClicked = true end self.aimPressing = true if self.aimMode == ControlAimMode.LookDirectionOrShoot then if self.aimDistance > 0.5 then self.aimTriggerUsing = true end else self.aimTriggerUsing = true end checkAimingByVirtualJoystick = true end if self.aimMode == ControlAimMode.LookPositionOrUse then if self.virtualJoystickCenterNode.isTouching then local angle = self.virtualJoystickCenterNode.controlledAngle local distance = self.virtualJoystickCenterNode.controlledDistanceRate self.aimAngle = angle self.aimDistance = distance if not self._lastCenterJoystickPressed then self.aimInstanceClicked = true end self.aimPressing = true checkAimingByVirtualJoystick = true end self._lastCenterJoystickPressed = self.virtualJoystickCenterNode.isTouching else self._lastCenterJoystickPressed = false end end else self.usingVirtualJoystick = false -- PC Mouse + Keyboard. self.operatingWall = InputControl.isPressing("Shift") local nPos = Input.mouse.position nPos.x = nPos.x / GameWindow.displayResolution.width nPos.y = nPos.y / GameWindow.displayResolution.height self.pcMouseAtMapX = MiscUtils.screenX + MiscUtils.screenWidth * nPos.x self.pcMouseAtMapY = MiscUtils.screenY + MiscUtils.screenHeight * nPos.y self.pcMouseAtMapXi = Utils.Cell(self.pcMouseAtMapX) self.pcMouseAtMapYi = Utils.Cell(self.pcMouseAtMapY) local lp = Input.mouse.isLeftButtonPressed if self.isPcMouseLeftPressing and not lp then self.isPcMouseLeftInstantUp = true elseif not self.isPcMouseLeftPressing and lp then self.isPcMouseLeftInstantDown = true if self.isPcMouseAtMap then self.isPcMouseLeftInstantDownAtMap = true self.isPcMouseLeftPressingAtMap = true end end self.isPcMouseLeftPressing = lp if not lp then self.isPcMouseLeftPressingAtMap = false end local rp = Input.mouse.isRightButtonPressed if self.isPcMouseRightPressing and not rp then self.isPcMouseRightInstantUp = true elseif not self.isPcMouseRightPressing and rp then self.isPcMouseRightInstantDown = true if self.isPcMouseAtMap then self.isPcMouseRightInstantDownAtMap = true self.isPcMouseRightPressingAtMap = true end end self.isPcMouseRightPressing = rp if not rp then self.isPcMouseRightPressingAtMap = false end end if Input.joystick[1].isConnected then local leftPress = false local rightPress = false if not checkMovingByVirtualJoystick then local x, y = Input.joystick[1]:getAxis(0), Input.joystick[1]:getAxis(1) if not (math.abs(x) < 0.001 and math.abs(y) < 0.001) then leftPress = true self:updateMovementByAxis(x, y) if self.usingVirtualJoystick then self.virtualJoystickLeftNode:setControl(x, y) if not self._lastWriteVirtualJoystickLeft then self.virtualJoystickLeftNode.controlledCenter = Vector2.new( self.virtualJoystickLeftNode.width / 2 + math.random(-20, 30), self.virtualJoystickLeftNode.height / 2 + math.random(-30, 30)) end end else if self.usingVirtualJoystick then self.virtualJoystickLeftNode:setControl(0, 0) end end end if not checkAimingByVirtualJoystick then local x, y = Input.joystick[1]:getAxis(2), Input.joystick[1]:getAxis(3) if not (math.abs(x) < 0.001 and math.abs(y) < 0.001) then rightPress = true local tempVec = Vector2.new(x, y) self.aimAngle = tempVec.angle self.aimDistance = tempVec.length if not self._lastRightJoystickPressed then self.aimInstanceClicked = true end self.aimPressing = true self.aimTriggerUsing = true if self.usingVirtualJoystick then self.virtualJoystickRightNode:setControl(x, y) if not self._lastWriteVirtualJoystickRight then self.virtualJoystickRightNode.controlledCenter = Vector2.new( self.virtualJoystickRightNode.width / 2 + math.random(-20, 30), self.virtualJoystickRightNode.height / 2 + math.random(-30, 30)) end end else if self.usingVirtualJoystick then self.virtualJoystickRightNode:setControl(0, 0) end end end self._lastWriteVirtualJoystickLeft = leftPress self._lastWriteVirtualJoystickRight = rightPress end self._lastRightJoystickPressed = self.aimPressing end return InputControl ================================================ FILE: client/MenuJoinInfo.lua ================================================ ---@class TC.MenuJoinInfo local MenuJoinInfo = class("MenuJoinData") local s_instance ---@return TC.MenuJoinInfo function MenuJoinInfo.getInstance() if s_instance == nil then s_instance = MenuJoinInfo.new() end return s_instance end function MenuJoinInfo:__init() self.playerInfo = { name = "" } self.worldInfo = { name = "" } self.serverInfo = { address = "", port = 0, isMultiplayer = false } end function MenuJoinInfo:getData() local joinData = JoinData.new() joinData.playerName = self.playerInfo.name joinData.worldName = self.worldInfo.name joinData.multiplayer = self.serverInfo.isMultiplayer joinData.address = self.serverInfo.address joinData.port = self.serverInfo.port return joinData end return MenuJoinInfo ================================================ FILE: client/ModClient.lua ================================================ local ModClient = class("ModClient") local MusicPool = require("MusicPool") local MusicSystem = require("MusicSystem") local UIManager = require("ui.UIManager") local InputControl = require("InputControl") local CameraInGame = require("CameraInGame") local ModTextures = require("mod_textures.ModTextures") local RecordData = require("record.RecordData") --- the constructor of this class function ModClient:__init() self._cameraGameObject = nil -- the menu background element renderer self._hudUI = nil self._pendingUI = nil self._lastState = nil self._stateBeginProxies = { [ClientState.InMenu] = self.beginInMenu, [ClientState.Joining] = self.beginJoining, [ClientState.Gaming] = self.beginGaming, [ClientState.SavingWorld] = self.beginSavingWorld, [ClientState.LosingConnection] = self.beginSavingWorld, } self._stateEndProxies = { [ClientState.LoadingWorld] = self.endLoadingWorld, [ClientState.Gaming] = self.endGaming, [ClientState.SavingWorld] = self.endSavingWorld, [ClientState.LosingConnection] = self.endSavingWorld, } self._stateUpdateProxies = { [ClientState.InMenu] = self.updateInMenu, [ClientState.Joining] = self.updateJoining, [ClientState.Gaming] = self.updateGaming, } self._stateRenderProxies = { [ClientState.InMenu] = self.renderInMenu, [ClientState.Gaming] = self.renderGaming, } self._testTime = 0 end function ModClient:init() FontManager.load(Path.join(Mod.current.assetRootPath, "font/msyhbd.ttf"), "msyhbd") require("languages.LocaleHelper").reload(require("languages.Locale")) require("settings.Settings").loadData() -- create the main camera self._cameraGameObject = GameObject.instantiate() self._cameraGameObject.camera:init() CameraInGame.getInstance():setCamera(self._cameraGameObject.camera) MusicPool.getInstance():initModMusicResources(Mod.GetByID("tc_music"), "music") MusicSystem.getInstance():registerFromProxy() ModTextures.getInstance() UIManager.getInstance():init() UIManager.getInstance():initUISpriteResources(Mod.current, "ui_res") UIManager.getInstance():initUISpriteResources(Mod.current, "ui_res_large") UIManager.getInstance():postInit() end function ModClient:start() end function ModClient:beginInMenu() require("ui.StartUI").new() MusicSystem.getInstance():switchToScene("tc:menu") end function ModClient:preUpdate() InputControl.getInstance():update() self._cameraGameObject.transform.position = Vector3.new(MiscUtils.screenX, MiscUtils.screenY, 0) end function ModClient:update() -- check end if self._lastState ~= nil and self._lastState ~= ClientState.current then print("end game state:", self._lastState, " -> ", ClientState.current) local proxy = self._stateEndProxies[self._lastState] if proxy then proxy(self) end end -- check begin if self._lastState ~= ClientState.current then self._lastState = ClientState.current print("begin game state:", self._lastState) local proxy = self._stateBeginProxies[ClientState.current] if proxy then proxy(self) end end -- check update local proxy = self._stateUpdateProxies[ClientState.current] if proxy then proxy(self) end UIManager.getInstance():update() MusicSystem.getInstance():update() end function ModClient:render() local proxy = self._stateRenderProxies[ClientState.current] if proxy then proxy(self) end UIManager.getInstance():render() end function ModClient:exit() end function ModClient:updateInMenu() end function ModClient:renderInMenu() end function ModClient:beginGaming() local HudUI = require("ui.hud.HudUI") self._hudUI = HudUI.new() end function ModClient:endGaming() self._hudUI:closeWindow() self._hudUI = nil end function ModClient:updateGaming() self._hudUI:update() MusicSystem.getInstance():updateGaming() RecordData.getInstance():update() end function ModClient:renderGaming() end function ModClient:beginJoining() local PendingUI = require("ui.PendingUI") self._pendingUI = PendingUI.new() end function ModClient:updateJoining() end function ModClient:endLoadingWorld() self._pendingUI:closeWindow() self._pendingUI = nil end function ModClient:beginSavingWorld() local PendingUI = require("ui.PendingUI") self._pendingUI = PendingUI.new() end function ModClient:endSavingWorld() self._pendingUI:closeWindow() self._pendingUI = nil end return ModClient ================================================ FILE: client/ModMusicSceneProxy.lua ================================================ ---@class TC.ModMusicSceneProxy local ModMusicSceneProxy = class("ModMusicSceneProxy") ---@type TC.ModMusicSceneProxy[] local s_proxy = {} ---__init ---@param proxy TC.MusicSceneProxy function ModMusicSceneProxy:__init(proxy) self._proxy = proxy end function ModMusicSceneProxy.getProxy() return s_proxy end function ModMusicSceneProxy.register(modProxyClass) table.insert(s_proxy, modProxyClass) end function ModMusicSceneProxy:onRegisterAllScenes() end return ModMusicSceneProxy ================================================ FILE: client/MusicCopyright.lua ================================================ local MusicCopyright = {} MusicCopyright["tc:menu1"] = { title = "menu1", author = "author1", } MusicCopyright["tc:menu2"] = { title = "menu2", author = "author2", } MusicCopyright["tc:unfinished"] = { title = "unfinished", author = "author3", } return MusicCopyright ================================================ FILE: client/MusicPool.lua ================================================ ---@class TC.MusicPool local MusicPool = class("MusicPool") ---@class TC.MusicPoolElement local MusicPoolElement = class("MusicPoolElement") function MusicPoolElement:__init(musicAssetPath) self.musicID = 0 self.musicAssetPath = musicAssetPath end local s_instance ---@return TC.MusicPool function MusicPool.getInstance() if s_instance == nil then s_instance = MusicPool.new() end return s_instance end function MusicPool:__init() self._elements = {} end ---initModMusicResources ---@param mod Mod ---@param dirPathInMod string function MusicPool:initModMusicResources(mod, dirPathInMod) local searchPath = Path.join(mod.assetRootPath, dirPathInMod) local musicNameMP3s = AssetManager.getAllFiles(searchPath, ".mp3", true, false, true) local musicNameOGGs = AssetManager.getAllFiles(searchPath, ".ogg", true, false, true) for _, musicName in ipairs(musicNameMP3s) do local name = mod.modId .. ":" .. musicName --print(name) self._elements[name] = MusicPoolElement.new(Path.join(searchPath, musicName .. ".mp3")) end for _, musicName in ipairs(musicNameOGGs) do local name = mod.modId .. ":" .. musicName --print(name) self._elements[name] = MusicPoolElement.new(Path.join(searchPath, musicName .. ".ogg")) end end function MusicPool:getIDAndActivateMusic(musicName) local element = self._elements[musicName] if element == nil then print("MusicPool:getIDAndActivateMusic failed:", musicName) assert(false) end if element.musicID == 0 then local bytes = AssetManager.readAsBytes(element.musicAssetPath) element.musicID = Audio.loadMusicEffectFromMemory(bytes, 0, bytes.count) end return element.musicID end function MusicPool:recycleAndEnsureMusicMemory(ensureMusicNames) local ensureNameDict = {} for _, name in ipairs(ensureMusicNames) do ensureNameDict[name] = true end -- unload all music if not ensured ---@param element TC.MusicPoolElement for name, element in pairs(self._elements) do if ensureNameDict[name] == nil then if element.musicID ~= 0 then Audio.unloadMusicEffectByID(element.musicID) element.musicID = 0 end end end -- load all music if ensured for name, _ in pairs(ensureNameDict) do ---@type TC.MusicPoolElement local element = self._elements[name] if element.musicID == 0 then local bytes = AssetManager.readAsBytes(element.musicAssetPath) element.musicID = Audio.loadMusicEffectFromMemory(bytes, 0, bytes.count) end end end return MusicPool ================================================ FILE: client/MusicScene.lua ================================================ ---@class TC.MusicScene local MusicScene = class("MusicScene") local Algorithm = require("util.Algorithm") ---__init ---@param musicList ---@param fadeInTime int ---@param fadeOutTime int ---@param interval int ---@param intervalRandOffset int function MusicScene:__init(musicList, fadeInTime, fadeOutTime, interval, intervalRandOffset) self.musicList = musicList self.fadeInTime = fadeInTime self.fadeOutTime = fadeOutTime self.interval = interval self.intervalRandOffset = intervalRandOffset end function MusicScene:doRandomList() Algorithm.Shuffle(self.musicList) end return MusicScene ================================================ FILE: client/MusicSceneProxy.lua ================================================ ---@class TC.MusicSceneProxy local MusicSceneProxy = class("MusicSceneProxy") local ModMusicSceneProxy = require("ModMusicSceneProxy") local s_instance ---@return TC.MusicSceneProxy function MusicSceneProxy.getInstance() if s_instance == nil then s_instance = MusicSceneProxy.new() end return s_instance end function MusicSceneProxy:__init() self.proxy = {} self.biomeProxy = {} self.bossProxy = {} end function MusicSceneProxy:register(name, data) self.proxy[name] = data end function MusicSceneProxy:registerAll() self:register("tc:menu", { musicList = { "tc_music:unfinished", "tc_music:menu1", "tc_music:menu2", }, fadeInTime = 5000, fadeOutTime = 1000, interval = 2000, intervalRandOffset = 100, }) self:register("tc:forest", { musicList = { "tc_music:overworld", "tc_music:day2", "tc_music:day3", "tc_music:day4", "tc_music:mc_aria_math", "tc_music:mc_blind_spots", "tc_music:mc_haunt_muskie", "tc_music:mc_chris", }, fadeInTime = 5000, fadeOutTime = 3000, interval = 2000, intervalRandOffset = 100, }) self:register("tc:night", { musicList = { "tc_music:night1", "tc_music:night2", "tc_music:night3", "tc_music:night4", }, fadeInTime = 5000, fadeOutTime = 3000, interval = 12000, intervalRandOffset = 10000, }) self:register("tc:snow", { musicList = { "tc_music:mc_snow", }, fadeInTime = 5000, fadeOutTime = 3000, interval = 2000, intervalRandOffset = 100, }) self:register("tc:tainted", { musicList = { "tc_music:cr_deep_freeze", }, fadeInTime = 5000, fadeOutTime = 3000, interval = 2000, intervalRandOffset = 100, }) self:register("tc:flesh", { musicList = { "tc_music:cr_dark_drifting", }, fadeInTime = 5000, fadeOutTime = 3000, interval = 2000, intervalRandOffset = 100, }) self:register("tc:jungle", { musicList = { "tc_music:mc_aria_math", "tc_music:mc_blind_spots", "tc_music:mc_haunt_muskie", "tc_music:mc_chris", }, fadeInTime = 5000, fadeOutTime = 3000, interval = 32000, intervalRandOffset = 16000, }) self:register("tc:cave", { musicList = { "tc_music:mcunder1", "tc_music:mcunder2", "tc_music:mcunder3", "tc_music:mcunder4", }, fadeInTime = 5000, fadeOutTime = 3000, interval = 8000, intervalRandOffset = 100, }) self:register("tc:mushroom_cave", { musicList = { "tc_music:cr_star_trails", }, fadeInTime = 3000, fadeOutTime = 3000, interval = 1000, intervalRandOffset = 100, }) self:register("tc:lava", { musicList = { "tc_music:cr_calamity_of_dread", }, fadeInTime = 5000, fadeOutTime = 3000, interval = 8000, intervalRandOffset = 100, }) self:register("tc:ice_cave", { musicList = { "tc_music:cr_snow_delta", }, fadeInTime = 5000, fadeOutTime = 3000, interval = 8000, intervalRandOffset = 100, }) self:register("tc:nether", { musicList = { "tc_music:mcnether1", }, fadeInTime = 5000, fadeOutTime = 3000, interval = 2000, intervalRandOffset = 100, }) self:register("tc:boss", { musicList = { "tc_music:boss", }, fadeInTime = 100, fadeOutTime = 1000, interval = 100, intervalRandOffset = 100, }) self:registerBiomeScene("tc:Surface", "tc:forest", "day", "tc:forest") self:registerBiomeScene("tc:Surface", "tc:forest", "night", "tc:night") self:registerBiomeScene("tc:Surface", "tc:soft_snow_land", "day", "tc:snow") self:registerBiomeScene("tc:Surface", "tc:soft_snow_land", "night", "tc:night") self:registerBiomeScene("tc:Surface", "tc:snow_land", "day", "tc:snow") self:registerBiomeScene("tc:Surface", "tc:snow_land", "night", "tc:night") self:registerBiomeScene("tc:Surface", "tc:tainted_land", "day", "tc:tainted") self:registerBiomeScene("tc:Surface", "tc:tainted_land", "night", "tc:tainted") self:registerBiomeScene("tc:Surface", "tc:flesh", "day", "tc:flesh") self:registerBiomeScene("tc:Surface", "tc:flesh", "night", "tc:flesh") self:registerBiomeScene("tc:Surface", "tc:jungle", "day", "tc:jungle") self:registerBiomeScene("tc:Surface", "tc:super_volcano", "day", "tc:lava") self:registerBiomeScene("tc:Surface", "tc:super_volcano", "night", "tc:lava") self:registerBiomeScene("tc:Underground", "tc:deep_ice_cave", "default", "tc:ice_cave") self:registerBiomeScene("tc:Underground", "tc:blue_mushroom_cave", "default", "tc:mushroom_cave") self:registerBiomeScene("tc:Underground", "tc:flesh_cave", "default", "tc:flesh") self:registerBiomeScene("tc:Underground", "tc:tainted_cave", "default", "tc:tainted") self:registerBiomeScene("tc:Nether", "tc:nether", "default", "tc:nether") self:registerBossScene("tc:snow_queen", "tc:boss") self:registerBossScene("tc:worm_head", "tc:boss") self:registerBossScene("tc:crison_eye", "tc:boss") self:registerBossScene("tc:dungeon_eater_head", "tc:boss") ---@type TC.ModMusicSceneProxy[] local modProxies = {} for _, c in ipairs(ModMusicSceneProxy.getProxy()) do table.insert(modProxies, c.new(self)) end for _, p in ipairs(modProxies) do p:onRegisterAllScenes() end end function MusicSceneProxy:registerBossScene(bossIDName, musicSceneName) local bossID = Reg.NpcID(bossIDName) self.bossProxy[bossID] = musicSceneName end function MusicSceneProxy:tryGetBossSceneName(bossID) return self.bossProxy[bossID] end ---registerBiomeScene ---@param biomeTypeName string ---@param biomeIDName string ---@param style string ---@param musicSceneName string function MusicSceneProxy:registerBiomeScene(biomeTypeName, biomeIDName, style, musicSceneName) local biomeType = Reg.BiomeTypeID(biomeTypeName) local biomeID = Reg.BiomeID(biomeIDName) if self.biomeProxy[biomeType] == nil then self.biomeProxy[biomeType] = {} end if self.biomeProxy[biomeType][biomeID] == nil then self.biomeProxy[biomeType][biomeID] = {} end self.biomeProxy[biomeType][biomeID][style] = musicSceneName end ---tryGetBiomeSceneName ---@param biomeType int ---@param biomeID int ---@param style string function MusicSceneProxy:tryGetBiomeSceneName(biomeType, biomeID, style) local biomeTypeProxy = self.biomeProxy[biomeType] if biomeTypeProxy == nil then return nil end local biomeIDProxy = biomeTypeProxy[biomeID] if biomeIDProxy == nil then return nil end return biomeIDProxy[style] end return MusicSceneProxy ================================================ FILE: client/MusicSystem.lua ================================================ ---@class TC.MusicSystem local MusicSystem = class("MusicSystem") local MusicScene = require("MusicScene") local MusicPool = require("MusicPool") local MusicSceneProxy = require("MusicSceneProxy") local SettingsData = require("settings.SettingsData") local RecordData = require("record.RecordData") local BIOME_TYPE_SURFACE = Reg.BiomeTypeID("tc:Surface") local BIOME_TYPE_UNDERGROUND = Reg.BiomeTypeID("tc:Underground") local BIOME_TYPE_NETHER = Reg.BiomeTypeID("tc:Nether") local s_instance local COPYRIGHT_DISPLAY_SECONDS = 4 ---@return TC.MusicSystem function MusicSystem.getInstance() if s_instance == nil then s_instance = MusicSystem.new() end return s_instance end function MusicSystem:__init() self.musicScenes = {} self.currentMusicScene = nil ---@type TC.MusicScene self.currentMusicSceneName = nil self.nextMusicSceneName = nil self.lastMusicSceneNameForContinue = nil self.lastMusicIndexForContinue = 1 self.lastMusicTimeForContinue = 0 self.usingLastMusicScene = false self.usingLastMusicIndex = 1 self.usingLastMusicTime = 0 self.nextMusicPendingTime = 0 self.isNextMusicPending = false self.musicIndexInList = 1 self.test = 0 self.lastBossID = -1 self.lastBiomeType = -1 self.lastBiomeID = -1 self.lastIsNight = false self.playingTime = 0 self._lastSoundVolumePercent = 100 self._lastMusicVolumePercent = 100 self.musicCopyright = nil self.musicCopyrightTick = 0 Audio.addMusicFinishedListener({ MusicSystem._onMusicFinished, self }) end function MusicSystem:_onMusicFinished() self.playingTime = 0 if self.nextMusicSceneName ~= nil then self.currentMusicScene = self.musicScenes[self.nextMusicSceneName] self.currentMusicSceneName = self.nextMusicSceneName self.nextMusicSceneName = nil local offsetTime = 0 if self.usingLastMusicScene ~= nil then self.musicIndexInList = self.usingLastMusicIndex offsetTime = self.usingLastMusicTime else self.musicIndexInList = 1 self.currentMusicScene:doRandomList() end self:_playCurrentMusic(offsetTime) else self.isNextMusicPending = true self.nextMusicPendingTime = self.currentMusicScene.interval + math.random(self.currentMusicScene.intervalRandOffset) end end function MusicSystem:update() if self._lastMusicVolumePercent ~= SettingsData.musicVolume then self._lastMusicVolumePercent = SettingsData.musicVolume Audio.setMusicVolume(self._lastMusicVolumePercent / 100.0) end if self._lastSoundVolumePercent ~= SettingsData.soundVolume then self._lastSoundVolumePercent = SettingsData.soundVolume Audio.setAllSoundEffectVolume(self._lastSoundVolumePercent / 100.0) end if self.isNextMusicPending then if self.nextMusicPendingTime > 0 then self.nextMusicPendingTime = self.nextMusicPendingTime - Time.deltaTime * 1000 end if self.nextMusicPendingTime <= 0 then self.isNextMusicPending = false self.nextMusicPendingTime = 0 self.musicIndexInList = self.musicIndexInList + 1 if self.musicIndexInList > #self.currentMusicScene.musicList then self.musicIndexInList = 1 end self:_playCurrentMusic() end end self.test = self.test + 1 if self.test == 60 * 10 then --self:switchToScene("tc:forest") end if Audio.isMusicPlaying() then self.playingTime = self.playingTime + Time.deltaTime else self.playingTime = 0 end if self.musicCopyrightTick > 0 then self.musicCopyrightTick = self.musicCopyrightTick - 1 if self.musicCopyrightTick == 0 then self.musicCopyright = nil end end end function MusicSystem:updateGaming() local player = PlayerUtils.GetCurrentClientPlayer() if player == nil then return end local biomeType = player.biomeType local biomeID = player.biomeID local isNight = MiscUtils.isNight local bossID = RecordData.getInstance().curBossID local playingBossMusic = false if self.lastBossID ~= bossID then self.lastBossID = bossID if bossID > 0 then local name = MusicSceneProxy.getInstance():tryGetBossSceneName(bossID) if name ~= nil then self:switchToScene(name) end end end if self.lastBossID > 0 then playingBossMusic = true self.lastBiomeType = -1 self.lastBiomeID = -1 end if not playingBossMusic then if self.lastBiomeType ~= biomeType or self.lastBiomeID ~= biomeID or self.lastIsNight ~= isNight then self.lastBiomeType = biomeType self.lastBiomeID = biomeID self.lastIsNight = isNight if biomeType == BIOME_TYPE_SURFACE then if not isNight then local name = MusicSceneProxy.getInstance():tryGetBiomeSceneName(biomeType, biomeID, "day") if name ~= nil then self:switchToScene(name) else name = MusicSceneProxy.getInstance():tryGetBiomeSceneName(biomeType, Reg.BiomeID("tc:forest"), "day") self:switchToScene(name) end else local name = MusicSceneProxy.getInstance():tryGetBiomeSceneName(biomeType, biomeID, "night") if name ~= nil then self:switchToScene(name) else name = MusicSceneProxy.getInstance():tryGetBiomeSceneName(biomeType, Reg.BiomeID("tc:forest"), "night") self:switchToScene(name) end end elseif biomeType == BIOME_TYPE_UNDERGROUND then local name = MusicSceneProxy.getInstance():tryGetBiomeSceneName(biomeType, biomeID, "default") if name ~= nil then self:switchToScene(name) else self:switchToScene("tc:cave") end elseif biomeType == BIOME_TYPE_NETHER then local name = MusicSceneProxy.getInstance():tryGetBiomeSceneName(biomeType, biomeID, "default") if name ~= nil then self:switchToScene(name) else self:switchToScene("tc:nether") end end end end end function MusicSystem:_playCurrentMusic(offsetTime) if offsetTime == nil then offsetTime = 0 end if #self.currentMusicScene.musicList > 0 then local name = self.currentMusicScene.musicList[self.musicIndexInList] local musicID = MusicPool.getInstance():getIDAndActivateMusic(name) Audio.playMusic(musicID, 1, self.currentMusicScene.fadeInTime, offsetTime * 1000) local MusicCopyright = require("MusicCopyright") if MusicCopyright[name] ~= nil then self.musicCopyright = MusicCopyright[name] self.musicCopyrightTick = 60 * COPYRIGHT_DISPLAY_SECONDS else self.musicCopyright = MusicCopyright['tc:unfinished'] self.musicCopyrightTick = 60 * COPYRIGHT_DISPLAY_SECONDS end end end function MusicSystem:switchToScene(sceneName) local scene = self.musicScenes[sceneName] ---@type TC.MusicScene if scene == nil then return end print("Play Music Scene:", sceneName) if self.currentMusicSceneName == nil then self.currentMusicSceneName = sceneName self.currentMusicScene = scene self.musicIndexInList = 1 self.currentMusicScene:doRandomList() self:_playCurrentMusic() else if sceneName == self.currentMusicSceneName then return end if self.lastMusicSceneNameForContinue ~= nil and sceneName == self.lastMusicSceneNameForContinue then self.usingLastMusicScene = self.lastMusicSceneNameForContinue self.usingLastMusicIndex = self.lastMusicIndexForContinue self.usingLastMusicTime = self.lastMusicTimeForContinue else self.usingLastMusicScene = nil self.usingLastMusicIndex = 1 self.usingLastMusicTime = 0 scene:doRandomList() end self.lastMusicSceneNameForContinue = self.currentMusicSceneName self.lastMusicIndexForContinue = self.musicIndexInList self.lastMusicTimeForContinue = self.playingTime self.nextMusicSceneName = sceneName Audio.stopMusic(self.currentMusicScene.fadeOutTime) end end function MusicSystem:playCurrentMusicSceneImmediately() if self.currentMusicScene == nil then return end end function MusicSystem:registerFromProxy() local Proxy = require("MusicSceneProxy") for name, data in pairs(Proxy.getInstance().proxy) do local musicList = {} local fadeInTime = 0 local fadeOutTime = 0 local interval = 0 local intervalRandOffset = 0 if data.musicList ~= nil then musicList = data.musicList end if data.fadeInTime ~= nil then fadeInTime = data.fadeInTime end if data.fadeOutTime ~= nil then fadeOutTime = data.fadeOutTime end if data.interval ~= nil then interval = data.interval end if data.intervalRandOffset ~= nil then intervalRandOffset = data.intervalRandOffset end self.musicScenes[name] = MusicScene.new( musicList, fadeInTime, fadeOutTime, interval, intervalRandOffset ) end end return MusicSystem ================================================ FILE: constants/Constants.lua ================================================ local Constants = { PLAYER_MAX_MAX_HEALTH = 400, PLAYER_MAX_MAX_MANA = 1000, } return Constants ================================================ FILE: contents/IGNORE_THIS_FOLDER.txt ================================================ ================================================ FILE: contents/commands/admin.json ================================================ { "admin": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "master", "parameters": [ { "type": "CP_PLAYER" } ], "script": { "path": "admin.lua" } } } ================================================ FILE: contents/commands/admin.lua ================================================ function RunCommand(sourceCmd, player) player:SetOP(OP_ADMIN) player:SetGameMode(GAME_MODE_CREATIVE) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("admin_ok"), player.name)) end ================================================ FILE: contents/commands/autosave-off.json ================================================ { "autosave-off": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "autosaveoff.lua" } } } ================================================ FILE: contents/commands/autosave-on.json ================================================ { "autosave-on": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "autosaveon.lua" } } } ================================================ FILE: contents/commands/autosaveoff.lua ================================================ function RunCommand(sourceCmd) MiscUtils.SetAutoSaveEnabled(false) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("autosave_off_ok"))) end ================================================ FILE: contents/commands/autosaveon.lua ================================================ function RunCommand(sourceCmd) MiscUtils.SetAutoSaveEnabled(true) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("autosave_on_ok"))) end ================================================ FILE: contents/commands/banip.json ================================================ { "banip": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_STRING" } ], "script": { "path": "banip.lua" } } } ================================================ FILE: contents/commands/banip.lua ================================================ function RunCommand(sourceCmd, ip) MiscUtils.Ban(ip) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("banip_ok"), ip)) end ================================================ FILE: contents/commands/blacklist.json ================================================ { "blacklist": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "blacklist.lua" } } } ================================================ FILE: contents/commands/blacklist.lua ================================================ function RunCommand(sourceCmd) local blackList = MiscUtils.GetBlackList() local count = blackList.length for i = 1, count do sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("blacklist_info"), i, blackList[i])) end sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("blacklist_ok"), count)) end ================================================ FILE: contents/commands/blueyoshiiscool.json ================================================ { "blueyoshiiscool": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "master", "parameters": [], "script": { "path": "byiscool.lua" } } } ================================================ FILE: contents/commands/buff.json ================================================ { "buff": { "isClient": false, "fromPlayer": true, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_BUFF" }, { "type": "CP_INTEGER", "min": 1, "max": 216000 } ], "script": { "path": "buff.lua" } } } ================================================ FILE: contents/commands/buff.lua ================================================ function InnerRunCommand(player, buffID, buffTime) player:AddBuff(buffID, buffTime) end function RunCommandFromPlayer(myPlayer, buffID, buffTime) InnerRunCommand(myPlayer, buffID, buffTime) MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("buff_ok"), myPlayer.name, LangUtils.BuffName(buffID), math.floor(buffTime / 60))) end function RunCommand(sourceCmd, player, buffID, buffTime) InnerRunCommand(player, buffID, buffTime) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("buff_ok"), player.name, LangUtils.BuffName(buffID), math.floor(buffTime / 60))) end ================================================ FILE: contents/commands/buffp.json ================================================ { "buffp": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_PLAYER" }, { "type": "CP_BUFF" }, { "type": "CP_INTEGER", "min": 1, "max": 216000 } ], "script": { "path": "buff.lua" } } } ================================================ FILE: contents/commands/byiscool.lua ================================================ function RunCommand(sourceCmd) local msg = string.format(LangUtils.ModText("blueyoshiiscool_ok")) MiscUtils.BroadcastUTF8(msg) end ================================================ FILE: contents/commands/clear.json ================================================ { "clear": { "isClient": false, "fromPlayer": true, "gameMode": "creative", "op": "any", "parameters": [], "script": { "path": "clear.lua" } } } ================================================ FILE: contents/commands/clear.lua ================================================ function RunCommandFromPlayer(myPlayer) myPlayer:ClearBackpack() MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("clear_ok"), myPlayer.name)) end function RunCommand(sourceCmd, player) player:ClearBackpack() sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("clear_ok"), player.name)) end ================================================ FILE: contents/commands/clearp.json ================================================ { "clearp": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_PLAYER" } ], "script": { "path": "clear.lua" } } } ================================================ FILE: contents/commands/day.json ================================================ { "day": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_INTEGER", "min": 0, "max": 86400 } ], "script": { "path": "day.lua" } } } ================================================ FILE: contents/commands/day.lua ================================================ function RunCommand(sourceCmd, dayTime) MiscUtils.SetDayTime(dayTime) local h, m, s = MiscUtils.GetDayTimeFormat() sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("day_ok"), h, m, s)) end ================================================ FILE: contents/commands/dayf.json ================================================ { "dayf": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_INTEGER", "min": 0, "max": 23 }, { "type": "CP_INTEGER", "min": 0, "max": 59, "default": 0 }, { "type": "CP_INTEGER", "min": 0, "max": 59, "default": 0 } ], "script": { "path": "dayf.lua" } } } ================================================ FILE: contents/commands/dayf.lua ================================================ function RunCommand(sourceCmd, h, m, s) MiscUtils.SetDayTimeFormat(h, m, s) h, m, s = MiscUtils.GetDayTimeFormat() sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("day_ok"), h, m, s)) end ================================================ FILE: contents/commands/daylock.json ================================================ { "daylock": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "any", "parameters": [], "script": { "path": "daylock.lua" } } } ================================================ FILE: contents/commands/daylock.lua ================================================ function RunCommand(sourceCmd) MiscUtils.SetDaySpeed(0) daySpeed = MiscUtils.GetDaySpeed() sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("dayspeed_ok"), daySpeed)) end ================================================ FILE: contents/commands/dayspeed.json ================================================ { "dayspeed": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_DOUBLE", "min": 0, "max": 1000 } ], "script": { "path": "dayspeed.lua" } } } ================================================ FILE: contents/commands/dayspeed.lua ================================================ function RunCommand(sourceCmd, daySpeed) MiscUtils.SetDaySpeed(daySpeed) daySpeed = MiscUtils.GetDaySpeed() sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("dayspeed_ok"), daySpeed)) end ================================================ FILE: contents/commands/dayunlock.json ================================================ { "dayunlock": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "any", "parameters": [], "script": { "path": "dayunlock.lua" } } } ================================================ FILE: contents/commands/dayunlock.lua ================================================ function RunCommand(sourceCmd) MiscUtils.SetDaySpeed(1.0) daySpeed = MiscUtils.GetDaySpeed() sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("dayspeed_ok"), daySpeed)) end ================================================ FILE: contents/commands/effect.json ================================================ { "effect": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_EFFECT" }, { "type": "CP_POSITION_CELL_X", "default": "~8" }, { "type": "CP_POSITION_CELL_Y", "default": "~-8" } ], "script": { "path": "effect.lua" } } } ================================================ FILE: contents/commands/effect.lua ================================================ function RunCommand(sourceCmd, effectID, x, y) EffectUtils.SendFromServer(effectID, x * 16, y * 16) end ================================================ FILE: contents/commands/enchant.json ================================================ { "enchant": { "isClient": false, "fromPlayer": true, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_ENCHANTMENT" }, { "type": "CP_INTEGER", "min": 1, "max": 8 } ], "script": { "path": "enchant.lua" } } } ================================================ FILE: contents/commands/enchant.lua ================================================ function RunCommand(myPlayer, enchantmentID, enchantmentLevel) local heldItemSlot = myPlayer:GetHeldItemSlot() local ok = false if heldItemSlot.hasItem then ok = heldItemSlot:AddEnchantment(enchantmentID, enchantmentLevel) end if ok then MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("em_ok"), myPlayer.name, LangUtils.ItemName(heldItemSlot.id), LangUtils.EnchantmentName(enchantmentID), enchantmentLevel)) else MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("em_fail"))) end end ================================================ FILE: contents/commands/ex.json ================================================ { "ex": { "isClient": false, "fromPlayer": true, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_INTEGER", "min": 1, "max": 10000000 } ], "script": { "path": "ex.lua" } } } ================================================ FILE: contents/commands/ex.lua ================================================ function InnerRunCommand(player, exValue) player:AddExperience(exValue) end function RunCommandFromPlayer(myPlayer, exValue) InnerRunCommand(myPlayer, exValue) MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("ex_ok"), myPlayer.name, exValue)) end function RunCommand(sourceCmd, player, exValue) InnerRunCommand(player, exValue) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("ex_ok"), player.name, exValue)) end ================================================ FILE: contents/commands/exp.json ================================================ { "exp": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_PLAYER" }, { "type": "CP_INTEGER", "min": 1, "max": 10000000 } ], "script": { "path": "ex.lua" } } } ================================================ FILE: contents/commands/gamemode.json ================================================ { "gamemode": { "isClient": false, "fromPlayer": true, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_GAME_MODE" } ], "script": { "path": "gamemodep.lua" } } } ================================================ FILE: contents/commands/gamemodep.json ================================================ { "gamemodep": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_PLAYER" }, { "type": "CP_GAME_MODE" } ], "script": { "path": "gamemodep.lua" } } } ================================================ FILE: contents/commands/gamemodep.lua ================================================ function InnerRunCommand(player, gameMode, changeFromSelf) player:SetGameMode(gameMode, changeFromSelf) local msg = "" if gameMode == GAME_MODE_SURVIVAL then msg = string.format(LangUtils.ModText("gamemodep_s_ok"), player.name) elseif gameMode == GAME_MODE_CREATIVE then msg = string.format(LangUtils.ModText("gamemodep_c_ok"), player.name) elseif gameMode == GAME_MODE_ADVENTURE then msg = string.format(LangUtils.ModText("gamemodep_a_ok"), player.name) end return msg end function RunCommandFromPlayer(myPlayer, gameMode) local msg = InnerRunCommand(myPlayer, gameMode, true) MiscUtils.UnicastUTF8(myPlayer, msg) end function RunCommand(sourceCmd, player, gameMode) local msg = InnerRunCommand(player, gameMode, false) MiscUtils.UnicastUTF8(player, msg) sourceCmd:ResponseUTF8(msg) end ================================================ FILE: contents/commands/gamemodew.json ================================================ { "gamemodew": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_GAME_MODE" } ], "script": { "path": "gamemodew.lua" } } } ================================================ FILE: contents/commands/gamemodew.lua ================================================ function RunCommand(sourceCmd, gameMode) MiscUtils.SetGameMode(gameMode) local msg = "" if gameMode == GAME_MODE_SURVIVAL then msg = string.format(LangUtils.ModText("gamemodew_s_ok")) elseif gameMode == GAME_MODE_CREATIVE then msg = string.format(LangUtils.ModText("gamemodew_c_ok")) elseif gameMode == GAME_MODE_ADVENTURE then msg = string.format(LangUtils.ModText("gamemodew_a_ok")) end sourceCmd:ResponseUTF8(msg) end ================================================ FILE: contents/commands/give.json ================================================ { "give": { "isClient": false, "fromPlayer": true, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_ITEM" }, { "type": "CP_INTEGER", "min": 1, "max": 9999, "default": 9999 } ], "script": { "path": "give.lua" } } } ================================================ FILE: contents/commands/give.lua ================================================ function InnerRunCommand(player, itemID, itemCount) local imax = ItemUtils.GetMaxCount(itemID) if itemCount > imax then itemCount = imax end player:AddBackpack(itemID, itemCount) return itemCount end function RunCommandFromPlayer(myPlayer, itemID, itemCount) itemCount = InnerRunCommand(myPlayer, itemID, itemCount) MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("give_ok"), myPlayer.name, LangUtils.ItemName(itemID), itemCount)) end function RunCommand(sourceCmd, player, itemID, itemCount) itemCount = InnerRunCommand(player, itemID, itemCount) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("give_ok"), player.name, LangUtils.ItemName(itemID), itemCount)) end ================================================ FILE: contents/commands/givep.json ================================================ { "givep": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_PLAYER" }, { "type": "CP_ITEM" }, { "type": "CP_INTEGER", "min": 1, "max": 9999, "default": 9999 } ], "script": { "path": "give.lua" } } } ================================================ FILE: contents/commands/home.json ================================================ { "home": { "isClient": false, "fromPlayer": true, "gameMode": "creative", "op": "any", "parameters": [], "script": { "path": "home.lua" } } } ================================================ FILE: contents/commands/home.lua ================================================ function RunCommandFromPlayer(myPlayer) local ok = myPlayer:GoHome() if ok then MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("home_ok"), myPlayer.name)) else MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("home_fail"), myPlayer.name)) end end ================================================ FILE: contents/commands/kick.json ================================================ { "kick": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_PLAYER" } ], "script": { "path": "kick.lua" } } } ================================================ FILE: contents/commands/kick.lua ================================================ function RunCommand(sourceCmd, player) local name = player.name MiscUtils.KickPlayer(name) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("kick_ok"), name)) end ================================================ FILE: contents/commands/kickall.json ================================================ { "kickall": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "kickall.lua" } } } ================================================ FILE: contents/commands/kickall.lua ================================================ function RunCommand(sourceCmd) MiscUtils.KickAllPlayers() end ================================================ FILE: contents/commands/kill.json ================================================ { "kill": { "isClient": false, "fromPlayer": true, "gameMode": "survival", "op": "any", "parameters": [], "script": { "path": "kill.lua" } } } ================================================ FILE: contents/commands/kill.lua ================================================ function RunCommandFromPlayer(myPlayer) myPlayer:Strike(DEATH_REASON_SUICIDE, Attack.new(114514, 0, 0)) end function RunCommand(sourceCmd, player) player:Strike(DEATH_REASON_UNKNOWN, Attack.new(114514, 0, 0)) end ================================================ FILE: contents/commands/killp.json ================================================ { "killp": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_PLAYER" } ], "script": { "path": "kill.lua" } } } ================================================ FILE: contents/commands/master.json ================================================ { "master": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "developer", "parameters": [ { "type": "CP_PLAYER" } ], "script": { "path": "master.lua" } } } ================================================ FILE: contents/commands/master.lua ================================================ function RunCommand(sourceCmd, player) player:SetOP(OP_MASTER) player:SetGameMode(GAME_MODE_CREATIVE) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("master_ok"), player.name)) end ================================================ FILE: contents/commands/me.json ================================================ { "me": { "isClient": false, "fromPlayer": true, "gameMode": "survival", "op": "any", "parameters": [ { "type": "CP_STRING" } ], "script": { "path": "me.lua" } } } ================================================ FILE: contents/commands/me.lua ================================================ function RunCommandFromPlayer(myPlayer, message) local msg = string.format("#H* %s %s", myPlayer.name, message) MiscUtils.BroadcastUTF8(msg) end ================================================ FILE: contents/commands/msg.json ================================================ { "msg": { "isClient": false, "fromPlayer": true, "gameMode": "survival", "op": "any", "parameters": [ { "type": "CP_PLAYER" }, { "type": "CP_STRING" } ], "script": { "path": "msg.lua" } } } ================================================ FILE: contents/commands/msg.lua ================================================ function RunCommandFromPlayer(myPlayer, toPlayer, message) MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("msg_to_content"), toPlayer.name, message)) MiscUtils.UnicastUTF8(toPlayer, string.format(LangUtils.ModText("msg_content"), myPlayer.name, message)) end function RunCommand(sourceCmd, toPlayer, message) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("msg_to_server_content"), toPlayer.name, message)) MiscUtils.UnicastUTF8(toPlayer, string.format(LangUtils.ModText("msg_server_content"), message)) end ================================================ FILE: contents/commands/noadmin.json ================================================ { "noadmin": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "master", "parameters": [ { "type": "CP_PLAYER" } ], "script": { "path": "noadmin.lua" } } } ================================================ FILE: contents/commands/noadmin.lua ================================================ function RunCommand(sourceCmd, player) player:SetOP(OP_ANY) local gameMode = MiscUtils.GetGameMode() player:SetGameMode(gameMode) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("noadmin_ok"), player.name)) end ================================================ FILE: contents/commands/nobanip.json ================================================ { "nobanip": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_STRING" } ], "script": { "path": "nobanip.lua" } } } ================================================ FILE: contents/commands/nobanip.lua ================================================ function RunCommand(sourceCmd, ip) local ok = MiscUtils.RemoveBan(ip) if ok then sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("nobanip_ok"), ip)) else sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("nobanip_fail"), ip)) end end ================================================ FILE: contents/commands/nomaster.json ================================================ { "nomaster": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "developer", "parameters": [ { "type": "CP_PLAYER" } ], "script": { "path": "nomaster.lua" } } } ================================================ FILE: contents/commands/nomaster.lua ================================================ function RunCommand(sourceCmd, player) player:SetOP(OP_ANY) local gameMode = MiscUtils.GetGameMode() player:SetGameMode(gameMode) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("nomaster_ok"), player.name)) end ================================================ FILE: contents/commands/npc.json ================================================ { "npc": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_NPC" }, { "type": "CP_POSITION_CELL_X", "default": "~8" }, { "type": "CP_POSITION_CELL_Y", "default": "~-8" } ], "script": { "path": "npc.lua" } } } ================================================ FILE: contents/commands/npc.lua ================================================ function RunCommand(sourceCmd, npcID, x, y) NpcUtils.Create(npcID, x * 16, y * 16) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("npc_ok"), LangUtils.NpcName(npcID), x, y)) end ================================================ FILE: contents/commands/players.json ================================================ { "players": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "players.lua" } } } ================================================ FILE: contents/commands/players.lua ================================================ function RunCommand(sourceCmd) local onlinePlayers = MiscUtils.GetOnlinePlayerList() local count = onlinePlayers.length for i = 1, count do local player = onlinePlayers[i] local info = string.format(LangUtils.ModText("player_info"), i, player.name, player.ip, player.portNumber) sourceCmd:ResponseUTF8(info) end sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("players_ok"), count)) end ================================================ FILE: contents/commands/port.json ================================================ { "port": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "port.lua" } } } ================================================ FILE: contents/commands/port.lua ================================================ function RunCommand(sourceCmd) local port = MiscUtils.GetPortNumber() sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("port_ok"), port)) end ================================================ FILE: contents/commands/pvp-off.json ================================================ { "pvp-off": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "pvpoff.lua" } } } ================================================ FILE: contents/commands/pvp-on.json ================================================ { "pvp-on": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "pvpon.lua" } } } ================================================ FILE: contents/commands/pvpoff.lua ================================================ function RunCommand(sourceCmd) MiscUtils.SetPVP(false) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("pvp_off_ok"))) end ================================================ FILE: contents/commands/pvpon.lua ================================================ function RunCommand(sourceCmd) MiscUtils.SetPVP(true) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("pvp_on_ok"))) end ================================================ FILE: contents/commands/safeblow-off.json ================================================ { "safeblow-off": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "safeblowoff.lua" } } } ================================================ FILE: contents/commands/safeblow-on.json ================================================ { "safeblow-on": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "safeblowon.lua" } } } ================================================ FILE: contents/commands/safeblowoff.lua ================================================ function RunCommand(sourceCmd) MiscUtils.SetSafeBlow(false) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("safeblow_off_ok"))) end ================================================ FILE: contents/commands/safeblowon.lua ================================================ function RunCommand(sourceCmd) MiscUtils.SetSafeBlow(true) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("safeblow_on_ok"))) end ================================================ FILE: contents/commands/save.json ================================================ { "save": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [], "script": { "path": "save.lua" } } } ================================================ FILE: contents/commands/save.lua ================================================ function RunCommand(sourceCmd) MiscUtils.SaveAll() sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("save_ok"))) end ================================================ FILE: contents/commands/say.json ================================================ { "say": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_STRING" } ], "script": { "path": "say.lua" } } } ================================================ FILE: contents/commands/say.lua ================================================ function RunCommand(sourceCmd, message) MiscUtils.BroadcastUTF8(string.format(LangUtils.ModText("say"), message)) end ================================================ FILE: contents/commands/spawn.json ================================================ { "spawn": { "isClient": false, "fromPlayer": true, "gameMode": "creative", "op": "any", "parameters": [], "script": { "path": "spawn.lua" } } } ================================================ FILE: contents/commands/spawn.lua ================================================ function RunCommandFromPlayer(myPlayer) myPlayer:TeleportToSpawn() MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("spawn_ok"), myPlayer.name)) end ================================================ FILE: contents/commands/state.json ================================================ { "state": { "isClient": false, "fromPlayer": true, "gameMode": "creative", "op": "admin", "parameters": [] } } ================================================ FILE: contents/commands/stopwea.json ================================================ { "stopwea": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "any", "parameters": [], "script": { "path": "stopwea.lua" } } } ================================================ FILE: contents/commands/stopwea.lua ================================================ function RunCommand(sourceCmd) MiscUtils.SetWeatherTime(216000 * 100) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("wea_ok"), 100)) end ================================================ FILE: contents/commands/tp.json ================================================ { "tp": { "isClient": false, "fromPlayer": true, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_POSITION_CELL_X" }, { "type": "CP_POSITION_CELL_Y" } ], "script": { "path": "tp.lua" } } } ================================================ FILE: contents/commands/tp.lua ================================================ function InnerRunCommand(player, x, y) player:Teleport(x * 16, y * 16) end function RunCommandFromPlayer(myPlayer, x, y) InnerRunCommand(myPlayer, x, y) MiscUtils.UnicastUTF8(myPlayer, string.format(LangUtils.ModText("tp_ok"), myPlayer.name, x, y)) end function RunCommand(sourceCmd, player, x, y) InnerRunCommand(player, x, y) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("tp_ok"), player.name, x, y)) end ================================================ FILE: contents/commands/tpp.json ================================================ { "tpp": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "admin", "parameters": [ { "type": "CP_PLAYER" }, { "type": "CP_POSITION_CELL_X" }, { "type": "CP_POSITION_CELL_Y" } ], "script": { "path": "tp.lua" } } } ================================================ FILE: contents/commands/wea.json ================================================ { "wea": { "isClient": false, "fromPlayer": false, "gameMode": "creative", "op": "any", "parameters": [ { "type": "CP_INTEGER", "min": 1, "max": 216000 } ], "script": { "path": "wea.lua" } } } ================================================ FILE: contents/commands/wea.lua ================================================ function RunCommand(sourceCmd, weaTime) MiscUtils.SetWeatherTime(weaTime) local progress = math.floor(weaTime / 86400 * 100) sourceCmd:ResponseUTF8(string.format(LangUtils.ModText("wea_ok"), progress)) end ================================================ FILE: data/backgrounds.json ================================================ { "sun": "backgrounds/sky/elements/sun.png", "moon": "backgrounds/sky/elements/moon.png", "smallClouds": [ "backgrounds/sky/clouds/small.png", "backgrounds/sky/clouds/small2.png", "backgrounds/sky/clouds/small3.png", "backgrounds/sky/clouds/small4.png", "backgrounds/sky/clouds/small5.png" ], "largeClouds": [ "backgrounds/sky/clouds/large.png", "backgrounds/sky/clouds/large2.png" ], "stars": [ "backgrounds/sky/stars/star.png", "backgrounds/sky/stars/star2.png", "backgrounds/sky/stars/star3.png", "backgrounds/sky/stars/star4.png", "backgrounds/sky/stars/star5.png" ], "walls": [ { "stone_wall": "backgrounds/walls/stone_wall.png" }, { "stone_wall_link": "backgrounds/walls/stone_wall_link.png" }, { "dirt_wall": "backgrounds/walls/dirt_wall.png" }, { "dirt_wall_link": "backgrounds/walls/dirt_wall_link.png" }, { "tainted_wall": "backgrounds/walls/tainted_wall.png" }, { "tainted_wall_link": "backgrounds/walls/tainted_wall_link.png" }, { "sand_wall": "backgrounds/walls/sand_wall.png" }, { "sand_wall_link": "backgrounds/walls/sand_wall_link.png" }, { "ice_wall": "backgrounds/walls/ice_wall.png" }, { "ice_wall_link": "backgrounds/walls/ice_wall_link.png" }, { "lava_wall": "backgrounds/walls/lava_wall.png" }, { "lava_wall_link": "backgrounds/walls/lava_wall_link.png" }, { "mud_wall": "backgrounds/walls/mud_wall.png" }, { "mud_wall_link": "backgrounds/walls/mud_wall_link.png" }, { "red_sand_wall": "backgrounds/walls/red_sand_wall.png" }, { "red_sand_wall_link": "backgrounds/walls/red_sand_wall_link.png" }, { "flesh_wall": "backgrounds/walls/flesh_wall.png" }, { "flesh_wall_link": "backgrounds/walls/flesh_wall_link.png" }, { "pile_cave_wall": "backgrounds/walls/pile_cave_wall.png" }, { "long_lava_wall": "backgrounds/walls/long_lava_wall.png" }, { "pile_ice_wall": "backgrounds/walls/pile_ice_wall.png" }, { "mushroom_wall": "backgrounds/walls/mushroom_wall.png" } ], "backgrounds": [ { "large_tree_leaf": "backgrounds/layers/large_tree_leaf.png" }, { "large_tree_leaf2": "backgrounds/layers/large_tree_leaf2.png" }, { "large_tree_stem": "backgrounds/layers/large_tree_stem.png" }, { "snowy_hill": "backgrounds/layers/snowy_hill.png" }, { "dirty_hill": "backgrounds/layers/dirty_hill.png" }, { "stone_hill": "backgrounds/layers/stone_hill.png" }, { "large_grass": "backgrounds/layers/large_grass.png" }, { "large_grass_tree": "backgrounds/layers/large_grass_tree.png" }, { "large_grass_medium_tree": "backgrounds/layers/large_grass_medium_tree.png" }, { "large_grass_small_tree": "backgrounds/layers/large_grass_small_tree.png" }, { "large_bush": "backgrounds/layers/large_bush.png" }, { "desert_back": "backgrounds/layers/desert_back.png" }, { "desert_hill": "backgrounds/layers/desert_hill.png" }, { "desert_hill_new": "backgrounds/layers/desert_hill_new.png" }, { "desert_hill_new_2": "backgrounds/layers/desert_hill_new_2.png" }, { "desert_back_hill": "backgrounds/layers/desert_back_hill.png" }, { "desert": "backgrounds/layers/desert.png" }, { "desert_2": "backgrounds/layers/desert_2.png" }, { "desert_back_hill2": "backgrounds/layers/desert_back_hill2.png" }, { "desert_back_hill3": "backgrounds/layers/desert_back_hill3.png" }, { "desert_front": "backgrounds/layers/desert_front.png" }, { "desert_rock": "backgrounds/layers/desert_rock.png" }, { "snow_back": "backgrounds/layers/snow_back.png" }, { "snow_hill": "backgrounds/layers/snow_hill.png" }, { "snow_trees": "backgrounds/layers/snow_trees.png" }, { "snow_trees2": "backgrounds/layers/snow_trees2.png" }, { "snow_trees3": "backgrounds/layers/snow_trees3.png" }, { "snow_dune": "backgrounds/layers/snow_dune.png" }, { "jungle_bush": "backgrounds/layers/jungle_bush.png" }, { "tainted_hill": "backgrounds/layers/tainted_hill.png" }, { "tainted_hill2": "backgrounds/layers/tainted_hill2.png" }, { "tainted_bush": "backgrounds/layers/tainted_bush.png" }, { "tainted_bush_strick": "backgrounds/layers/tainted_bush_strick.png" }, { "tainted_rock": "backgrounds/layers/tainted_rock.png" }, { "lava_lake": "backgrounds/layers/lava_lake.png" }, { "lava_layer": "backgrounds/layers/lava_layer.png" }, { "lava_rock": "backgrounds/layers/lava_rock.png" }, { "lava_pile": "backgrounds/layers/lava_pile.png" }, { "lava_layer_hanging": "backgrounds/layers/lava_layer_hanging.png" }, { "lava_rock_hanging": "backgrounds/layers/lava_rock_hanging.png" }, { "lava_pile_hanging": "backgrounds/layers/lava_pile_hanging.png" }, { "fossil": "backgrounds/layers/fossil.png" }, { "waste_back": "backgrounds/layers/waste_back.png" }, { "waste_back2": "backgrounds/layers/waste_back2.png" }, { "waste_hill": "backgrounds/layers/waste_hill.png" }, { "waste_hill2": "backgrounds/layers/waste_hill2.png" }, { "flesh_fossil": "backgrounds/layers/flesh_fossil.png" }, { "flesh_fossil2": "backgrounds/layers/flesh_fossil2.png" }, { "flesh_back": "backgrounds/layers/flesh_back.png" }, { "flesh_back2": "backgrounds/layers/flesh_back2.png" }, { "flesh_hill": "backgrounds/layers/flesh_hill.png" }, { "flesh_hill2": "backgrounds/layers/flesh_hill2.png" }, { "flesh_bush": "backgrounds/layers/flesh_bush.png" }, { "mushroom_grass": "backgrounds/layers/mushroom_grass.png" }, { "large_mushrooms": "backgrounds/layers/large_mushrooms.png" }, { "large_mushrooms2": "backgrounds/layers/large_mushrooms2.png" }, { "volcano_back": "backgrounds/layers/volcano_back.png" }, { "volcano_back2": "backgrounds/layers/volcano_back2.png" }, { "volcano_back3": "backgrounds/layers/volcano_back3.png" }, { "snowy_hill2": "backgrounds/layers/snowy_hill2.png" }, { "tainted_hill3": "backgrounds/layers/tainted_hill3.png" }, { "flesh_hill3": "backgrounds/layers/flesh_hill3.png" }, { "waste_hill3": "backgrounds/layers/waste_hill3.png" }, { "volcano_hill": "backgrounds/layers/volcano_hill.png" }, { "snow_mountain": "backgrounds/layers/snow_mountain.png" }, { "snow_trees_new": "backgrounds/layers/snow_trees_new.png" }, { "snow_trees_new2": "backgrounds/layers/snow_trees_new2.png" } ] } ================================================ FILE: data/block_config.json ================================================ { "exParticles": [ { "torch_particle": [ { "condition": { "checkInterval": true, "intervalTime": 24 }, "action": { "effectId": "fire_smoke", "offsetX": [ 6, 10 ], "offsetY": [ -4, 0 ], "speedX": [ -0.25, 0.25 ], "speedY": [ -0.5 ], "rotateSpeed": [ -0.05, 0.05 ], "scale": [ 0.95, 1.45 ], "alpha": [ 0.8 ], "color": [ 255, 255, 255, 255 ] } }, { "condition": { "checkRandom": true, "randomTimes": 256 }, "action": { "effectId": "liquid_paticular", "offsetX": [ 6, 10 ], "offsetY": [ -4, 0 ], "speedX": [ -0.25, 0.25 ], "speedY": [ -2.0 ], "rotateSpeed": [ -0.05, 0.05 ], "scale": [ 0.5 ], "alpha": [ 1.0 ], "color": [ 255, 255, 255, 0 ] } } ] }, { "campfire_particle": [ { "condition": { "checkInterval": true, "intervalTime": 32 }, "action": { "effectId": "fire_smoke", "offsetX": [ 10, 22 ], "offsetY": [ 4, 12 ], "speedX": [ -0.25, 0.25 ], "speedY": [ -2.0 ], "rotateSpeed": [ -0.05, 0.05 ], "scale": [ 1.8, 2.2 ], "alpha": [ 0.8 ], "color": [ 255, 255, 255, 255 ] } }, { "condition": { "checkRandom": true, "randomTimes": 256 }, "action": { "effectId": "liquid_paticular", "offsetX": [ 10, 22 ], "offsetY": [ 4, 12 ], "speedX": [ -1.25, 1.25 ], "speedY": [ -2.0 ], "rotateSpeed": [ -0.05, 0.05 ], "scale": [ 0.5 ], "alpha": [ 1.0 ], "color": [ 255, 255, 255, 0 ] } } ] }, { "end_rod_particle": [ { "condition": { "checkRandom": true, "randomTimes": 256 }, "action": { "effectId": "liquid_paticular", "offsetX": [ 6, 10 ], "offsetY": [ 6, 10 ], "speedX": [ -1.25, 1.25 ], "speedY": [ -2.0, 0.0 ], "rotateSpeed": [ -0.05, 0.05 ], "scale": [ 0.85, 1.0 ], "alpha": [ 1.0 ], "color": [ 255, 255, 255, 255 ] } } ] }, { "ore_particle": [ { "condition": { "checkRandom": true, "randomTimes": 512, "checkLighting": true, "lightingArea": [ 18, 32 ] }, "action": { "effectId": "flash", "offsetX": [ 0, 16 ], "offsetY": [ 0, 16 ], "speedX": [ 0.0 ], "speedY": [ 0.0 ], "rotateSpeed": [ 0.0 ], "scale": [ 2.0 ], "alpha": [ 1.0 ], "color": [ 255, 255, 255, 255 ] } } ] }, { "furnace_particle": [ { "condition": { "checkInterval": true, "intervalTime": 16, "checkAnimation": true, "animationIndex": 1 }, "action": { "effectId": "fire", "offsetX": [ 18, 30 ], "offsetY": [ 20, 28 ], "speedX": [ 0.0 ], "speedY": [ 0.0 ], "rotateSpeed": [ 0.0 ], "scale": [ 0.8, 1.2 ], "alpha": [ 1.0 ], "color": [ 255, 255, 255, 255 ] } }, { "condition": { "checkInterval": true, "intervalTime": 32, "checkAnimation": true, "animationIndex": 1 }, "action": { "effectId": "fire_smoke", "offsetX": [ 22, 26 ], "offsetY": [ 20, 28 ], "speedX": [ -0.25, 0.25 ], "speedY": [ -0.5 ], "rotateSpeed": [ -0.05, 0.05 ], "scale": [ 0.9, 1.5 ], "alpha": [ 1.0 ], "color": [ 255, 255, 255, 255 ] } } ] } ], "growGroups": [ { "NORMAL_GROUP": [ [ "grass", 100 ], [ "grass", 100 ], [ "dandelion", 10 ], [ "allium", 10 ], [ "sunflower", 5 ], [ "brown_mushroom", 20 ], [ "red_mushroom", 20 ], [ "large_brown_mushroom", 5 ], [ "large_red_mushroom", 5 ], [ "lilac", 5 ], [ "red_tulip", 8 ], [ "white_tulip", 8 ], [ "orange_tulip", 8 ], [ "pink_tulip", 8 ], [ "azure_bluet", 8 ], [ "blue_orchid", 8 ], [ "fern", 6 ], [ "peony", 5 ], [ "rose_bush", 5 ], [ "poppy", 8 ] ] }, { "TAINTED_GROUP": [ [ "tainted_grass", 10 ] ] }, { "FLESH_GROUP": [ [ "blood_grass", 10 ] ] } ], "hangGrowGroups": [ { "NORMAL_GROUP": [ [ "vine", 10 ] ] }, { "TAINTED_GROUP": [ [ "tainted_vine", 10 ] ] }, { "FLESH_GROUP": [ [ "eyeball_vine", 10 ] ] } ], "farmGroups": [ { "FARMLAND_GROUP": [ "melon_seed", "pumpkin_seed", "seed", "sugar_cane", "carrot", "potato" ] }, { "SAND_GROUP": [ "sugar_cane" ] }, { "SOULSAND_GROUP": [ "nether_wart" ] } ], "placeChecks": [ { "PLACE_TREE_CHECK": { "bottomBlocks": [], "topBlocks": [] } }, { "PLACE_PLANT_CHECK": { "bottomBlocks": [], "topBlocks": [] } }, { "PLACE_VINE_CHECK": { "bottomBlocks": [], "topBlocks": [ "dirt", "coarse_dirt", "tainted_dirt", "tainted_stone", "flesh_dirt" ] } }, { "PLACE_STONE_DECO_CHECK": { "bottomBlocks": [ "cobblestone", "stone" ], "topBlocks": [ "cobblestone", "stone" ] } }, { "PLACE_ICE_DECO_CHECK": { "bottomBlocks": [ "snow", "snow_soft", "ice_cobblestone", "ice_cobblestone_hard" ], "topBlocks": [ "snow", "snow_soft", "ice_cobblestone", "ice_cobblestone_hard" ] } }, { "PLACE_JUNGLE_DECO_CHECK": { "bottomBlocks": [ "dirt", "coarse_dirt" ], "topBlocks": [ "dirt", "coarse_dirt" ] } }, { "PLACE_SAND_DECO_CHECK": { "bottomBlocks": [ "sandstone", "red_sand_stone" ], "topBlocks": [ "sandstone", "red_sand_stone" ] } }, { "PLACE_TAINTED_DECO_CHECK": { "bottomBlocks": [ "tainted_dirt", "tainted_stone" ], "topBlocks": [ "tainted_dirt", "tainted_stone" ] } }, { "PLACE_WASTE_DECO_CHECK": { "bottomBlocks": [ "red_sand_stone" ], "topBlocks": [ "red_sand_stone" ] } }, { "PLACE_UNDERWATER_CHECK": { "bottomBlocks": [ "sandstone" ], "topBlocks": [] } }, { "PLACE_ANDESITE_DECO_CHECK": { "bottomBlocks": [ "andesite" ], "topBlocks": [ "andesite" ] } }, { "PLACE_DIORITE_DECO_CHECK": { "bottomBlocks": [ "diorite" ], "topBlocks": [ "diorite" ] } }, { "PLACE_GRANITE_DECO_CHECK": { "bottomBlocks": [ "granite" ], "topBlocks": [ "granite" ] } }, { "PLACE_OBSIDIAN_DECO_CHECK": { "bottomBlocks": [ "obsidian" ], "topBlocks": [ "obsidian" ] } }, { "PLACE_MUSHROOM_CHECK": { "bottomBlocks": [ "brown_mushroom_block", "red_mushroom_block", "mycelium" ], "topBlocks": [] } }, { "PLACE_BLUE_MUSHROOM_CHECK": { "bottomBlocks": [ "blue_mushroom_dirt", "blue_mushroom_stem" ], "topBlocks": [] } } ], "ores": { "none": [], "default": [ { "oreId": "ore_iron", "density": 625, "radius": 4, "startYi": 400, "endYi": 2560 }, { "oreId": "ore_gold", "density": 312, "radius": 5, "startYi": 1000, "endYi": 2560 }, { "oreId": "ore_coal", "density": 500, "radius": 5, "startYi": 400, "endYi": 2560 }, { "oreId": "ore_diamond", "density": 230, "radius": 2, "startYi": 1400, "endYi": 2560 }, { "oreId": "ore_emerald", "density": 190, "radius": 2, "startYi": 1000, "endYi": 2560 }, { "oreId": "ore_lapis", "density": 320, "radius": 3, "startYi": 1200, "endYi": 2560 }, { "oreId": "ore_redstone", "density": 850, "radius": 4, "startYi": 1800, "endYi": 2560 }, { "oreId": "ore_copper", "density": 700, "radius": 4, "startYi": 300, "endYi": 2560 }, { "oreId": "ore_tin", "density": 650, "radius": 4, "startYi": 300, "endYi": 2560 }, { "oreId": "ore_lead", "density": 550, "radius": 4, "startYi": 600, "endYi": 2560 }, { "oreId": "ore_silver", "density": 800, "radius": 4, "startYi": 1200, "endYi": 2560 }, { "oreId": "ore_ancient_debris", "density": 180, "radius": 3, "startYi": 2560, "endYi": 3072 }, { "oreId": "ore_nether_quartz", "density": 600, "radius": 4, "startYi": 2560, "endYi": 3072 } ] }, "groups": [ "ORE_GOLD", "ORE_DIAMOND", "ORE_REDSTONE", "ORE_IRON", "ORE_EMERALD", "ORE_LAPIS", "ORE_COAL", "MUSHROOM", "DIRT", "COARSE_DIRT", "TAINTED_DIRT", "COBBLESTONE", "TAINTED_STONE", "STONE", "OBSIDIAN", "PRISMARINE", "DIORITE", "GRANITE", "ANDESITE", "GRAVEL", "CLAY", "SNOW", "ICE", "SAND", "REDSAND", "FLESH_DIRT", "FLESH_STONE", "FLESH_GUT", "MYCELIUM", "GLOWSTONE", "SOUL_SAND", "NETHERRACK", "MAGMA_BLOCK", "ENDSTONE", "ICECOBBLESTONE", "SANDSTONE", "RED_SAND_STONE", "SPONGE", "SLIME_BLOCK", "THRON", "STONE_BRICK", "SANDSTONE_CARVED", "SANDSTONE_SMOOTH", "WOOD_A", "WOOD_B", "ARTIFICAL", "PLATFORM", "FENCE", "BAR", "GLASS", "FURNITURE_ALL", "TREE_ALL" ], "subGroups": [ "BED", "CLOSED_DOOR", "OPENED_DOOR", "BOOKCASE", "PRESSURE_PLATE", "WOOD", "LOG" ] } ================================================ FILE: data/item_config.json ================================================ { "ammos": [ "arrow", "bullet", "rocket" ], "toolGrade": [ ["NONE", 0], ["GRASS", 100], ["WOOD", 200], ["STONE", 300], ["IRON", 400], ["GOLD", 500], ["DIAMOND", 600] ], "oreDictionary": [ "OD_IRON_INGOT", "OD_COPPER_INGOT", "OD_TERRACOTTA", "OD_WOODEN_PLATFORM", "OD_WOODEN_PLANK", "OD_WOOD", "OD_WOOD_STRIPPED", "OD_WOOL", "OD_GLASS", "OD_BOOKCASE", "OD_STAFF", "OD_SWORD", "OD_HOE" ], "sub_groups": [ "SUB_GROUP_DIAMOND", "SUB_GROUP_NETHERITE" ], "groups": [ { "name": "ALL", "list": [] }, { "name": "NATURE", "itemIconId": "dirt", "list": [ "GROUP_DIRT", "GROUP_STONE", "GROUP_COBBLESTONE", "GROUP_ANDESITE", "GROUP_DIORITE", "GROUP_GRANITE", "GROUP_PRISMARINE", "GROUP_SAND", "GROUP_RED_SAND", "GROUP_ENDSTONE", "GROUP_NETHER", "GROUP_SNOW", "GROUP_ICE", "GROUP_ICE_COBBLESTONE", "GROUP_MUSHROOM_BLOCK", "GROUP_FLESH", "GROUP_TAINTED", "GROUP_VOLCANO", "GROUP_LOG", "GROUP_ORE", "GROUP_OTHERS_BLOCK" ] }, { "name": "MANMADE", "itemIconId": "stone_brick", "list": [ "GROUP_STONE_BRICK", "GROUP_ENDSTONE_BRICK", "GROUP_NETHER_BRICK", "GROUP_SNOW_BRICK", "GROUP_ICE_BRICK", "GROUP_GLASS", "GROUP_WOODEN_PLANK", "GROUP_WOODEN_PLATFORM", "GROUP_PLATFORM", "GROUP_WOOD", "GROUP_WOOD_STRIPPED", "GROUP_TERRACOTTA", "GROUP_WOOL", "GROUP_ORE_BLOCK" ] }, { "name": "PLANT", "itemIconId": "orange_tulip", "list": [ "GROUP_GRASS", "GROUP_FLOWER", "GROUP_LARGE_FLOWER", "GROUP_SAPLING", "GROUP_PUMPKIN", "GROUP_MELON" ] }, { "name": "FURNITURE", "itemIconId": "crafting_table", "list": [ "GROUP_WOODEN_FENCE", "GROUP_STONE_FENCE", "GROUP_NETHER_FENCE", "GROUP_PAINTING", "GROUP_WOODEN_FURNITURE", "GROUP_WOODEN_BED", "GROUP_WOODEN_TABLE", "GROUP_WOODEN_CABINET", "GROUP_WOODEN_CHAIR", "GROUP_BOOKCASE", "GROUP_BENCH", "GROUP_STONE_FURNITURE", "GROUP_OTHERS_FURNITURE", "GROUP_SHULKER_BOX", "GROUP_PRESSURE_PLATE", "GROUP_DOOR", "GROUP_TORCH", "GROUP_LIGHTING", "GROUP_BUTTON", "GROUP_TOWER" ] }, { "name": "REDSTONE", "itemIconId": "redstone", "list": [ "GROUP_REDSTONE_WIRE", "GROUP_WIRE_CUTTER" ] }, { "name": "FOOD", "itemIconId": "apple", "list": [ "GROUP_FOOD" ] }, { "name": "TOOL", "itemIconId": "wooden_pickaxe", "list": [ "GROUP_BUCKET", "GROUP_AXE", "GROUP_PICKAXE", "GROUP_HOE", "GROUP_FISHINGROD", "GROUP_SHEARS", "GROUP_LIGHTER", "GROUP_DRILL", "GROUP_SAW", "GROUP_MAP", "GROUP_DROPABLE", "GROUP_BOOK", "GROUP_TOWER_CORE" ] }, { "name": "WEAPON", "itemIconId": "stone_sword", "list": [ "GROUP_HELMET", "GROUP_CHESTPLATE", "GROUP_LEGGINGS", "GROUP_SWORD", "GROUP_BOW", "GROUP_CROSS_BOW", "GROUP_GUN", "GROUP_LAUNCHER", "GROUP_ARROW", "GROUP_BULLET", "GROUP_ROCKET", "GROUP_BOMB", "GROUP_STAFF", "GROUP_BOOMERANG", "GROUP_LOOT" ] }, { "name": "POTION", "itemIconId": "potion_awkward", "list": [ "GROUP_POTION" ] }, { "name": "MATERIAL", "itemIconId": "stick", "list": [ "GROUP_STICK", "GROUP_MATERIAL", "GROUP_DYE", "GROUP_SEED", "GROUP_MANA", "GROUP_BOSS" ] }, { "name": "GOODS", "itemIconId": "iron_ingot", "list": [ "GROUP_DIAMOND", "GROUP_EMERALD", "GROUP_LAPIS", "GROUP_QUARTZ", "GROUP_REDSTONE", "GROUP_NUGGET", "GROUP_INGOT" ] } ] } ================================================ FILE: data/sound_config.json ================================================ { "soundGroup": [ { "step_grass": [ "step_snow1", "step_snow2", "step_snow3", "step_snow4" ] }, { "step_stone": [ "step_stone1", "step_stone2", "step_stone3", "step_stone4", "step_stone5", "step_stone6" ] }, { "step_wood": [ "step_wood1", "step_wood2", "step_wood3", "step_wood4", "step_wood5", "step_wood6" ] }, { "step_snow": [ "step_snow1", "step_snow2", "step_snow3", "step_snow4" ] }, { "dirt": [ "dirt1", "dirt2", "dirt3" ] }, { "sand": [ "sand1", "sand2", "sand3" ] }, { "stone": [ "stone1", "stone2", "stone3" ] }, { "wood": [ "wood1", "wood2", "wood3" ] }, { "snow": [ "snow1", "snow2", "snow3" ] }, { "grass": [ "grass1", "grass2", "grass3" ] }, { "shatter": [ "shatter1", "shatter2", "shatter3" ] }, { "glass": [ "glass1", "glass2", "glass3" ] }, { "cloth": [ "cloth1", "cloth2", "cloth3" ] }, { "tink": [ "tink1", "tink2", "tink3" ] }, { "swim": [ "swim1", "swim2", "swim3", "swim4" ] }, { "farm": [ "sand1", "sand2", "sand3" ] }, { "strip": [ "strip1", "strip2", "strip3", "strip4" ] }, { "door": [ "door1", "door2" ] }, { "explode": [ "explode1", "explode2", "explode3", "explode4" ] }, { "portal": [ "portal", "portal2" ] }, { "hit": [ "hit1", "hit2", "hit3" ] }, { "eat": [ "eat1", "eat2", "eat3" ] }, { "thunder": [ "thunder1", "thunder2", "thunder3" ] }, { "rain": [ "rain1", "rain2", "rain3", "rain4" ] }, { "wand": [ "wand1", "wand2", "wand3" ] }, { "thorns_hit": [ "thorns_hit1", "thorns_hit2", "thorns_hit3", "thorns_hit4" ] }, { "enchant": [ "enchant1", "enchant2", "enchant3" ] } ] } ================================================ FILE: data/sounds.json ================================================ [ { "sys3": { "path": "sounds/sys3.ogg" } }, { "cannon": { "path": "sounds/cannon.ogg" } }, { "pop": { "path": "sounds/pop.ogg" } }, { "stone1": { "path": "sounds/stone1.ogg" } }, { "stone2": { "path": "sounds/stone2.ogg" } }, { "stone3": { "path": "sounds/stone3.ogg" } }, { "dirt1": { "path": "sounds/dirt1.ogg" } }, { "dirt2": { "path": "sounds/dirt2.ogg" } }, { "dirt3": { "path": "sounds/dirt3.ogg" } }, { "wood1": { "path": "sounds/wood1.ogg" } }, { "wood2": { "path": "sounds/wood2.ogg" } }, { "wood3": { "path": "sounds/wood3.ogg" } }, { "grass1": { "path": "sounds/grass1.ogg" } }, { "grass2": { "path": "sounds/grass2.ogg" } }, { "grass3": { "path": "sounds/grass3.ogg" } }, { "cloth1": { "path": "sounds/cloth1.ogg" } }, { "cloth2": { "path": "sounds/cloth2.ogg" } }, { "cloth3": { "path": "sounds/cloth3.ogg" } }, { "sand1": { "path": "sounds/sand1.ogg" } }, { "sand2": { "path": "sounds/sand2.ogg" } }, { "sand3": { "path": "sounds/sand3.ogg" } }, { "step_cloth": { "path": "sounds/step_cloth.ogg" } }, { "step_grass1": { "path": "sounds/step_grass1.ogg" } }, { "step_grass2": { "path": "sounds/step_grass2.ogg" } }, { "step_grass3": { "path": "sounds/step_grass3.ogg" } }, { "step_grass4": { "path": "sounds/step_grass4.ogg" } }, { "step_grass5": { "path": "sounds/step_grass5.ogg" } }, { "step_grass6": { "path": "sounds/step_grass6.ogg" } }, { "step_ladder": { "path": "sounds/step_ladder.ogg" } }, { "step_sand": { "path": "sounds/step_sand.ogg" } }, { "step_snow1": { "path": "sounds/step_snow1.ogg" } }, { "step_snow2": { "path": "sounds/step_snow2.ogg" } }, { "step_snow3": { "path": "sounds/step_snow3.ogg" } }, { "step_snow4": { "path": "sounds/step_snow4.ogg" } }, { "step_stone1": { "path": "sounds/step_stone1.ogg" } }, { "step_stone2": { "path": "sounds/step_stone2.ogg" } }, { "step_stone3": { "path": "sounds/step_stone3.ogg" } }, { "step_stone4": { "path": "sounds/step_stone4.ogg" } }, { "step_stone5": { "path": "sounds/step_stone5.ogg" } }, { "step_stone6": { "path": "sounds/step_stone6.ogg" } }, { "step_wood1": { "path": "sounds/step_wood1.ogg" } }, { "step_wood2": { "path": "sounds/step_wood2.ogg" } }, { "step_wood3": { "path": "sounds/step_wood3.ogg" } }, { "step_wood4": { "path": "sounds/step_wood4.ogg" } }, { "step_wood5": { "path": "sounds/step_wood5.ogg" } }, { "step_wood6": { "path": "sounds/step_wood6.ogg" } }, { "bowhit": { "path": "sounds/bowhit.ogg" } }, { "bow": { "path": "sounds/bow.ogg" } }, { "explode1": { "path": "sounds/explode1.ogg" } }, { "explode2": { "path": "sounds/explode2.ogg" } }, { "explode3": { "path": "sounds/explode3.ogg" } }, { "explode4": { "path": "sounds/explode4.ogg" } }, { "launch": { "path": "sounds/launch.ogg" } }, { "broken": { "path": "sounds/broken.ogg" } }, { "chest": { "path": "sounds/chest.ogg" } }, { "chestclosed": { "path": "sounds/chestclosed.ogg" } }, { "glass1": { "path": "sounds/glass1.ogg" } }, { "glass2": { "path": "sounds/glass2.ogg" } }, { "glass3": { "path": "sounds/glass3.ogg" } }, { "button1": { "path": "sounds/button1.ogg" } }, { "door1": { "path": "sounds/door1.ogg" } }, { "door2": { "path": "sounds/door2.ogg" } }, { "hit1": { "path": "sounds/hit1.ogg" } }, { "hit2": { "path": "sounds/hit2.ogg" } }, { "hit3": { "path": "sounds/hit3.ogg" } }, { "creeper1": { "path": "sounds/creeper1.ogg" } }, { "creeper2": { "path": "sounds/creeper2.ogg" } }, { "creeper3": { "path": "sounds/creeper3.ogg" } }, { "creeper_death": { "path": "sounds/creeper_death.ogg" } }, { "slime_attack1": { "path": "sounds/slime_attack1.ogg" } }, { "slime_attack2": { "path": "sounds/slime_attack2.ogg" } }, { "splash": { "path": "sounds/splash.ogg" } }, { "lavapop": { "path": "sounds/lavapop.ogg" } }, { "pig_death": { "path": "sounds/pig_death.ogg" } }, { "pig_say1": { "path": "sounds/pig_say1.ogg" } }, { "pig_say2": { "path": "sounds/pig_say2.ogg" } }, { "pig_say3": { "path": "sounds/pig_say3.ogg" } }, { "zombie_death": { "path": "sounds/zombie_death.ogg" } }, { "zombie_say1": { "path": "sounds/zombie_say1.ogg" } }, { "zombie_say2": { "path": "sounds/zombie_say2.ogg" } }, { "zombie_say3": { "path": "sounds/zombie_say3.ogg" } }, { "zombie_hurt1": { "path": "sounds/zombie_hurt1.ogg" } }, { "zombie_hurt2": { "path": "sounds/zombie_hurt2.ogg" } }, { "skeleton_death": { "path": "sounds/skeleton_death.ogg" } }, { "skeleton1": { "path": "sounds/skeleton1.ogg" } }, { "skeleton2": { "path": "sounds/skeleton2.ogg" } }, { "skeleton3": { "path": "sounds/skeleton3.ogg" } }, { "spider_death": { "path": "sounds/spider_death.ogg" } }, { "spider_say1": { "path": "sounds/spider_say1.ogg" } }, { "spider_say2": { "path": "sounds/spider_say2.ogg" } }, { "spider_say3": { "path": "sounds/spider_say3.ogg" } }, { "bat_death": { "path": "sounds/bat_death.ogg" } }, { "bat_hurt1": { "path": "sounds/bat_hurt1.ogg" } }, { "bat_hurt2": { "path": "sounds/bat_hurt2.ogg" } }, { "bat_hurt3": { "path": "sounds/bat_hurt3.ogg" } }, { "chicken_say1": { "path": "sounds/chicken_say1.ogg" } }, { "chicken_say2": { "path": "sounds/chicken_say2.ogg" } }, { "chicken_say3": { "path": "sounds/chicken_say3.ogg" } }, { "chicken_hurt1": { "path": "sounds/chicken_hurt1.ogg" } }, { "chicken_hurt2": { "path": "sounds/chicken_hurt2.ogg" } }, { "sheep_say1": { "path": "sounds/sheep_say1.ogg" } }, { "sheep_say2": { "path": "sounds/sheep_say2.ogg" } }, { "sheep_say3": { "path": "sounds/sheep_say3.ogg" } }, { "cow_say1": { "path": "sounds/cow_say1.ogg" } }, { "cow_say2": { "path": "sounds/cow_say2.ogg" } }, { "cow_say3": { "path": "sounds/cow_say3.ogg" } }, { "cow_hurt1": { "path": "sounds/cow_hurt1.ogg" } }, { "cow_hurt2": { "path": "sounds/cow_hurt2.ogg" } }, { "cow_hurt3": { "path": "sounds/cow_hurt3.ogg" } }, { "cat_meow1": { "path": "sounds/cat_meow1.ogg" } }, { "cat_meow2": { "path": "sounds/cat_meow2.ogg" } }, { "cat_meow3": { "path": "sounds/cat_meow3.ogg" } }, { "cat_hit1": { "path": "sounds/cat_hit1.ogg" } }, { "cat_hit2": { "path": "sounds/cat_hit2.ogg" } }, { "cat_hit3": { "path": "sounds/cat_hit3.ogg" } }, { "rabbit_hurt1": { "path": "sounds/rabbit_hurt1.ogg" } }, { "rabbit_hurt2": { "path": "sounds/rabbit_hurt2.ogg" } }, { "rabbit_hurt3": { "path": "sounds/rabbit_hurt3.ogg" } }, { "turtle_hurt1": { "path": "sounds/turtle_hurt1.ogg" } }, { "turtle_hurt2": { "path": "sounds/turtle_hurt2.ogg" } }, { "turtle_hurt3": { "path": "sounds/turtle_hurt3.ogg" } }, { "turtle_death": { "path": "sounds/turtle_death.ogg" } }, { "villager_say1": { "path": "sounds/villager_say1.ogg" } }, { "villager_say2": { "path": "sounds/villager_say2.ogg" } }, { "villager_say3": { "path": "sounds/villager_say3.ogg" } }, { "villager_hit1": { "path": "sounds/villager_hit1.ogg" } }, { "villager_hit2": { "path": "sounds/villager_hit2.ogg" } }, { "villager_hit3": { "path": "sounds/villager_hit3.ogg" } }, { "villager_death": { "path": "sounds/villager_death.ogg" } }, { "fuse": { "path": "sounds/fuse.ogg" } }, { "pufferfish_hurt1": { "path": "sounds/pufferfish_hurt1.ogg" } }, { "pufferfish_hurt2": { "path": "sounds/pufferfish_hurt2.ogg" } }, { "dolphin_hurt1": { "path": "sounds/dolphin_hurt1.ogg" } }, { "dolphin_hurt2": { "path": "sounds/dolphin_hurt2.ogg" } }, { "dolphin_hurt3": { "path": "sounds/dolphin_hurt3.ogg" } }, { "wolf_hurt1": { "path": "sounds/wolf_hurt1.ogg" } }, { "wolf_hurt2": { "path": "sounds/wolf_hurt2.ogg" } }, { "wolf_hurt3": { "path": "sounds/wolf_hurt3.ogg" } }, { "wolf_bark1": { "path": "sounds/wolf_bark1.ogg" } }, { "wolf_bark2": { "path": "sounds/wolf_bark2.ogg" } }, { "wolf_bark3": { "path": "sounds/wolf_bark3.ogg" } }, { "wolf_death": { "path": "sounds/wolf_death.ogg" } }, { "enderman_death": { "path": "sounds/enderman_death.ogg" } }, { "enderman_hit1": { "path": "sounds/enderman_hit1.ogg" } }, { "enderman_hit2": { "path": "sounds/enderman_hit2.ogg" } }, { "enderman_hit3": { "path": "sounds/enderman_hit3.ogg" } }, { "enderman_idle1": { "path": "sounds/enderman_idle1.ogg" } }, { "enderman_idle2": { "path": "sounds/enderman_idle2.ogg" } }, { "enderman_idle3": { "path": "sounds/enderman_idle3.ogg" } }, { "portal": { "path": "sounds/portal.ogg" } }, { "portal2": { "path": "sounds/portal2.ogg" } }, { "zpig1": { "path": "sounds/zpig1.ogg" } }, { "zpig2": { "path": "sounds/zpig2.ogg" } }, { "zpig3": { "path": "sounds/zpig3.ogg" } }, { "zpighurt1": { "path": "sounds/zpighurt1.ogg" } }, { "zpighurt2": { "path": "sounds/zpighurt2.ogg" } }, { "zpigdeath": { "path": "sounds/zpigdeath.ogg" } }, { "blaze_death": { "path": "sounds/blaze_death.ogg" } }, { "blaze_hit1": { "path": "sounds/blaze_hit1.ogg" } }, { "blaze_hit2": { "path": "sounds/blaze_hit2.ogg" } }, { "blaze_hit3": { "path": "sounds/blaze_hit3.ogg" } }, { "fireball": { "path": "sounds/fireball.ogg" } }, { "affectionate_scream": { "path": "sounds/affectionate_scream.ogg" } }, { "ghast_charge": { "path": "sounds/ghast_charge.ogg" } }, { "ghast_death": { "path": "sounds/ghast_death.ogg" } }, { "ghast_moan1": { "path": "sounds/ghast_moan1.ogg" } }, { "ghast_moan2": { "path": "sounds/ghast_moan2.ogg" } }, { "ghast_moan3": { "path": "sounds/ghast_moan3.ogg" } }, { "phantom_death": { "path": "sounds/phantom_death.ogg" } }, { "phantom_hurt1": { "path": "sounds/phantom_hurt1.ogg" } }, { "phantom_hurt2": { "path": "sounds/phantom_hurt2.ogg" } }, { "phantom_hurt3": { "path": "sounds/phantom_hurt3.ogg" } }, { "shulker_open": { "path": "sounds/shulker_open.ogg" } }, { "shulker_close": { "path": "sounds/shulker_close.ogg" } }, { "shulker_hit1": { "path": "sounds/shulker_hit1.ogg" } }, { "orb": { "path": "sounds/orb.ogg" } }, { "levelup": { "path": "sounds/levelup.ogg" } }, { "drink": { "path": "sounds/drink.ogg" } }, { "eat1": { "path": "sounds/eat1.ogg" } }, { "eat2": { "path": "sounds/eat2.ogg" } }, { "eat3": { "path": "sounds/eat3.ogg" } }, { "system1": { "path": "sounds/system1.ogg" } }, { "anvil_use": { "path": "sounds/anvil_use.ogg" } }, { "shear": { "path": "sounds/shear.ogg" } }, { "swim1": { "path": "sounds/swim1.ogg" } }, { "swim2": { "path": "sounds/swim2.ogg" } }, { "swim3": { "path": "sounds/swim3.ogg" } }, { "swim4": { "path": "sounds/swim4.ogg" } }, { "system2": { "path": "sounds/system2.ogg" } }, { "shotgun_fire": { "path": "sounds/shotgun_fire.ogg" } }, { "click": { "path": "sounds/click.ogg" } }, { "female_hit1": { "path": "sounds/female_hit1.ogg" } }, { "female_hit2": { "path": "sounds/female_hit2.ogg" } }, { "female_hit3": { "path": "sounds/female_hit3.ogg" } }, { "shatter1": { "path": "sounds/shatter1.ogg" } }, { "tink1": { "path": "sounds/tink1.ogg" } }, { "tink2": { "path": "sounds/tink2.ogg" } }, { "tink3": { "path": "sounds/tink3.ogg" } }, { "rain1": { "path": "sounds/rain1.ogg" } }, { "rain2": { "path": "sounds/rain2.ogg" } }, { "rain3": { "path": "sounds/rain3.ogg" } }, { "rain4": { "path": "sounds/rain4.ogg" } }, { "thunder1": { "path": "sounds/thunder1.ogg" } }, { "thunder2": { "path": "sounds/thunder2.ogg" } }, { "thunder3": { "path": "sounds/thunder3.ogg" } }, { "grass": { "path": "sounds/grass.ogg" } }, { "weapon": { "path": "sounds/weapon.ogg" } }, { "anvil_land": { "path": "sounds/anvil_land.ogg" } }, { "bazooka_fire": { "path": "sounds/bazooka_fire.ogg" } }, { "chain_gun_fire": { "path": "sounds/chain_gun_fire.ogg" } }, { "grenade_fire": { "path": "sounds/grenade_fire.ogg" } }, { "pistol_fire": { "path": "sounds/pistol_fire.ogg" } }, { "rifle_fire": { "path": "sounds/rifle_fire.ogg" } }, { "snow1": { "path": "sounds/snow1.ogg" } }, { "snow2": { "path": "sounds/snow2.ogg" } }, { "snow3": { "path": "sounds/snow3.ogg" } }, { "shatter2": { "path": "sounds/shatter2.ogg" } }, { "shatter3": { "path": "sounds/shatter3.ogg" } }, { "strip1": { "path": "sounds/strip1.ogg" } }, { "strip2": { "path": "sounds/strip2.ogg" } }, { "strip3": { "path": "sounds/strip3.ogg" } }, { "strip4": { "path": "sounds/strip4.ogg" } }, { "barrel_open": { "path": "sounds/barrel_open.ogg" } }, { "shulker_box_open": { "path": "sounds/shulker_box_open.ogg" } }, { "monster": { "path": "sounds/monster.ogg" } }, { "attack1": { "path": "sounds/attack1.ogg" } }, { "attack2": { "path": "sounds/attack2.ogg" } }, { "fireball2": { "path": "sounds/fireball2.ogg" } }, { "laser": { "path": "sounds/laser.ogg" } }, { "wand1": { "path": "sounds/wand1.ogg" } }, { "wand2": { "path": "sounds/wand2.ogg" } }, { "wand3": { "path": "sounds/wand3.ogg" } }, { "gore1": { "path": "sounds/gore1.ogg" } }, { "gore2": { "path": "sounds/gore2.ogg" } }, { "gore3": { "path": "sounds/gore3.ogg" } }, { "thorns_hit1": { "path": "sounds/thorns_hit1.ogg" } }, { "thorns_hit2": { "path": "sounds/thorns_hit2.ogg" } }, { "thorns_hit3": { "path": "sounds/thorns_hit3.ogg" } }, { "thorns_hit4": { "path": "sounds/thorns_hit4.ogg" } }, { "enchant1": { "path": "sounds/enchant1.ogg" } }, { "enchant2": { "path": "sounds/enchant2.ogg" } }, { "enchant3": { "path": "sounds/enchant3.ogg" } }, { "travel": { "path": "sounds/travel.ogg" } }, { "trigger": { "path": "sounds/trigger.ogg" } } ] ================================================ FILE: effect_ai/Explosion.json ================================================ { "Explosion": { "pAI": "Explosion_AI" } } ================================================ FILE: effect_ai/GlowingFlow.json ================================================ { "GlowingFlow": { "ai": "GlowingFlow" } } ================================================ FILE: effect_ai/Gore.json ================================================ { "Gore": { "pAI": "Gore_AI" } } ================================================ FILE: effect_ai/Smoke.json ================================================ { "Smoke": {} } ================================================ FILE: effects/arrow_paticular.json ================================================ { "arrow_paticular": { "ai": "Smoke", "textureData": "chip.png", "width": 6, "height": 6, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 6, "gfxHeight": 6, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 72, "isForeground": false, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true } } ================================================ FILE: effects/chasting_word.json ================================================ { "chasting_word": { "ai": "Smoke", "textureData": "heal.png", "width": 12, "height": 12, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 12, "gfxHeight": 12, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 72, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/chip.json ================================================ { "chip": { "ai": "Smoke", "textureData": "chip.png", "width": 6, "height": 6, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 6, "gfxHeight": 6, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 160, "isForeground": true, "gravity": true, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true, "isLighting": true } } ================================================ FILE: effects/chip_fast.json ================================================ { "chip_fast": { "ai": "Smoke", "textureData": "chip.png", "width": 6, "height": 6, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 6, "gfxHeight": 6, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 64, "isForeground": true, "gravity": true, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true, "isLighting": true } } ================================================ FILE: effects/circle.json ================================================ { "circle": { "ai": "Smoke", "textureData": "circle.png", "width": 32, "height": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 32, "gfxHeight": 32, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 48, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "isLighting": true, "slowSpeed": true, "slowRotateSpeed": true, "lightColor": [ 26, 0, 0, 0 ] } } ================================================ FILE: effects/ender_flash.json ================================================ { "ender_flash": { "ai": "Smoke", "textureData": "ender_flash.png", "width": 6, "height": 6, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 6, "gfxHeight": 6, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 72, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true, "isLighting": true, "lightColor": [ 24, 0, 0, 8 ] } } ================================================ FILE: effects/exp_paticular.json ================================================ { "exp_paticular": { "ai": "Smoke", "textureData": "liquid_paticular.png", "width": 6, "height": 6, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 6, "gfxHeight": 6, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 160, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true } } ================================================ FILE: effects/explosion.json ================================================ { "explosion": { "ai": "Explosion", "textureData": "explosion.png", "width": 64, "height": 64, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 64, "gfxHeight": 64, "frameStyle": 0, "frameStyles": 1, "frames": 16, "frameSpeed": 2, "disappearTime": 32, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/fallen_flame_star.json ================================================ { "fallen_flame_star": { "ai": "Smoke", "textureData": "flame_star.png", "width": 6, "height": 6, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 6, "gfxHeight": 6, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 72, "isForeground": true, "gravity": true, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "isLighting": true, "slowSpeed": true, "slowRotateSpeed": true, "lightColor": [ 20, 0, 0, 0 ] } } ================================================ FILE: effects/fire.json ================================================ { "fire": { "ai": "Smoke", "textureData": "fire.png", "width": 16, "height": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 16, "gfxHeight": 16, "frameStyle": 0, "frameStyles": 1, "frames": 4, "frameSpeed": 8, "disappearTime": 120, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "isLighting": true, "slowSpeed": true, "slowRotateSpeed": true, "lightColor": [ 20, 6, 6, 0 ] } } ================================================ FILE: effects/fire_flame.json ================================================ { "fire_flame": { "ai": "Smoke", "textureData": "fire_flame.png", "width": 16, "height": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 16, "gfxHeight": 16, "frameStyle": 0, "frameStyles": 3, "frames": 1, "frameSpeed": 8, "disappearTime": 80, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": false, "slowSpeed": true, "slowRotateSpeed": true, "isLighting": true, "lightColor": [ 28, 12, 8, 0 ] } } ================================================ FILE: effects/fire_flame_long.json ================================================ { "fire_flame_long": { "ai": "Smoke", "textureData": "fire_flame.png", "width": 16, "height": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 16, "gfxHeight": 16, "frameStyle": 0, "frameStyles": 3, "frames": 1, "frameSpeed": 8, "disappearTime": 300, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": false, "slowSpeed": true, "slowRotateSpeed": true, "isLighting": true, "lightColor": [ 28, 12, 8, 0 ] } } ================================================ FILE: effects/fire_smoke.json ================================================ { "fire_smoke": { "ai": "Smoke", "textureData": "fire_smoke.png", "width": 16, "height": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 16, "gfxHeight": 16, "frameStyle": 0, "frameStyles": 3, "frames": 1, "frameSpeed": 8, "disappearTime": 80, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": false, "slowRotateSpeed": true, "isLighting": true } } ================================================ FILE: effects/flame_star.json ================================================ { "flame_star": { "ai": "Smoke", "textureData": "flame_star.png", "width": 6, "height": 6, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 6, "gfxHeight": 6, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 72, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "isLighting": true, "slowSpeed": true, "slowRotateSpeed": true, "lightColor": [ 20, 0, 0, 0 ] } } ================================================ FILE: effects/flash.json ================================================ { "flash": { "ai": "Smoke", "textureData": "flash.png", "width": 6, "height": 6, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 6, "gfxHeight": 6, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 32, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "isLighting": true, "slowSpeed": true, "slowRotateSpeed": true, "lightColor": [ 24, 0, 0, 0 ] } } ================================================ FILE: effects/flash2.json ================================================ { "flash2": { "ai": "Smoke", "textureData": "flash2.png", "width": 14, "height": 14, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 14, "gfxHeight": 14, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 32, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "isLighting": true, "slowSpeed": true, "slowRotateSpeed": true, "lightColor": [ 24, 0, 0, 0 ] } } ================================================ FILE: effects/flow_particular.json ================================================ { "flow_particular": { "ai": "GlowingFlow", "textureData": "flow_particular.png", "width": 8, "height": 8, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 8, "gfxHeight": 8, "frameStyle": 0, "frameStyles": 1, "frames": 4, "frameSpeed": 8, "disappearTime": 180, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false, "isLighting": true, "lightColor": [ 28, 0, 0, 0 ] } } ================================================ FILE: effects/gores/gore_angry_skeleton.json ================================================ { "gore_angry_skeleton": { "ai": "Gore", "textureData": "angry_skeleton.png", "width": 20, "height": 20, "gfxOffsetX": -2, "gfxOffsetY": 0, "gfxWidth": 24, "gfxHeight": 20, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_arrow_zombie.json ================================================ { "gore_arrow_zombie": { "ai": "Gore", "textureData": "arrow_zombie.png", "width": 24, "height": 24, "gfxOffsetX": -12, "gfxOffsetY": -1, "gfxWidth": 48, "gfxHeight": 26, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_bald_zombie.json ================================================ { "gore_bald_zombie": { "ai": "Gore", "textureData": "bald_zombie.png", "width": 20, "height": 20, "gfxOffsetX": -1, "gfxOffsetY": -2, "gfxWidth": 22, "gfxHeight": 24, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_bat.json ================================================ { "gore_bat": { "ai": "Gore", "textureData": "bat.png", "width": 20, "height": 20, "gfxOffsetX": -3, "gfxOffsetY": -2, "gfxWidth": 26, "gfxHeight": 24, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_black_rabbit.json ================================================ { "gore_black_rabbit": { "ai": "Gore", "textureData": "black_rabbit.png", "width": 16, "height": 16, "gfxOffsetX": 0, "gfxOffsetY": -1, "gfxWidth": 16, "gfxHeight": 18, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_black_skeleton.json ================================================ { "gore_black_skeleton": { "ai": "Gore", "textureData": "black_skeleton.png", "width": 20, "height": 20, "gfxOffsetX": -2, "gfxOffsetY": 0, "gfxWidth": 24, "gfxHeight": 20, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_blood_bat.json ================================================ { "gore_blood_bat": { "ai": "Gore", "textureData": "blood_bat.png", "width": 20, "height": 20, "gfxOffsetX": -1, "gfxOffsetY": -1, "gfxWidth": 22, "gfxHeight": 22, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_blood_eye.json ================================================ { "gore_blood_eye": { "ai": "Gore", "textureData": "blood_eye.png", "width": 20, "height": 20, "gfxOffsetX": -10, "gfxOffsetY": -10, "gfxWidth": 40, "gfxHeight": 40, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_blood_skeleton.json ================================================ { "gore_blood_skeleton": { "ai": "Gore", "textureData": "blood_skeleton.png", "width": 20, "height": 20, "gfxOffsetX": -2, "gfxOffsetY": 0, "gfxWidth": 24, "gfxHeight": 20, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_bone_lee.json ================================================ { "gore_bone_lee": { "ai": "Gore", "textureData" : "bone_lee.png", "width" : 20, "height" : 20, "gfxOffsetX" : -4, "gfxOffsetY" : 0, "gfxWidth" : 28, "gfxHeight" : 20, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_bone_officer.json ================================================ { "gore_bone_officer": { "ai": "Gore", "textureData" : "bone_officer.png", "width" : 20, "height" : 20, "gfxOffsetX" : -6, "gfxOffsetY" : -3, "gfxWidth" : 32, "gfxHeight" : 26, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_bone_sniper.json ================================================ { "gore_bone_sniper": { "ai": "Gore", "textureData" : "bone_sniper.png", "width" : 20, "height" : 20, "gfxOffsetX" : -5, "gfxOffsetY" : -3, "gfxWidth" : 30, "gfxHeight" : 26, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_boney_skeleton.json ================================================ { "gore_boney_skeleton": { "ai": "Gore", "textureData": "boney_skeleton.png", "width": 20, "height": 20, "gfxOffsetX": -8, "gfxOffsetY": -4, "gfxWidth": 36, "gfxHeight": 28, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_brown_mushroom_cow.json ================================================ { "gore_brown_mushroom_cow": { "ai": "Gore", "textureData": "brown_mushroom_cow.png", "width": 32, "height": 32, "gfxOffsetX": -4, "gfxOffsetY": -4, "gfxWidth": 40, "gfxHeight": 40, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_brown_rabbit.json ================================================ { "gore_brown_rabbit": { "ai": "Gore", "textureData": "brown_rabbit.png", "width": 16, "height": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 16, "gfxHeight": 16, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_chicken.json ================================================ { "gore_chicken": { "ai": "Gore", "textureData": "chicken.png", "width": 14, "height": 14, "gfxOffsetX": -2, "gfxOffsetY": 0, "gfxWidth": 18, "gfxHeight": 14, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_cow.json ================================================ { "gore_cow": { "ai": "Gore", "textureData": "cow.png", "width": 24, "height": 24, "gfxOffsetX": -8, "gfxOffsetY": -3, "gfxWidth": 40, "gfxHeight": 30, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_creeper.json ================================================ { "gore_creeper": { "ai": "Gore", "textureData": "creeper.png", "width": 20, "height": 20, "gfxOffsetX": -2, "gfxOffsetY": 0, "gfxWidth": 24, "gfxHeight": 20, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_cursed_skull.json ================================================ { "gore_cursed_skull": { "ai": "Gore", "textureData" : "cursed_skull.png", "width" : 20, "height" : 20, "gfxOffsetX" : -3, "gfxOffsetY" : -2, "gfxWidth" : 26, "gfxHeight" : 24, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_dark_mage.json ================================================ { "gore_dark_mage": { "ai": "Gore", "textureData" : "dark_mage.png", "width" : 20, "height" : 20, "gfxOffsetX" : -2, "gfxOffsetY" : -1, "gfxWidth" : 24, "gfxHeight" : 22, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_dead_mage.json ================================================ { "gore_dead_mage": { "ai": "Gore", "textureData" : "dead_mage.png", "width" : 20, "height" : 20, "gfxOffsetX" : -6, "gfxOffsetY" : -7, "gfxWidth" : 32, "gfxHeight" : 34, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_doge_zombie.json ================================================ { "gore_doge_zombie": { "ai": "Gore", "textureData": "doge_zombie.png", "width": 20, "height": 20, "gfxOffsetX": -4, "gfxOffsetY": -1, "gfxWidth": 28, "gfxHeight": 22, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_dolphin.json ================================================ { "gore_dolphin": { "ai": "Gore", "textureData": "dolphin.png", "width": 32, "height": 32, "gfxOffsetX": -8, "gfxOffsetY": -3, "gfxWidth": 48, "gfxHeight": 38, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_drowned.json ================================================ { "gore_drowned": { "ai": "Gore", "textureData": "drowned.png", "width": 20, "height": 20, "gfxOffsetX": -4, "gfxOffsetY": -3, "gfxWidth": 28, "gfxHeight": 26, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_dungeon_creeper.json ================================================ { "gore_dungeon_creeper": { "ai": "Gore", "textureData" : "dungeon_creeper.png", "width" : 20, "height" : 20, "gfxOffsetX" : -6, "gfxOffsetY" : -12, "gfxWidth" : 32, "gfxHeight" : 44, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_dungeon_knight.json ================================================ { "gore_dungeon_knight": { "ai": "Gore", "textureData" : "dungeon_knight.png", "width" : 20, "height" : 20, "gfxOffsetX" : -6, "gfxOffsetY" : -6, "gfxWidth" : 32, "gfxHeight" : 32, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_eagle.json ================================================ { "gore_eagle": { "ai": "Gore", "textureData": "eagle.png", "width": 16, "height": 16, "gfxOffsetX": -4, "gfxOffsetY": -3, "gfxWidth": 24, "gfxHeight": 22, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_enderman.json ================================================ { "gore_enderman": { "ai": "Gore", "textureData": "enderman.png", "width": 20, "height": 20, "gfxOffsetX": -3, "gfxOffsetY": -4, "gfxWidth": 26, "gfxHeight": 28, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_evil.json ================================================ { "gore_evil": { "ai": "Gore", "textureData" : "evil.png", "width" : 20, "height" : 20, "gfxOffsetX" : 0, "gfxOffsetY" : -1, "gfxWidth" : 20, "gfxHeight" : 22, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_evoker.json ================================================ { "gore_evoker": { "ai": "Gore", "textureData": "evoker.png", "width": 30, "height": 30, "gfxOffsetX": -1, "gfxOffsetY": 0, "gfxWidth": 32, "gfxHeight": 30, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_eye_guard.json ================================================ { "gore_eye_guard": { "ai": "Gore", "textureData" : "eye_guard.png", "width" : 20, "height" : 20, "gfxOffsetX" : -14, "gfxOffsetY" : -38, "gfxWidth" : 48, "gfxHeight" : 96, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_eye_guard_laser.json ================================================ { "gore_eye_guard_laser": { "ai": "Gore", "textureData" : "eye_guard_laser.png", "width" : 20, "height" : 20, "gfxOffsetX" : -14, "gfxOffsetY" : -38, "gfxWidth" : 48, "gfxHeight" : 96, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_flower_creeper.json ================================================ { "gore_flower_creeper": { "ai": "Gore", "textureData": "flower_creeper.png", "width": 8, "height": 8, "gfxOffsetX": -10, "gfxOffsetY": -5, "gfxWidth": 28, "gfxHeight": 18, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_fly_eye.json ================================================ { "gore_fly_eye": { "ai": "Gore", "textureData" : "fly_eye.png", "width" : 20, "height" : 20, "gfxOffsetX" : -2, "gfxOffsetY" : -4, "gfxWidth" : 24, "gfxHeight" : 28, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_fly_mouth.json ================================================ { "gore_fly_mouth": { "ai": "Gore", "textureData" : "fly_mouth.png", "width" : 20, "height" : 20, "gfxOffsetX" : -2, "gfxOffsetY" : -4, "gfxWidth" : 24, "gfxHeight" : 28, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_fly_skeleton.json ================================================ { "gore_fly_skeleton": { "ai": "Gore", "textureData" : "fly_skeleton.png", "width" : 20, "height" : 20, "gfxOffsetX" : -6, "gfxOffsetY" : -7, "gfxWidth" : 32, "gfxHeight" : 34, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_giant_cursed_skull.json ================================================ { "gore_giant_cursed_skull": { "ai": "Gore", "textureData" : "giant_cursed_skull.png", "width" : 20, "height" : 20, "gfxOffsetX" : -12, "gfxOffsetY" : -14, "gfxWidth" : 44, "gfxHeight" : 48, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_grass_walker.json ================================================ { "gore_grass_walker": { "ai": "Gore", "textureData" : "grass_walker.png", "width" : 20, "height" : 20, "gfxOffsetX" : -5, "gfxOffsetY" : -6, "gfxWidth" : 30, "gfxHeight" : 32, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_grim_reaper.json ================================================ { "gore_grim_reaper": { "ai": "Gore", "textureData" : "grim_reaper.png", "width" : 20, "height" : 20, "gfxOffsetX" : -2, "gfxOffsetY" : -1, "gfxWidth" : 24, "gfxHeight" : 22, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_husk.json ================================================ { "gore_husk": { "ai": "Gore", "textureData": "husk.png", "width": 20, "height": 20, "gfxOffsetX": -4, "gfxOffsetY": -3, "gfxWidth": 28, "gfxHeight": 26, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_ice_sprite_girl.json ================================================ { "gore_ice_sprite_girl": { "ai": "Gore", "textureData" : "ice_sprite_girl.png", "width" : 20, "height" : 20, "gfxOffsetX" : -6, "gfxOffsetY" : -5, "gfxWidth" : 32, "gfxHeight" : 30, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_iron_zombie.json ================================================ { "gore_iron_zombie": { "ai": "Gore", "textureData": "iron_zombie.png", "width": 20, "height": 20, "gfxOffsetX": -3, "gfxOffsetY": -1, "gfxWidth": 26, "gfxHeight": 22, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_jungle_bat.json ================================================ { "gore_jungle_bat": { "ai": "Gore", "textureData": "jungle_bat.png", "width": 20, "height": 20, "gfxOffsetX": -1, "gfxOffsetY": -1, "gfxWidth": 22, "gfxHeight": 22, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_large_bat.json ================================================ { "gore_large_bat": { "ai": "Gore", "textureData" : "large_bat.png", "width" : 20, "height" : 20, "gfxOffsetX" : -5, "gfxOffsetY" : -5, "gfxWidth" : 30, "gfxHeight" : 30, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_large_jungle_bat.json ================================================ { "gore_large_jungle_bat": { "ai": "Gore", "textureData": "large_jungle_bat.png", "width": 20, "height": 20, "gfxOffsetX": -4, "gfxOffsetY": -6, "gfxWidth": 28, "gfxHeight": 32, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_large_spider.json ================================================ { "gore_large_spider": { "ai": "Gore", "textureData" : "large_spider.png", "width" : 20, "height" : 20, "gfxOffsetX" : -2, "gfxOffsetY" : 0, "gfxWidth" : 24, "gfxHeight" : 20, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_lava_snake_body.json ================================================ { "gore_lava_snake_body": { "ai": "Gore", "textureData" : "lava_snake_body.png", "width" : 20, "height" : 20, "gfxOffsetX" : -12, "gfxOffsetY" : -8, "gfxWidth" : 44, "gfxHeight" : 36, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_lava_snake_head.json ================================================ { "gore_lava_snake_head": { "ai": "Gore", "textureData" : "lava_snake_head.png", "width" : 20, "height" : 20, "gfxOffsetX" : -15, "gfxOffsetY" : -10, "gfxWidth" : 50, "gfxHeight" : 40, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_lava_snake_tail.json ================================================ { "gore_lava_snake_tail": { "ai": "Gore", "textureData" : "lava_snake_tail.png", "width" : 20, "height" : 20, "gfxOffsetX" : -17, "gfxOffsetY" : -10, "gfxWidth" : 54, "gfxHeight" : 40, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_mad_skeleton.json ================================================ { "gore_mad_skeleton": { "ai": "Gore", "textureData" : "mad_skeleton.png", "width" : 20, "height" : 20, "gfxOffsetX" : -2, "gfxOffsetY" : 0, "gfxWidth" : 24, "gfxHeight" : 20, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_mad_skeleton_armed.json ================================================ { "gore_mad_skeleton_armed": { "ai": "Gore", "textureData" : "mad_skeleton_armed.png", "width" : 20, "height" : 20, "gfxOffsetX" : -3, "gfxOffsetY" : -2, "gfxWidth" : 26, "gfxHeight" : 24, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_mad_skeleton_tall.json ================================================ { "gore_mad_skeleton_tall": { "ai": "Gore", "textureData" : "mad_skeleton_tall.png", "width" : 20, "height" : 20, "gfxOffsetX" : -4, "gfxOffsetY" : -2, "gfxWidth" : 28, "gfxHeight" : 24, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_mad_skeleton_tall_armed.json ================================================ { "gore_mad_skeleton_tall_armed": { "ai": "Gore", "textureData" : "mad_skeleton_tall_armed.png", "width" : 20, "height" : 20, "gfxOffsetX" : -3, "gfxOffsetY" : -2, "gfxWidth" : 26, "gfxHeight" : 24, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_mad_skeleton_tall_helmet_armed.json ================================================ { "gore_mad_skeleton_tall_helmet_armed": { "ai": "Gore", "textureData" : "mad_skeleton_tall_helmet_armed.png", "width" : 20, "height" : 20, "gfxOffsetX" : -4, "gfxOffsetY" : -7, "gfxWidth" : 28, "gfxHeight" : 34, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_magma_birdo.json ================================================ { "gore_magma_birdo": { "ai": "Gore", "textureData": "magma_birdo.png", "width": 20, "height": 20, "gfxOffsetX": -5, "gfxOffsetY": -3, "gfxWidth": 30, "gfxHeight": 26, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_man_eater.json ================================================ { "gore_man_eater": { "ai": "Gore", "textureData": "man_eater.png", "width": 20, "height": 20, "gfxOffsetX": -6, "gfxOffsetY": -16, "gfxWidth": 32, "gfxHeight": 52, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_mummy.json ================================================ { "gore_mummy": { "ai": "Gore", "textureData": "mummy.png", "width": 20, "height": 20, "gfxOffsetX": -1, "gfxOffsetY": -2, "gfxWidth": 22, "gfxHeight": 24, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_paimon.json ================================================ { "gore_paimon": { "ai": "Gore", "textureData" : "paimon.png", "width" : 20, "height" : 20, "gfxOffsetX" : -9, "gfxOffsetY" : -4, "gfxWidth" : 38, "gfxHeight" : 28, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_phantom.json ================================================ { "gore_phantom": { "ai": "Gore", "textureData": "phantom.png", "width": 20, "height": 20, "gfxOffsetX": -6, "gfxOffsetY": -4, "gfxWidth": 32, "gfxHeight": 28, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_pig.json ================================================ { "gore_pig": { "ai": "Gore", "textureData": "pig.png", "width": 32, "height": 32, "gfxOffsetX": -4, "gfxOffsetY": -3, "gfxWidth": 40, "gfxHeight": 38, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_ragged_mage.json ================================================ { "gore_ragged_mage": { "ai": "Gore", "textureData" : "ragged_mage.png", "width" : 20, "height" : 20, "gfxOffsetX" : -2, "gfxOffsetY" : 0, "gfxWidth" : 24, "gfxHeight" : 20, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_red_mage.json ================================================ { "gore_red_mage": { "ai": "Gore", "textureData" : "red_mage.png", "width" : 20, "height" : 20, "gfxOffsetX" : -6, "gfxOffsetY" : -5, "gfxWidth" : 32, "gfxHeight" : 30, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_red_mushroom_cow.json ================================================ { "gore_red_mushroom_cow": { "ai": "Gore", "textureData": "red_mushroom_cow.png", "width": 32, "height": 32, "gfxOffsetX": -4, "gfxOffsetY": -4, "gfxWidth": 40, "gfxHeight": 40, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_red_phantom.json ================================================ { "gore_red_phantom": { "ai": "Gore", "textureData" : "red_phantom.png", "width" : 20, "height" : 20, "gfxOffsetX" : 1, "gfxOffsetY" : 2, "gfxWidth" : 18, "gfxHeight" : 16, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_rock_man.json ================================================ { "gore_rock_man": { "ai": "Gore", "textureData" : "rock_man.png", "width" : 20, "height" : 20, "gfxOffsetX" : -3, "gfxOffsetY" : -1, "gfxWidth" : 26, "gfxHeight" : 22, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_sheep.json ================================================ { "gore_sheep": { "ai": "Gore", "textureData": "sheep.png", "width": 20, "height": 20, "gfxOffsetX": -7, "gfxOffsetY": -6, "gfxWidth": 34, "gfxHeight": 32, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_shulker.json ================================================ { "gore_shulker": { "ai": "Gore", "textureData": "shulker.png", "width": 16, "height": 16, "gfxOffsetX": -8, "gfxOffsetY": -1, "gfxWidth": 32, "gfxHeight": 18, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_skeleton_assaulter.json ================================================ { "gore_skeleton_assaulter": { "ai": "Gore", "textureData" : "skeleton_assaulter.png", "width" : 20, "height" : 20, "gfxOffsetX" : -2, "gfxOffsetY" : 0, "gfxWidth" : 24, "gfxHeight" : 20, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_skeleton_blue_armed.json ================================================ { "gore_skeleton_blue_armed": { "ai": "Gore", "textureData" : "skeleton_blue_armed.png", "width" : 20, "height" : 20, "gfxOffsetX" : -7, "gfxOffsetY" : -4, "gfxWidth" : 34, "gfxHeight" : 28, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_skeleton_blue_armed_masked.json ================================================ { "gore_skeleton_blue_armed_masked": { "ai": "Gore", "textureData" : "skeleton_blue_armed_masked.png", "width" : 20, "height" : 20, "gfxOffsetX" : -7, "gfxOffsetY" : -4, "gfxWidth" : 34, "gfxHeight" : 28, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_skeleton_blue_knight.json ================================================ { "gore_skeleton_blue_knight": { "ai": "Gore", "textureData" : "skeleton_blue_knight.png", "width" : 20, "height" : 20, "gfxOffsetX" : -6, "gfxOffsetY" : -5, "gfxWidth" : 32, "gfxHeight" : 30, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_skeleton_fire_armed.json ================================================ { "gore_skeleton_fire_armed": { "ai": "Gore", "textureData" : "skeleton_fire_armed.png", "width" : 20, "height" : 20, "gfxOffsetX" : -7, "gfxOffsetY" : -4, "gfxWidth" : 34, "gfxHeight" : 28, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_skeleton_fire_armed_swordsman.json ================================================ { "gore_skeleton_fire_armed_swordsman": { "ai": "Gore", "textureData" : "skeleton_fire_armed_swordsman.png", "width" : 20, "height" : 20, "gfxOffsetX" : -3, "gfxOffsetY" : -4, "gfxWidth" : 26, "gfxHeight" : 28, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_skeleton_guard.json ================================================ { "gore_skeleton_guard": { "ai": "Gore", "textureData" : "skeleton_guard.png", "width" : 20, "height" : 20, "gfxOffsetX" : -6, "gfxOffsetY" : -3, "gfxWidth" : 32, "gfxHeight" : 26, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_skeleton_kid.json ================================================ { "gore_skeleton_kid": { "ai": "Gore", "textureData" : "skeleton_kid.png", "width" : 20, "height" : 20, "gfxOffsetX" : -3, "gfxOffsetY" : 1, "gfxWidth" : 26, "gfxHeight" : 18, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_skull.json ================================================ { "gore_skull": { "ai": "Gore", "textureData": "skull.png", "width": 20, "height": 20, "gfxOffsetX": -2, "gfxOffsetY": 0, "gfxWidth": 24, "gfxHeight": 20, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_small_hell_eater.json ================================================ { "gore_small_hell_eater": { "ai": "Gore", "textureData": "small_hell_eater.png", "width": 16, "height": 16, "gfxOffsetX": -8, "gfxOffsetY": -8, "gfxWidth": 32, "gfxHeight": 32, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_snow_guner.json ================================================ { "gore_snow_guner": { "ai": "Gore", "textureData" : "snow_guner.png", "width" : 20, "height" : 20, "gfxOffsetX" : -4, "gfxOffsetY" : -4, "gfxWidth" : 28, "gfxHeight" : 28, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_spider.json ================================================ { "gore_spider": { "ai": "Gore", "textureData": "spider.png", "width": 20, "height": 20, "gfxOffsetX": -3, "gfxOffsetY": 0, "gfxWidth": 26, "gfxHeight": 20, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_squid.json ================================================ { "gore_squid": { "ai": "Gore", "textureData": "squid.png", "width": 20, "height": 20, "gfxOffsetX": -1, "gfxOffsetY": -1, "gfxWidth": 22, "gfxHeight": 22, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_tainted_creeper.json ================================================ { "gore_tainted_creeper": { "ai": "Gore", "textureData": "tainted_creeper.png", "width": 20, "height": 20, "gfxOffsetX": -6, "gfxOffsetY": -6, "gfxWidth": 32, "gfxHeight": 32, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_tainted_skeleton.json ================================================ { "gore_tainted_skeleton": { "ai": "Gore", "textureData": "tainted_skeleton.png", "width": 20, "height": 20, "gfxOffsetX": -2, "gfxOffsetY": 0, "gfxWidth": 24, "gfxHeight": 20, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_turtle.json ================================================ { "gore_turtle": { "ai": "Gore", "textureData": "turtle.png", "width": 16, "height": 16, "gfxOffsetX": -9, "gfxOffsetY": -5, "gfxWidth": 34, "gfxHeight": 26, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_undead_miner.json ================================================ { "gore_undead_miner": { "ai": "Gore", "textureData" : "undead_miner.png", "width" : 20, "height" : 20, "gfxOffsetX" : -3, "gfxOffsetY" : -1, "gfxWidth" : 26, "gfxHeight" : 22, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_vampire_miner.json ================================================ { "gore_vampire_miner": { "ai": "Gore", "textureData" : "vampire_miner.png", "width" : 20, "height" : 20, "gfxOffsetX" : -4, "gfxOffsetY" : -3, "gfxWidth" : 28, "gfxHeight" : 26, "frameStyle" : 0, "frameStyles" : 1, "frames" : 1, "frameSpeed" : 8, "disappearTime" : 600, "isForeground" : false, "gravity" : true, "collisionWithBlocks" : true, "fixByBlocks" : true, "fadeScale" : false, "fadeAlpha" : false, "slowSpeed" : false, "slowRotateSpeed" : false } } ================================================ FILE: effects/gores/gore_villager_zombie.json ================================================ { "gore_villager_zombie": { "ai": "Gore", "textureData": "villager_zombie.png", "width": 20, "height": 20, "gfxOffsetX": -3, "gfxOffsetY": -3, "gfxWidth": 26, "gfxHeight": 26, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_waste_mummy.json ================================================ { "gore_waste_mummy": { "ai": "Gore", "textureData": "waste_mummy.png", "width": 20, "height": 20, "gfxOffsetX": -7, "gfxOffsetY": -5, "gfxWidth": 34, "gfxHeight": 30, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_white_rabbit.json ================================================ { "gore_white_rabbit": { "ai": "Gore", "textureData": "white_rabbit.png", "width": 16, "height": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 16, "gfxHeight": 16, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_wither_skeleton.json ================================================ { "gore_wither_skeleton": { "ai": "Gore", "textureData": "wither_skeleton.png", "width": 20, "height": 20, "gfxOffsetX": -4, "gfxOffsetY": -2, "gfxWidth": 28, "gfxHeight": 24, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_worm_body.json ================================================ { "gore_worm_body": { "ai": "Gore", "textureData": "worm_body.png", "width": 30, "height": 30, "gfxOffsetX": -8, "gfxOffsetY": -11, "gfxWidth": 46, "gfxHeight": 52, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 300, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_worm_head.json ================================================ { "gore_worm_head": { "ai": "Gore", "textureData": "worm_head.png", "width": 30, "height": 30, "gfxOffsetX": -24, "gfxOffsetY": -11, "gfxWidth": 78, "gfxHeight": 52, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 300, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_worm_tail.json ================================================ { "gore_worm_tail": { "ai": "Gore", "textureData": "worm_tail.png", "width": 30, "height": 30, "gfxOffsetX": -15, "gfxOffsetY": -17, "gfxWidth": 60, "gfxHeight": 64, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 300, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_yellow_rabbit.json ================================================ { "gore_yellow_rabbit": { "ai": "Gore", "textureData": "yellow_rabbit.png", "width": 16, "height": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 16, "gfxHeight": 16, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_zombie.json ================================================ { "gore_zombie": { "ai": "Gore", "textureData": "zombie.png", "width": 20, "height": 20, "gfxOffsetX": -6, "gfxOffsetY": -3, "gfxWidth": 32, "gfxHeight": 26, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/gores/gore_zombie_pigman.json ================================================ { "gore_zombie_pigman": { "ai": "Gore", "textureData": "zombie_pigman.png", "width": 20, "height": 20, "gfxOffsetX": -4, "gfxOffsetY": -3, "gfxWidth": 28, "gfxHeight": 26, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 600, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/heal.json ================================================ { "heal": { "ai": "Smoke", "textureData": "heal.png", "width": 12, "height": 12, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 12, "gfxHeight": 12, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 72, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": false, "slowSpeed": true, "slowRotateSpeed": true } } ================================================ FILE: effects/laser_flash.json ================================================ { "laser_flash": { "ai": "Smoke", "textureData": "laser_flash.png", "width": 8, "height": 8, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 8, "gfxHeight": 8, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 72, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true, "isLighting": true, "lightColor": [ 16, 0, 0, 0 ] } } ================================================ FILE: effects/liquid_paticular.json ================================================ { "liquid_paticular": { "ai": "Smoke", "textureData": "liquid_paticular.png", "width": 8, "height": 8, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 8, "gfxHeight": 8, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 160, "isForeground": true, "gravity": true, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true } } ================================================ FILE: effects/poison.json ================================================ { "poison": { "ai": "Smoke", "textureData": "poison.png", "width": 20, "height": 20, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 20, "gfxHeight": 20, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 72, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true } } ================================================ FILE: effects/pot_break.json ================================================ { "pot_break": { "ai": "Gore", "textureData": "pot_break.png", "width": 16, "height": 16, "gfxOffsetX": -8, "gfxOffsetY": -8, "gfxWidth": 32, "gfxHeight": 32, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 1000, "isForeground": false, "gravity": true, "collisionWithBlocks": true, "fixByBlocks": true, "fadeScale": false, "fadeAlpha": false, "slowSpeed": false, "slowRotateSpeed": false } } ================================================ FILE: effects/redstone_smoke.json ================================================ { "redstone_smoke": { "ai": "Smoke", "textureData": "redstone_smoke.png", "width": 16, "height": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 16, "gfxHeight": 16, "frameStyle": 0, "frameStyles": 3, "frames": 1, "frameSpeed": 8, "disappearTime": 80, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true } } ================================================ FILE: effects/smoke.json ================================================ { "smoke": { "ai": "Smoke", "textureData": "smoke.png", "width": 32, "height": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 32, "gfxHeight": 32, "frameStyle": 0, "frameStyles": 3, "frames": 1, "frameSpeed": 8, "disappearTime": 120, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true } } ================================================ FILE: effects/star.json ================================================ { "star": { "ai": "Smoke", "textureData": "star.png", "width": 16, "height": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 16, "gfxHeight": 16, "frameStyle": 0, "frameStyles": 1, "frames": 1, "frameSpeed": 8, "disappearTime": 72, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": false, "isLighting": true, "slowSpeed": true, "slowRotateSpeed": true, "lightColor": [ 24, 0, 0, 0 ] } } ================================================ FILE: effects/white_smoke.json ================================================ { "white_smoke": { "ai": "Smoke", "textureData": "white_smoke.png", "width": 32, "height": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "gfxWidth": 32, "gfxHeight": 32, "frameStyle": 0, "frameStyles": 3, "frames": 1, "frameSpeed": 8, "disappearTime": 60, "isForeground": true, "gravity": false, "collisionWithBlocks": false, "fixByBlocks": false, "fadeScale": true, "fadeAlpha": true, "slowSpeed": true, "slowRotateSpeed": true } } ================================================ FILE: enchantments/BaseEnchantmentProxy.lua ================================================ ---@class TC.BaseEnchantmentProxy local BaseEnchantmentProxy = class("BaseEnchantmentProxy") ---OnHeld ---@param level int ---@param player Player ---@param itemStack ItemStack function BaseEnchantmentProxy.OnHeld(level, player, itemStack) end ---OnUpdateSecond ---@param level int ---@param player Player ---@param itemStack ItemStack function BaseEnchantmentProxy.OnUpdateSecond(level, player, itemStack) end ---OnEquipped ---@param equipmentIndex int ---@param level int ---@param player Player ---@param itemStack ItemStack function BaseEnchantmentProxy.OnEquipped(equipmentIndex, level, player, itemStack) end ---OnEquippedHitByNpc ---@param equipmentIndex int ---@param level int ---@param player Player ---@param itemStack ItemStack ---@param npc Npc function BaseEnchantmentProxy.OnEquippedHitByNpc(equipmentIndex, level, player, itemStack, npc) end ---OnEquippedHitByProjectile ---@param equipmentIndex int ---@param level int ---@param player Player ---@param itemStack ItemStack ---@param projectile Projectile function BaseEnchantmentProxy.OnEquippedHitByProjectile(equipmentIndex, level, player, itemStack, projectile) end return BaseEnchantmentProxy ================================================ FILE: enchantments/EnchantmentAquaAffinity.lua ================================================ ---@class TC.EnchantmentAquaAffinity:TC.BaseEnchantmentProxy local EnchantmentAquaAffinity = class("EnchantmentAquaAffinity") function EnchantmentAquaAffinity.OnEquipped(equipmentIndex, level, player, _) if player.inLiquid then player.digSpeedRate = player.digSpeedRate + level * 0.1 end end return EnchantmentAquaAffinity ================================================ FILE: enchantments/EnchantmentBlastProtection.lua ================================================ ---@class TC.EnchantmentBlastProtection:TC.BaseEnchantmentProxy local EnchantmentBlastProtection = class("EnchantmentBlastProtection") function EnchantmentBlastProtection.OnEquipped(equipmentIndex, level, player, _) player.baseDefense.blastDefense = player.baseDefense.blastDefense + level end return EnchantmentBlastProtection ================================================ FILE: enchantments/EnchantmentDepthStrider.lua ================================================ ---@class TC.EnchantmentDepthStrider:TC.BaseEnchantmentProxy local EnchantmentDepthStrider = class("EnchantmentDepthStrider") function EnchantmentDepthStrider.OnEquipped(equipmentIndex, level, player, _) if player.inLiquid then player.speedRate = player.speedRate + level * 0.2 end end return EnchantmentDepthStrider ================================================ FILE: enchantments/EnchantmentFeatherFalling.lua ================================================ ---@class TC.EnchantmentFeatherFalling:TC.BaseEnchantmentProxy local EnchantmentFeatherFalling = class("EnchantmentFeatherFalling") function EnchantmentFeatherFalling.OnEquipped(equipmentIndex, level, player, _) player.baseDefense.fallDefense = player.baseDefense.fallDefense + level end return EnchantmentFeatherFalling ================================================ FILE: enchantments/EnchantmentFireProtection.lua ================================================ ---@class TC.EnchantmentFireProtection:TC.BaseEnchantmentProxy local EnchantmentFireProtection = class("EnchantmentFireProtection") function EnchantmentFireProtection.OnEquipped(equipmentIndex, level, player, _) player.baseDefense.flameDefense = player.baseDefense.flameDefense + level end return EnchantmentFireProtection ================================================ FILE: enchantments/EnchantmentFrostWalker.lua ================================================ ---@class TC.EnchantmentFrostWalker:TC.BaseEnchantmentProxy local EnchantmentFrostWalker = class("EnchantmentFrostWalker") function EnchantmentFrostWalker.OnHeld(level, player, _) local waterID = Reg.LiquidID("water") local xi1 = Utils.Cell(player.x) - 2 local xi2 = Utils.Cell(player.rightX) + 2 local yi1 = Utils.Cell(player.bottomY) local yi2 = yi1 + 1 if MapUtils.IsAreaValid(xi1, yi1 - 1, xi2 - xi1, yi2 - yi1 + 1) then for xi = xi1, xi2 do for yi = yi1, yi2 do if not MapUtils.HasFront(xi, yi) then local liquidID, amount = MapUtils.GetLiquidIDAmount(xi, yi) if liquidID == waterID then if not MapUtils.IsSolid(xi, yi - 1) then MapUtils.RemoveFront(xi, yi) MapUtils.SetFront(xi, yi, Reg.BlockID("ice_thin")) MapUtils.SetFrontTag(xi, yi, amount) for i = 1, 4 do EffectUtils.SendFromServer(Reg.EffectID("heal"), xi * 16 + 8, yi * 16 + 8, Utils.RandSym(1.0), Utils.RandSym(1.0), Utils.RandSym(0.25)) end end end end end end end end return EnchantmentFrostWalker ================================================ FILE: enchantments/EnchantmentKnockBack.lua ================================================ ---@class TC.EnchantmentKnockBack:TC.BaseEnchantmentProxy local EnchantmentKnockBack = class("EnchantmentKnockBack") function EnchantmentKnockBack.OnHeld(level, player, _) player.baseAttack.knockBack = player.baseAttack.knockBack + level end return EnchantmentKnockBack ================================================ FILE: enchantments/EnchantmentPhyton.lua ================================================ ---@class TC.EnchantmentPhyton:TC.BaseEnchantmentProxy local EnchantmentPhyton = class("EnchantmentProtection") function EnchantmentPhyton.OnUpdateSecond(level, player, itemStack) itemStack:AddDurable(level * 2) end return EnchantmentPhyton ================================================ FILE: enchantments/EnchantmentProjectileProtection.lua ================================================ ---@class TC.EnchantmentProjectileProtection:TC.BaseEnchantmentProxy local EnchantmentProjectileProtection = class("EnchantmentProjectileProtection") function EnchantmentProjectileProtection.OnEquipped(equipmentIndex, level, player, _) player.baseDefense.projectileDefense = player.baseDefense.projectileDefense + level end return EnchantmentProjectileProtection ================================================ FILE: enchantments/EnchantmentProtection.lua ================================================ ---@class TC.EnchantmentProtection:TC.BaseEnchantmentProxy local EnchantmentProtection = class("EnchantmentProtection") function EnchantmentProtection.OnEquipped(equipmentIndex, level, player, _) player.baseDefense.defense = player.baseDefense.defense + level end return EnchantmentProtection ================================================ FILE: enchantments/EnchantmentProxies.lua ================================================ ---@class TC.EnchantmentProxies local EnchantmentProxies = class("EnchantmentProxies") local s_instance ---@return TC.EnchantmentProxies function EnchantmentProxies.getInstance() if s_instance == nil then s_instance = EnchantmentProxies.new() end return s_instance end function EnchantmentProxies:__init() ---@type TC.BaseEnchantmentProxy[] self._proxies = {} end ---OnHeld ---@param itemStack ItemStack ---@param player Player function EnchantmentProxies:OnHeld(itemStack, player) if not itemStack:HasEnchantment() then return end for index = 0, itemStack.enchantmentCount - 1 do local enchantment = itemStack:GetEnchantmentByIndex(index) local proxy = self._proxies[enchantment.id] if proxy and proxy.OnHeld ~= nil then proxy.OnHeld(enchantment.level, player, itemStack) end end end ---OnUpdateSecond ---@param itemStack ItemStack ---@param player Player function EnchantmentProxies:OnUpdateSecond(itemStack, player) if not itemStack:HasEnchantment() then return end for index = 0, itemStack.enchantmentCount - 1 do local enchantment = itemStack:GetEnchantmentByIndex(index) local proxy = self._proxies[enchantment.id] if proxy and proxy.OnUpdateSecond ~= nil then proxy.OnUpdateSecond(enchantment.level, player, itemStack) end end end ---@param equipmentIndex int ---@param itemStack ItemStack ---@param player Player function EnchantmentProxies:OnEquipped(equipmentIndex, itemStack, player) if not itemStack:HasEnchantment() then return end for index = 0, itemStack.enchantmentCount - 1 do local enchantment = itemStack:GetEnchantmentByIndex(index) local proxy = self._proxies[enchantment.id] if proxy and proxy.OnEquipped ~= nil then proxy.OnEquipped(equipmentIndex, enchantment.level, player, itemStack) end end end ---@param equipmentIndex int ---@param itemStack ItemStack ---@param player Player ---@param npc Npc function EnchantmentProxies:OnEquippedHitByNpc(equipmentIndex, itemStack, player, npc) if not itemStack:HasEnchantment() then return end for index = 0, itemStack.enchantmentCount - 1 do local enchantment = itemStack:GetEnchantmentByIndex(index) local proxy = self._proxies[enchantment.id] if proxy and proxy.OnEquippedHitByNpc ~= nil then proxy.OnEquippedHitByNpc(equipmentIndex, enchantment.level, player, itemStack, npc) end end end ---@param equipmentIndex int ---@param itemStack ItemStack ---@param player Player ---@param projectile Projectile function EnchantmentProxies:OnEquippedHitByProjectile(equipmentIndex, itemStack, player, projectile) if not itemStack:HasEnchantment() then return end for index = 0, itemStack.enchantmentCount - 1 do local enchantment = itemStack:GetEnchantmentByIndex(index) local proxy = self._proxies[enchantment.id] if proxy and proxy.OnEquippedHitByProjectile ~= nil then proxy.OnEquippedHitByProjectile(equipmentIndex, enchantment.level, player, itemStack, projectile) end end end function EnchantmentProxies:Register(idName, proxy) local id = Reg.EnchantmentID(idName) self._proxies[id] = proxy end function EnchantmentProxies:RegisterAll() self:Register("tc:knockback", require("EnchantmentKnockBack")) self:Register("tc:sharpness", require("EnchantmentSharpness")) self:Register("tc:blast_protection", require("EnchantmentBlastProtection")) self:Register("tc:aqua_affinity", require("EnchantmentAquaAffinity")) self:Register("tc:depth_strider", require("EnchantmentDepthStrider")) self:Register("tc:feather_falling", require("EnchantmentFeatherFalling")) self:Register("tc:fire_protection", require("EnchantmentFireProtection")) self:Register("tc:projectile_protection", require("EnchantmentProjectileProtection")) self:Register("tc:protection", require("EnchantmentProtection")) self:Register("tc:respiration", require("EnchantmentRespiration")) self:Register("tc:frost_walker", require("EnchantmentFrostWalker")) self:Register("tc:thorns", require("EnchantmentThorns")) self:Register("tc:phyton", require("EnchantmentPhyton")) end return EnchantmentProxies ================================================ FILE: enchantments/EnchantmentRespiration.lua ================================================ ---@class TC.EnchantmentRespiration:TC.BaseEnchantmentProxy local EnchantmentRespiration = class("EnchantmentRespiration") function EnchantmentRespiration.OnEquipped(equipmentIndex, level, player, _) player.baseDefense.breathDefense = player.baseDefense.breathDefense + level end return EnchantmentRespiration ================================================ FILE: enchantments/EnchantmentSharpness.lua ================================================ ---@class TC.EnchantmentSharpness:TC.BaseEnchantmentProxy local EnchantmentSharpness = class("EnchantmentSharpness") function EnchantmentSharpness.OnHeld(level, player, _) player.baseAttack.attack = player.baseAttack.attack + level end return EnchantmentSharpness ================================================ FILE: enchantments/EnchantmentThorns.lua ================================================ ---@class TC.EnchantmentThorns:TC.BaseEnchantmentProxy local EnchantmentThorns = class("EnchantmentThorns") function EnchantmentThorns.OnEquippedHitByNpc(equipmentIndex, level, player, itemStack, npc) local hitAngle = player:GetAngleTo(npc.centerX, npc.centerY) npc:Strike(Attack.new(1 + level, 1 + level, 0), hitAngle) SoundUtils.PlaySoundGroup(Reg.SoundGroupID("thorns_hit"), player.centerXi, player.centerYi) local initAngle = Utils.RandDouble(math.pi) local times = Utils.RandIntArea(4, 4) for i = 0, times do local angle = initAngle + i * math.pi * 2 / times EffectUtils.SendFromServer(Reg.EffectID("heal"), player.centerX, player.centerY, math.cos(angle) * 3, math.sin(angle) * 3, Utils.RandSym(0.1), Utils.RandDoubleArea(1, 0.5), 1.0, Color.Red ) end end return EnchantmentThorns ================================================ FILE: enchantments/aqua_affinity.json ================================================ { "aqua_affinity": { "noCreating": false, "minCreatingLevel": 3, "allowMaxLevel": 8, "tool": [ "HELMET" ] } } ================================================ FILE: enchantments/bane_of_arthropods.json ================================================ { "bane_of_arthropods": { "noCreating": false, "minCreatingLevel": 5, "allowMaxLevel": 8, "tool": [ "SWORD" ], "conflict": [ "smite", "sharpness" ] } } ================================================ FILE: enchantments/blast_protection.json ================================================ { "blast_protection": { "noCreating": false, "minCreatingLevel": 3, "allowMaxLevel": 8, "tool": [ "HELMET", "CHESTPLATE", "LEGGINGS" ], "conflict": [ "protection", "fire_protection", "projectile_protection" ] } } ================================================ FILE: enchantments/curse_of_binding.json ================================================ { "curse_of_binding": { "noCreating": true, "minCreatingLevel": 1000, "allowMaxLevel": 8, "tool": [ "HELMET", "CHESTPLATE", "LEGGINGS" ] } } ================================================ FILE: enchantments/curse_of_vanishing.json ================================================ { "curse_of_vanishing": { "noCreating": true, "minCreatingLevel": 1000, "allowMaxLevel": 8, "tool": [ "AXE", "PICKAXE", "SWORD", "BOW", "FISHING_ROD", "HELMET", "CHESTPLATE", "LEGGINGS" ] } } ================================================ FILE: enchantments/depth_strider.json ================================================ { "depth_strider": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "LEGGINGS" ], "conflict": [ "frost_walker" ] } } ================================================ FILE: enchantments/efficiency.json ================================================ { "efficiency": { "noCreating": false, "minCreatingLevel": 1, "allowMaxLevel": 8, "tool": [ "AXE", "PICKAXE" ] } } ================================================ FILE: enchantments/feather_falling.json ================================================ { "feather_falling": { "noCreating": false, "minCreatingLevel": 10, "allowMaxLevel": 8, "tool": [ "LEGGINGS" ] } } ================================================ FILE: enchantments/fire_aspect.json ================================================ { "fire_aspect": { "noCreating": false, "minCreatingLevel": 15, "allowMaxLevel": 8, "tool": [ "SWORD" ] } } ================================================ FILE: enchantments/fire_protection.json ================================================ { "fire_protection": { "noCreating": false, "minCreatingLevel": 8, "allowMaxLevel": 6, "tool": [ "HELMET", "CHESTPLATE", "LEGGINGS" ], "conflict": [ "blast_protection", "protection", "projectile_protection" ] } } ================================================ FILE: enchantments/flame.json ================================================ { "flame": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "BOW" ] } } ================================================ FILE: enchantments/fortune.json ================================================ { "fortune": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "AXE", "PICKAXE" ], "conflict": [ "silk_touch" ] } } ================================================ FILE: enchantments/frost_walker.json ================================================ { "frost_walker": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "LEGGINGS" ], "conflict": [ "depth_strider" ] } } ================================================ FILE: enchantments/infinity.json ================================================ { "infinity": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "BOW" ] } } ================================================ FILE: enchantments/knockback.json ================================================ { "knockback": { "noCreating": false, "minCreatingLevel": 15, "allowMaxLevel": 8, "tool": [ "SWORD" ] } } ================================================ FILE: enchantments/looting.json ================================================ { "looting": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "SWORD" ] } } ================================================ FILE: enchantments/luck_of_the_sea.json ================================================ { "luck_of_the_sea": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "FISHING_ROD" ] } } ================================================ FILE: enchantments/lure.json ================================================ { "lure": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "FISHING_ROD" ] } } ================================================ FILE: enchantments/multishot.json ================================================ { "multishot": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "CROSS_BOW" ], "conflict": [ "piercing" ] } } ================================================ FILE: enchantments/phyton.json ================================================ { "phyton": { "noCreating": true, "minCreatingLevel": 1000, "allowMaxLevel": 8, "tool": [ "AXE", "PICKAXE", "SWORD", "BOW", "FISHING_ROD", "HELMET", "CHESTPLATE", "LEGGINGS" ] } } ================================================ FILE: enchantments/piercing.json ================================================ { "piercing": { "noCreating": false, "minCreatingLevel": 18, "allowMaxLevel": 8, "tool": [ "CROSS_BOW" ], "conflict": [ "multishot" ] } } ================================================ FILE: enchantments/power.json ================================================ { "power": { "noCreating": false, "minCreatingLevel": 7, "allowMaxLevel": 8, "tool": [ "BOW" ] } } ================================================ FILE: enchantments/projectile_protection.json ================================================ { "projectile_protection": { "noCreating": false, "minCreatingLevel": 1, "allowMaxLevel": 8, "tool": [ "HELMET", "CHESTPLATE", "LEGGINGS" ], "conflict": [ "blast_protection", "fire_protection", "protection" ] } } ================================================ FILE: enchantments/protection.json ================================================ { "protection": { "noCreating": false, "minCreatingLevel": 1, "allowMaxLevel": 8, "tool": [ "HELMET", "CHESTPLATE", "LEGGINGS" ], "conflict": [ "blast_protection", "fire_protection", "projectile_protection" ] } } ================================================ FILE: enchantments/punch.json ================================================ { "punch": { "noCreating": false, "minCreatingLevel": 5, "allowMaxLevel": 8, "tool": [ "BOW" ] } } ================================================ FILE: enchantments/quick_charge.json ================================================ { "quick_charge": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "CROSS_BOW" ] } } ================================================ FILE: enchantments/respiration.json ================================================ { "respiration": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "HELMET" ] } } ================================================ FILE: enchantments/sharpness.json ================================================ { "sharpness": { "noCreating": false, "minCreatingLevel": 3, "allowMaxLevel": 8, "tool": [ "SWORD" ], "conflict": [ "bane_of_arthropods", "smite" ] } } ================================================ FILE: enchantments/silk_touch.json ================================================ { "silk_touch": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 2, "tool": [ "AXE", "PICKAXE" ], "conflict": [ "fortune" ] } } ================================================ FILE: enchantments/smite.json ================================================ { "smite": { "noCreating": false, "minCreatingLevel": 6, "allowMaxLevel": 8, "tool": [ "SWORD" ], "conflict": [ "bane_of_arthropods", "sharpness" ] } } ================================================ FILE: enchantments/thorns.json ================================================ { "thorns": { "noCreating": false, "minCreatingLevel": 29, "allowMaxLevel": 8, "tool": [ "CHESTPLATE" ] } } ================================================ FILE: enchantments/unbreaking.json ================================================ { "unbreaking": { "noCreating": false, "minCreatingLevel": 1, "allowMaxLevel": 8, "tool": [ "AXE", "PICKAXE", "SWORD", "BOW", "FISHING_ROD", "HELMET", "CHESTPLATE", "LEGGINGS" ] } } ================================================ FILE: game_debug.json ================================================ { "captureLoadedChunk": false, "hideCmd": true, "maxFps": false, "singlePlayerPort": 0, "stopNpcSpawn": false, "isSpawnNpcQuick": false, "ignoreHeartbeatPacket": true } ================================================ FILE: init.lua ================================================ local ModTerraCraft = class("ModTerraCraft") local RecordData = require("record.RecordData") function ModTerraCraft:__init() self.m_client = nil self.m_server = nil self.m_gcTick = 0 if NetMode.current == NetMode.Client then self.m_client = require("client.ModClient").new() end end function ModTerraCraft:registerProxy() math.randomseed(os.time()) local guiLoader = require("ui.GuiLoader").new() if NetMode.current == NetMode.Client then Mod.current:RegisterClientGuiLoaderCallback({ guiLoader.GetClientGuiElement, guiLoader }) else Mod.current:RegisterServerGuiLoaderCallback({ guiLoader.GetServerGuiElement, guiLoader }) local TCModWorldData = require("world.TCModWorldData") local wdIns = TCModWorldData.getInstance() Mod.current:RegisterWorldServerSaver({ TCModWorldData.Save, wdIns }) Mod.current:RegisterWorldServerLoader({ TCModWorldData.Load, wdIns }) end local networkProxyHandler = require("network.TCNetworkProxyHandler") networkProxyHandler.new() local EnchantmentProxies = require("enchantments.EnchantmentProxies") EnchantmentProxies.getInstance():RegisterAll() local BuffProxies = require("buffs.BuffProxies") BuffProxies.getInstance():RegisterAll() local AdvancementTriggers = require("advancements.AdvancementTriggers") AdvancementTriggers.getInstance():RegisterAll() if NetMode.current == NetMode.Client then local MusicSceneProxy = require("client.MusicSceneProxy") MusicSceneProxy.getInstance():registerAll() end collectgarbage() end function ModTerraCraft:init() self:registerProxy() if Mod.GetByID("mod_edit") then print("has mod_edit!") end if NetMode.current == NetMode.Server then else self.m_client:init() end end function ModTerraCraft:start() if NetMode.current == NetMode.Server then else self.m_client:start() end end function ModTerraCraft:preUpdate() if NetMode.current == NetMode.Server then else self.m_client:preUpdate() end end function ModTerraCraft:update() if NetMode.current == NetMode.Server then RecordData.getInstance():update() else self.m_client:update() end self.m_gcTick = self.m_gcTick + 1 if self.m_gcTick >= 60 then -- do gc every 1 seconds self.m_gcTick = 0 collectgarbage() end end function ModTerraCraft:render() if NetMode.current == NetMode.Client then self.m_client:render() end end function ModTerraCraft:exit() if NetMode.current == NetMode.Server then else self.m_client:exit() end end return ModTerraCraft ================================================ FILE: item_ai/Axe.json ================================================ { "Axe": { "script": { "path": "Axe.lua" }, "destroyFragileBlocks": true, "crossTiles": false, "consumeItems": false, "consumeMana": false, "directHitPlayer": true, "directHitNpc": true, "hitDecreaseDurable": 0.2, "shootDecreaseDurable": 0.0 } } ================================================ FILE: item_ai/Axe.lua ================================================ ---@class TC.Axe:TC.BaseTool local Axe = class("Staff", require("BaseTool")) function Axe:DrawIcon(position, color, spriteExData) self:_DrawIconRotated(position, color, spriteExData) end return Axe ================================================ FILE: item_ai/BaseAccessory.lua ================================================ ---@class TC.BaseAccessory:ModItem local BaseAccessory = class("BaseAccessory", ModItem) --- ---@param player Player function BaseAccessory:OnAccessoryUpdate(player) end return BaseAccessory ================================================ FILE: item_ai/BaseRangedWeapon.lua ================================================ ---@class TC.BaseRangedWeapon:TC.BaseTool local BaseRangedWeapon = class("BaseRangedWeapon", require("BaseTool")) local GPlayer = require("player.GPlayer") function BaseRangedWeapon:OnUsedByNpc(npc) local item = self.itemStack:GetItem() local modNpc = npc:GetModNpc() if modNpc.GetHeldItemJoint ~= nil then local itemJoint = modNpc:GetHeldItemJoint() local projectileID = item.shootProjectileID local realShootAngle = npc.watchAngle local shootPoint = self:GetShootPoint(itemJoint) local speed = item.speed local proj = ProjectileUtils.CreateFromNpc(npc, projectileID, shootPoint.x, shootPoint.y, math.cos(realShootAngle) * speed, math.sin(realShootAngle) * speed, npc.baseAttack) proj.isCheckPlayer = true end end function BaseRangedWeapon:OnHeld(player) local item = self.itemStack:GetItem() local globalPlayer = GPlayer.GetInstance(player) local lookAngle = globalPlayer:GetLookAngleInFacingDirection() - math.pi / 2 local body = globalPlayer.bone.joints:getJoint("base.body") local head = body:getChild("head") local backArm = body:getChild("back_arm") local backHand = backArm:getChild("back_hand") local frontArm = body:getChild("front_arm") backArm.angle = lookAngle backHand.angle = 0 local bodyAngle = lookAngle + math.pi / 2 head.angle = bodyAngle / 4 if item.twoHands then frontArm.angle = lookAngle end globalPlayer.bone:update(false) end function BaseRangedWeapon:OnUsed(player) local item = self.itemStack:GetItem() local globalPlayer = GPlayer.GetInstance(player) if globalPlayer.currentActionMaxTicks <= 0 then -- avoid divide by zero return end if item.consumeMana > 0 and player.mana < item.consumeMana then return end if item.maxDurable > 0 and self.itemStack.durable <= 0 then return end local lookAngle = globalPlayer:GetLookAngleInFacingDirection() - math.pi / 2 local itemJoint = globalPlayer:GetHeldItemJoint() ---@type Joint2D local body = globalPlayer.bone.joints:getJoint("base.body") local head = body:getChild("head") local backArm = body:getChild("back_arm") local backHand = backArm:getChild("back_hand") local frontArm = body:getChild("front_arm") backArm.angle = lookAngle backHand.angle = 0 local bodyAngle = lookAngle + math.pi / 2 head.angle = bodyAngle / 4 local realShootAngle = player.lookAngle if item.twoHands then if item.usePosture == 1 then local rate = globalPlayer.currentActionTick * 1.0 / globalPlayer.currentActionMaxTicks if rate < 0.5 then frontArm.angle = lookAngle - math.sin(rate * math.pi / 0.5) else frontArm.angle = lookAngle end else frontArm.angle = lookAngle end end self:OnSolveUsingAnimation(player) -- Let's shoot the projectile from current bow! local triggerShooting = globalPlayer.currentActionTick == 0 if triggerShooting then local needConsume = true local ammoIndex = -1 local projectileID = 0 local checkConsume = self:IsCheckingConsume(player) local isMorePower = false if checkConsume then if item.ammoID > 0 then local searchBest = item.ammoLevel == 0 ammoIndex = globalPlayer:GetAmmoIndexInBackpack(item.ammoID, item.ammoLevel, searchBest) if ammoIndex >= 0 then local slot = player.backpackInventory:GetSlot(ammoIndex) if slot.hasStack then local ammoItem = slot:GetStack():GetItem() if item.ammoLevel > 0 and ammoItem.ammoLevel == 0 then projectileID = item.shootProjectileID else projectileID = ammoItem.projectileID end if item.ammoLevel > 0 and item.ammoLevel == ammoItem.ammoLevel then isMorePower = true end end end end else needConsume = false projectileID = item.shootProjectileID end if checkConsume and ammoIndex < 0 then return end projectileID = self:GetActualProjectileID(player, projectileID) if projectileID > 0 then local collided = MapUtils.WeaponCollideWithMap(itemJoint:getWorldObb(), false) -- TODO: FIX THIS local ignoreOverlapWithSolid = true if not collided or (collided and ignoreOverlapWithSolid) then local killAmmo = false local attachItemID = -1 if NetMode.current == NetMode.Server then if needConsume and ammoIndex >= 0 and player.backpackInventory:GetSlot(ammoIndex).hasStack then if Utils.RandDouble(1) >= item.noConsumeChance then killAmmo = true if self:NeedAttachItemToProjectile(player) then attachItemID = player.backpackInventory:GetSlot(ammoIndex):GetStack():GetItem().id end end end end local shootPoint = self:GetShootPoint(itemJoint) local speed = self:GetShootSpeed(player, projectileID, nil) local attack = self:GetAttackValue(player, projectileID, nil) realShootAngle = self:GetRealShootAngle(realShootAngle, player, projectileID, nil) attack = attack or Attack.new(0, 0, 0) if isMorePower then attack.attack = math.floor(attack.attack * 1.3) attack.knockBack = math.floor(attack.knockBack * 1.3) end local angleDt = self:GetMultiProjectileDeltaAngle(player, projectileID) local angleTotalDt = 0 local shootTimes = math.max(1, item.shootTimes) for i = 0, shootTimes - 1 do local angle = realShootAngle + angleTotalDt angleTotalDt = -angleTotalDt if i % 2 == 0 then angleTotalDt = angleTotalDt + angleDt end local realAttack = self:GetRealAttackValue(shootTimes, attack) local proj = ProjectileUtils.CreateFromPlayer(player, projectileID, shootPoint.x, shootPoint.y, math.cos(angle) * speed, math.sin(angle) * speed, realAttack) proj.isCheckNpc = true if attachItemID > 0 and NetMode.current == NetMode.Server then local mp = proj:GetModProjectile() if mp then mp.attachItemID = attachItemID attachItemID = -1 end end end if item.consumeMana > 0 then player.mana = math.max(player.mana - item.consumeMana, 0) end local ammoStack = nil if needConsume and ammoIndex >= 0 and player.backpackInventory:GetSlot(ammoIndex).hasStack then ammoStack = player.backpackInventory:GetSlot(ammoIndex):GetStack() end self:OnAfterShoot(player, projectileID, ammoStack, itemJoint, realShootAngle) if killAmmo then player.backpackInventory:GetSlot(ammoIndex):DecrStackSize(1) end if item.maxDurable > 0 then self.itemStack:LoseDurable(1) end end end end -- test --if NetMode.current == NetMode.Client then -- local tp = itemJoint.transform.worldMatrix:transformVector2(self.itemStack:GetItem():GetFirePoint(0)) -- local spx, spy = math.cos(realShootAngle) * 8, math.sin(realShootAngle) * 8 -- EffectUtils.Create(Reg.EffectID("circle"), tp.x, tp.y, -- spx, spy, -- 0, 0.2, 0.2) -- --end end ---OnSolveUsingAnimation ---@param player Player function BaseRangedWeapon:OnSolveUsingAnimation(player) end ---IsCheckingConsume ---@param player Player ---@return boolean function BaseRangedWeapon:IsCheckingConsume(player) return false end function BaseRangedWeapon:NeedAttachItemToProjectile(player) return false end ---GetActualProjectileID ---@param player Player ---@param rawProjectileID int ---@return int function BaseRangedWeapon:GetActualProjectileID(player, rawProjectileID) return rawProjectileID end ---GetMultiProjectileDeltaAngle ---@param player Player ---@param projectileID int ---@return double function BaseRangedWeapon:GetMultiProjectileDeltaAngle(player, projectileID) return 0.1 end ---GetAttackValue ---@param player Player ---@param projectileID int ---@param ammoStack ItemStack|nil ---@return Attack function BaseRangedWeapon:GetAttackValue(player, projectileID, ammoStack) local item = self.itemStack:GetItem() local attack = player.baseAttack.attack + item.baseAttack.attack local knockBack = player.baseAttack.knockBack + item.baseAttack.knockBack local crit = player.baseAttack.crit + item.baseAttack.crit return Attack.new(attack, knockBack, crit) end function BaseRangedWeapon:GetRealAttackValue(shootTimes, baseAttack) local attack = baseAttack.attack local knockBack = baseAttack.knockBack local crit = baseAttack.crit for i = 2, shootTimes do attack = attack * 0.8 knockBack = knockBack * 0.8 crit = crit * 0.8 end return Attack.new(attack, knockBack, crit) end ---GetShootSpeed ---@param player Player ---@param projectileID int ---@param ammoStack ItemStack|nil ---@return double function BaseRangedWeapon:GetShootSpeed(player, projectileID, ammoStack) local item = self.itemStack:GetItem() return item.speed end ---GetRealShootAngle ---@param baseAngle double ---@param player Player ---@param projectileID int ---@param ammoStack ItemStack|nil ---@return double function BaseRangedWeapon:GetRealShootAngle(baseAngle, player, projectileID, ammoStack) local item = self.itemStack:GetItem() return Utils.FixAngle(baseAngle + Utils.RandSym(item.deviation)) end ---@param player Player ---@param projectileID int ---@param ammoStack ItemStack|nil ---@param itemJoint Joint2D ---@param realShootAngle double function BaseRangedWeapon:OnAfterShoot(player, projectileID, ammoStack, itemJoint, realShootAngle) local item = self.itemStack:GetItem() local soundID = item.useSoundID if soundID > 0 then SoundUtils.PlaySound(soundID, player.centerXi, player.centerYi) end local soundGroupID = item.useSoundGroupID if soundGroupID > 0 then SoundUtils.PlaySoundGroup(soundGroupID, player.centerXi, player.centerYi) end local force = 0 local backForceX = -force * math.cos(realShootAngle) local backForceY = -force * math.sin(realShootAngle) player.speedX = player.speedX + backForceX player.speedY = player.speedY + backForceY end ---GetShootPoint ---@param itemJoint Joint2D ---@return Vector2 function BaseRangedWeapon:GetShootPoint(itemJoint) return itemJoint.transform.worldMatrix:transformVector2(self.itemStack:GetItem():GetFirePoint(0)) end return BaseRangedWeapon ================================================ FILE: item_ai/BaseTool.lua ================================================ ---@class TC.BaseTool:ModItem local BaseTool = class("BaseTool", ModItem) function BaseTool:_DrawIconRotated(position, color, spriteExData, rotateAngle) if rotateAngle == nil then rotateAngle = math.pi / 4 end local item = self.itemStack:GetItem() local texture = item.iconTextureLocation local rectSource = TextureManager.getSourceRect(texture) spriteExData.angle = spriteExData.angle + rotateAngle spriteExData.originX = rectSource.width / 2 spriteExData.originY = rectSource.height / 2 local adaptWidth = rectSource.width > 32 local adaptHeight = rectSource.height > 32 if adaptWidth or adaptHeight then local maxRate = 1.0 if adaptWidth then maxRate = math.max(maxRate, rectSource.width / 32.0) end if adaptHeight then maxRate = math.max(maxRate, rectSource.height / 32.0) end spriteExData.scaleRateX = spriteExData.scaleRateX / maxRate * 1.25 spriteExData.scaleRateY = spriteExData.scaleRateY / maxRate * 1.25 end Sprite.draw(texture, position, rectSource, color, spriteExData, 0) end return BaseTool ================================================ FILE: item_ai/BlueTalisman.json ================================================ { "BlueTalisman": { "script": { "path": "BlueTalisman.lua" } } } ================================================ FILE: item_ai/BlueTalisman.lua ================================================ ---@class TC.BlueTalisman:TC.BaseAccessory local BlueTalisman = class("BlueTalisman", require("BaseAccessory")) ---OnAccessory ---@param player Player function BlueTalisman:OnAccessoryUpdate(player) if player.tickTime % 64 == 0 then player:AddMagic(1, false) end end return BlueTalisman ================================================ FILE: item_ai/BossCaller.json ================================================ { "BossCaller": { "script": { "path": "BossCaller.lua" } } } ================================================ FILE: item_ai/BossCaller.lua ================================================ ---@class TC.BossCaller:ModItem local BossCaller = class("BossCaller", ModItem) function BossCaller:Init() self.isBossCaller = true end function BossCaller:CanUse(player) return true end function BossCaller:OnUsed(player) self:GenBoss(player) SoundUtils.PlaySound(Reg.SoundID("monster"), player.centerXi, player.centerYi) end function BossCaller:GenBoss(player) end function BossCaller:IsKilledAfterUsed() return true end return BossCaller ================================================ FILE: item_ai/Bow.json ================================================ { "Bow": { "script": { "path": "Bow.lua" }, "destroyFragileBlocks": false, "crossTiles": false, "consumeItems": true, "consumeMana": false, "directHitPlayer": false, "directHitNpc": false, "hitDecreaseDurable": 0.0, "shootDecreaseDurable": 1.0 } } ================================================ FILE: item_ai/Bow.lua ================================================ ---@class Bow:TC.BaseRangedWeapon local Bow = class("Bow", require("BaseRangedWeapon")) function Bow:IsCheckingConsume(player) return true end function Bow:NeedAttachItemToProjectile(player) return true end --function Bow:CheckShoot(itemSlot, hitbox, consumeItemID, projectileID, fireX, fireY, shootSpeed, shootAngle, baseAttack) -- -- check enchantments -- baseAttack.attack = baseAttack.attack + itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("power")) -- baseAttack.knockBack = baseAttack.knockBack + itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("punch")) -- return true --end -- --function Bow:OnShootFromPlayer(itemSlot, player, hitbox, consumeItemID, projectileID, fireX, fireY, shootSpeed, shootAngle, -- baseAttack) -- local flameLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("flame")) -- local shootTimes = itemSlot.shootTimes -- for i = 1, shootTimes do -- local angle = shootAngle + Utils.RandSym(itemSlot.deviation) -- local speed = shootSpeed -- local proj = ProjectileUtils.CreateFromPlayer(player, projectileID, fireX, fireY, math.cos(angle) * speed, -- math.sin(angle) * speed, baseAttack) -- proj.isCheckPlayer = true -- proj.isCheckNpc = true -- if proj.modData:DataOf("Arrow") then -- if i == 1 and consumeItemID > 0 then -- proj.modData.attachItemID = consumeItemID -- end -- proj.modData.flameLevel = flameLevel -- end -- end -- return true --end -- --function Bow:OnShootFromNpc(itemSlot, npc, hitbox, consumeItemID, projectileID, fireX, fireY, shootSpeed, shootAngle, -- baseAttack) -- local flameLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("flame")) -- local shootTimes = itemSlot.shootTimes -- for i = 1, shootTimes do -- local angle = shootAngle + Utils.RandSym(itemSlot.deviation) -- local speed = shootSpeed -- local proj = ProjectileUtils.CreateFromNpc(npc, projectileID, fireX, fireY, math.cos(angle) * speed, -- math.sin(angle) * speed, baseAttack) -- proj.isCheckPlayer = true -- proj.isCheckNpc = false -- if proj.modData:DataOf("Arrow") then -- if i == 1 and consumeItemID > 0 then -- proj.modData.attachItemID = consumeItemID -- end -- proj.modData.flameLevel = flameLevel -- end -- end -- return true --end -- --function Bow:CheckConsumeItem(itemSlot, player, projectileID) -- local infinityLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("infinity")) -- -- Has unlimited enchantments, so no items are consumed -- if infinityLevel > 0 then -- return false -- end -- return true --end return Bow ================================================ FILE: item_ai/CrisonEye.json ================================================ { "CrisonEye": { "script": { "path": "CrisonEye.lua" } } } ================================================ FILE: item_ai/CrisonEye.lua ================================================ ---@class TC.CrisonEyeItem:TC.BossCaller local CrisonEye = class("CrisonEye", require("BossCaller")) local RecordData = require("record.RecordData") function CrisonEye:CanUse(player) if MiscUtils.isNight then if not RecordData.getInstance().hasCrisonEye then return true end end return false end ---@param player Player function CrisonEye:GenBoss(player) NpcUtils.Create(Reg.NpcID("crison_eye"), player.centerX - 700, player.centerY - 400) end return CrisonEye ================================================ FILE: item_ai/DungeonEater.json ================================================ { "DungeonEater": { "script": { "path": "DungeonEater.lua" } } } ================================================ FILE: item_ai/DungeonEater.lua ================================================ ---@class TC.DungeonEaterItem:TC.BossCaller local DungeonEater = class("DungeonEater", require("BossCaller")) local RecordData = require("record.RecordData") function DungeonEater:CanUse(player) if not RecordData.getInstance().hasDungeonEater then if player.biomeID == Reg.BiomeID("more_dungeons:tr_dungeon") then return true end end return false end ---@param player Player function DungeonEater:GenBoss(player) NpcUtils.Create(Reg.NpcID("dungeon_eater_head"), player.centerX - 700, player.centerY + 300) end return DungeonEater ================================================ FILE: item_ai/EnderMirror.json ================================================ { "EnderMirror": { "script": { "path": "EnderMirror.lua" } } } ================================================ FILE: item_ai/EnderMirror.lua ================================================ ---@class TC.EnderMirror:ModItem local EnderMirror = class("EnderMirror", ModItem) function EnderMirror:Init() end function EnderMirror:CanUse(player) return true end function EnderMirror:OnHeld(player) end function EnderMirror:OnUsed(player) local ok = player:GoHome() if not ok then player:TeleportToSpawn() end player:FinishAdvancement(Reg.AdvancementID("mirror")) SoundUtils.PlaySound(Reg.SoundID("travel"), player.centerXi, player.centerYi) end function EnderMirror:GenBoss(player) end function EnderMirror:IsKilledAfterUsed() return false end return EnderMirror ================================================ FILE: item_ai/Food.json ================================================ { "Food": { "script": { "path": "Food.lua" } } } ================================================ FILE: item_ai/Food.lua ================================================ ---@class TC.Food:ModItem local Food = class("Food", ModItem) local Constants = require("constants.Constants") function Food:CanUse(player) local stack = self.itemStack local healthCodeID = Reg.BuffID("health_cold") local item = stack:GetItem() local buffs = item.buffs if player:HasBuff(healthCodeID) then for _, buff in ipairs(buffs) do if buff.id == healthCodeID then return false end end end if #buffs > 0 then return true end if item.addHealth > 0 or (item.addMagic > 0 and item.addMaxMagic == 0) then return true end if item.addMaxMagic > 0 then if player.maxMana < Constants.PLAYER_MAX_MAX_MANA then return true end return false end if item.food > 0 and player.foodLevel < 100 then return true end return false end function Food:OnUsed(player) local item = self.itemStack:GetItem() if item.addHealth ~= 0 then local v = math.abs(item.addHealth) if item.addHealth < 0 then player:Strike(DeathReason.BUFF, Attack.new(v, 0, 0), 0, false, false) else player:Heal(v) end end if item.addMaxMagic ~= 0 then local PlayerConstants = require("player.PlayerConstants") player.maxMana = math.min(PlayerConstants.MaxManaA, player.maxMana + item.addMaxMagic) end if item.addMagic ~= 0 then local v = math.abs(item.addMagic) player:AddMagic(v) end local buffs = item.buffs for _, buff in ipairs(buffs) do player:AddBuff(buff.id, buff.time) end if item.food > 0 and player.foodLevel < 100 then player:AddFood(item.food, item.foodSaturation) end self:PlayEatSound(player) end function Food:PlayEatSound(player) SoundUtils.PlaySoundGroup(Reg.SoundGroupID("eat"), player.centerXi, player.centerYi) end function Food:IsKilledAfterUsed() return true end return Food ================================================ FILE: item_ai/Gun.json ================================================ { "Gun": { "script": { "path": "Gun.lua" }, "destroyFragileBlocks": false, "crossTiles": false, "consumeItems": true, "consumeMana": false, "directHitPlayer": false, "directHitNpc": false, "hitDecreaseDurable": 0.0, "shootDecreaseDurable": 1.0 } } ================================================ FILE: item_ai/Gun.lua ================================================ ---@class TC.Gun:TC.BaseRangedWeapon local Gun = class("Gun", require("BaseRangedWeapon")) function Gun:IsCheckingConsume(player) return true end function Gun:NeedAttachItemToProjectile(player) return true end --local e_fire_smoke = Reg.EffectID("fire_smoke") --local e_liquid_paticular = Reg.EffectID("liquid_paticular") -- --function Gun:CheckShoot(itemSlot, hitbox, consumeItemID, projectileID, fireX, fireY, shootSpeed, shootAngle, baseAttack) -- -- Add some gunpowder effect. -- -- local special = itemSlot.special -- if special == 1 then -- Shoot from a normal gun. -- local effect = EffectUtils.Create(e_fire_smoke, fireX, fireY, math.cos(shootAngle) * 0.5 + Utils.RandSym(0.25), -- math.cos(shootAngle) * 0.5 + Utils.RandSym(0.25), Utils.RandSym(0.1), -- Utils.RandDoubleArea(1.5, 0.5), 0.5) -- effect.color = Color.new(200,200,200) -- for i = 1, 3 do -- local effect2 = EffectUtils.Create(e_liquid_paticular, fireX, fireY, -- math.cos(shootAngle) * 1.0 + Utils.RandSym(0.25), -- math.cos(shootAngle) * 1.0 - Utils.RandDouble(0.5), Utils.RandSym(0.1), 0.5) -- effect2.color = Color.Yellow -- end -- elseif special == 2 then -- Shoot from a fire gun. -- local effect = EffectUtils.Create(e_liquid_paticular, fireX, fireY, -- math.cos(shootAngle) * 0.2 + Utils.RandSym(0.25), -Utils.RandDouble(0.75), -- Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 1.0), 0.5) -- effect.color = Color.new(255,180,0) -- elseif special == 3 then -- Shoot from a laser gun. -- for i = 1, 3 do -- EffectUtils.Create(e_liquid_paticular, fireX, fireY, math.cos(shootAngle) * 0.2 + Utils.RandSym(0.25), -- -Utils.RandDouble(0.75), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 1.0), 0.5) -- end -- end -- -- return true --end return Gun ================================================ FILE: item_ai/InfBow.json ================================================ { "InfBow": { "script": { "path": "InfBow.lua" }, "destroyFragileBlocks": false, "crossTiles": false, "consumeItems": true, "consumeMana": false, "directHitPlayer": false, "directHitNpc": false, "hitDecreaseDurable": 0.0, "shootDecreaseDurable": 1.0 } } ================================================ FILE: item_ai/InfBow.lua ================================================ ---@class InfBow:TC.BaseRangedWeapon local InfBow = class("InfBow", require("BaseRangedWeapon")) function InfBow:IsCheckingConsume(player) return false end function InfBow:NeedAttachItemToProjectile(player) return false end return InfBow ================================================ FILE: item_ai/Ingot.json ================================================ { "Ingot": { "script": { "path": "Ingot.lua" } } } ================================================ FILE: item_ai/Ingot.lua ================================================ ---@class TC.Ingot:ModItem local Ingot = class("Ingot", ModItem) function Ingot:IsUseTex32() return true end function Ingot:DrawIcon(position, color, spriteExData) local item = self.itemStack:GetItem() local texture = item.iconTextureLocation local rectSource = TextureManager.getSourceRect(texture) local width = rectSource.width local height = rectSource.height / 2 spriteExData.originX = width / 2 spriteExData.originY = height / 2 local rectBase = Rect.new(0, 0, width, height) Sprite.draw(texture, position, rectBase, item.iconColor * color, spriteExData, 0) if item.iconColor2.alpha ~= 0 then local rectHighlight = Rect.new(0, height, width, height) Sprite.draw(texture, position, rectHighlight, item.iconColor2 * color, spriteExData, 0) end end return Ingot ================================================ FILE: item_ai/LavaNecklace.json ================================================ { "LavaNecklace": { "script": { "path": "LavaNecklace.lua" } } } ================================================ FILE: item_ai/LavaNecklace.lua ================================================ ---@class TC.LavaNecklace:TC.BaseAccessory local LavaNecklace = class("LavaNecklace", require("BaseAccessory")) ---OnAccessory ---@param player Player function LavaNecklace:OnAccessoryUpdate(player) if NetMode.current == NetMode.Client then local cnt = 3 for i = 1, cnt do local angle = player.tickTime / 10 + math.pi * 2 / cnt * i local d = 45 local x = player.centerX + math.cos(angle) * d local y = player.centerY + math.sin(angle) * d local effect = EffectUtils.Create( Reg.EffectID("circle"), x, y, Utils.RandSym(0.5), Utils.RandSym(0.5), 0, Utils.RandDoubleArea(0.25, 0.15), Utils.RandDoubleArea(0.25, 0.15), Color.new(255, 255, 0) ) effect:SetDisappearTime(6) local effect = EffectUtils.Create( Reg.EffectID("chip"), x, y, Utils.RandSym(1.5), Utils.RandSym(1.5), 0, Utils.RandDoubleArea(0.75, 0.5), Utils.RandDoubleArea(0.5, 0.5), Color.new(255, 255, 0) ) effect:SetDisappearTime(12) end --if player.tickTime % 8 == 0 then -- local effect = EffectUtils.Create(Reg.EffectID("heal"), -- player.randX, player.randY, -- Utils.RandSym(1), Utils.RandDoubleArea(-2, 2) -- ) -- effect:SetDisappearTime(10) -- --end else if player.tickTime % 64 == 0 then player:AddBuff(Reg.BuffID("fire_defense"), 100) end end end return LavaNecklace ================================================ FILE: item_ai/LavaSword.json ================================================ { "LavaSword": { "script": { "path": "LavaSword.lua" } } } ================================================ FILE: item_ai/LavaSword.lua ================================================ ---@class TC.LavaSword:TC.Sword local LavaSword = class("LavaSword", require("Sword")) function LavaSword:ModifyHitNpc(npc, baseAttack) npc:AddBuff(Reg.BuffID("fire"), 128) return true end return LavaSword ================================================ FILE: item_ai/LightingTalisman.json ================================================ { "LightingTalisman": { "script": { "path": "LightingTalisman.lua" } } } ================================================ FILE: item_ai/LightingTalisman.lua ================================================ ---@class TC.LightingTalisman:TC.BaseAccessory local LightingTalisman = class("LightingTalisman", require("BaseAccessory")) ---OnAccessory ---@param player Player function LightingTalisman:OnAccessoryUpdate(player) LightingUtils.Add(player.centerXi, player.centerYi, 32) end return LightingTalisman ================================================ FILE: item_ai/Pickaxe.json ================================================ { "Pickaxe": { "script": { "path": "Pickaxe.lua" }, "destroyFragileBlocks": true, "crossTiles": false, "consumeItems": false, "consumeMana": false, "directHitPlayer": true, "directHitNpc": true, "hitDecreaseDurable": 0.2, "shootDecreaseDurable": 0.0 } } ================================================ FILE: item_ai/Pickaxe.lua ================================================ ---@class TC.Pickaxe:TC.BaseTool local Pickaxe = class("Staff", require("BaseTool")) function Pickaxe:DrawIcon(position, color, spriteExData) self:_DrawIconRotated(position, color, spriteExData) end return Pickaxe ================================================ FILE: item_ai/Potion.json ================================================ { "Potion": { "script": { "path": "Potion.lua" } } } ================================================ FILE: item_ai/Potion.lua ================================================ ---@class TC.Potion:TC.Food local Potion = class("Potion", require("Food")) function Potion:IsUseTex32() return true end function Potion:DrawIcon(position, color, spriteExData) local item = self.itemStack:GetItem() local texture = item.iconTextureLocation local rectSource = TextureManager.getSourceRect(texture) local width = rectSource.width local height = rectSource.height / 2 spriteExData.originX = width / 2 spriteExData.originY = height / 2 local rectBase = Rect.new(0, 0, width, height) local rectLiquid = Rect.new(0, height, width, height) if item.iconColor2.alpha ~= 0 then Sprite.draw(texture, position, rectLiquid, item.iconColor2 * color, spriteExData, 0) end Sprite.draw(texture, position, rectBase, color, spriteExData, 0) end function Potion:PlayEatSound(player) SoundUtils.PlaySound(Reg.SoundID("drink"), player.centerXi, player.centerYi) end return Potion ================================================ FILE: item_ai/RedTalisman.json ================================================ { "RedTalisman": { "script": { "path": "RedTalisman.lua" } } } ================================================ FILE: item_ai/RedTalisman.lua ================================================ ---@class TC.RedTalisman:TC.BaseAccessory local RedTalisman = class("RedTalisman", require("BaseAccessory")) ---OnAccessory ---@param player Player function RedTalisman:OnAccessoryUpdate(player) if player.tickTime % 64 == 0 then player:Heal(1, false) end end return RedTalisman ================================================ FILE: item_ai/RocketBoost.json ================================================ { "RocketBoost": { "script": { "path": "RocketBoost.lua" } } } ================================================ FILE: item_ai/RocketBoost.lua ================================================ ---@class TC.RocketBoost:TC.BaseAccessory local RocketBoost = class("RocketBoost", require("BaseAccessory")) local GPlayer = require("player.GPlayer") local PlayerConstants = require("player.PlayerConstants") function RocketBoost:Init() self.flying = false self.flyingTime = 0 self.flyingTimeMax = 128 end ---OnAccessory ---@param player Player function RocketBoost:OnAccessoryUpdate(player) if NetMode.current == NetMode.Client then local gPlayer = GPlayer.GetInstance(player) self.flyingTimeMax = 128 self:FlyMove(player) if self.flying then local fts = { gPlayer.bone.joints:getJoint("base.body.front_leg.front_feet"), gPlayer.bone.joints:getJoint("base.body.back_leg.back_feet") } for i = 1, 2 do local c = fts[i].transform.worldMatrix:transformVector2(Vector2.new(4, 16)) local effect = EffectUtils.Create( Reg.EffectID("fire_smoke"), c.x, c.y, Utils.RandSym(0.5), 1 + Utils.RandSym(0.5), Utils.RandSym(0.5), Utils.RandDoubleArea(0.55, 0.15), 1.0, Color.new(255, 255, 255) ) effect:SetDisappearTime(50) if player.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("fire_flame"), c.x, c.y, Utils.RandSym(0.5), 0.5 + Utils.RandSym(0.5), Utils.RandSym(0.5), Utils.RandDoubleArea(0.55, 0.15), 1.0, Color.new(255, 255, 255) ) end end end end end function RocketBoost:FlyMove(player) local gPlayer = GPlayer.GetInstance(player) if not gPlayer.jump then self.flying = false end if player.stand then self.flying = false self.flyingTime = 0 return end if player.speedY > 0.5 then if gPlayer.jump then self.flying = true end end if self.flying then self.flyingTime = self.flyingTime + 1 if self.flyingTime > self.flyingTimeMax then self.flying = false return end player.speedY = player.speedY - 0.8 if player.speedY < -PlayerConstants.MAX_SPEED_UP / 2 then player.speedY = -PlayerConstants.MAX_SPEED_UP / 2 end end end return RocketBoost ================================================ FILE: item_ai/Staff.json ================================================ { "Staff": { "script": { "path": "Staff.lua" }, "destroyFragileBlocks": false, "crossTiles": false, "consumeItems": false, "consumeMana": true, "directHitPlayer": false, "directHitNpc": false, "hitDecreaseDurable": 0.0, "shootDecreaseDurable": 0.0 } } ================================================ FILE: item_ai/Staff.lua ================================================ ---@class TC.Staff:TC.BaseRangedWeapon local Staff = class("Staff", require("BaseRangedWeapon")) local GPlayer = require("player.GPlayer") local BoneAction = { StaffShooting = 5, } function Staff:OnHeld(player) local globalPlayer = GPlayer.GetInstance(player) if globalPlayer.currentAction == BoneAction.StaffShooting or globalPlayer.lastTickAction == BoneAction.StaffShooting then return end local body = globalPlayer.bone.joints:getJoint("base.body") local backArm = body:getChild("back_arm") local backHand = backArm:getChild("back_hand") backArm.angle = -math.pi * 0.4 backHand.angle = 0 globalPlayer.bone:update(false) end function Staff:OnSolveUsingAnimation(player) local globalPlayer = GPlayer.GetInstance(player) local itemJoint = globalPlayer:GetHeldItemJoint() itemJoint.angle = math.pi end function Staff:DrawIcon(position, color, spriteExData) self:_DrawIconRotated(position, color, spriteExData) end return Staff ================================================ FILE: item_ai/Sword.json ================================================ { "Sword": { "script": { "path": "Sword.lua" } } } ================================================ FILE: item_ai/Sword.lua ================================================ ---@class TC.Sword:TC.BaseTool local Sword = class("Sword", require("BaseTool")) local GPlayer = require("player.GPlayer") local USE_DECREASE_DURABLE = 0.5 function Sword:Init() self.wasSwingAtCenter = false end function Sword:OnHeld(player) end function Sword:IsKilledAfterUsed() return self.itemStack.durable <= 0 end function Sword:OnKilledAfterUsed(player) SoundUtils.PlaySound(Reg.SoundID("broken"), player.centerXi, player.centerYi) end function Sword:OnUsedByNpc(npc) local modNpc = npc:GetModNpc() if modNpc == nil or modNpc.GetHeldItemJoint == nil then return end local itemJoint = modNpc:GetHeldItemJoint() local attack = npc.baseAttack local resPlayerIndex = EntityIndex.new() local isHitPlayer = PlayerUtils.WeaponCollide(self.itemStack, 0, itemJoint:getWorldObb(), attack, resPlayerIndex) if isHitPlayer then local player = PlayerUtils.Get(resPlayerIndex) local hitAngle = 0.0 if not npc.direction then hitAngle = math.pi end player:StrikeFromNpc(npc, attack, hitAngle, true) end end function Sword:OnUsed(player) local item = self.itemStack:GetItem() local globalPlayer = GPlayer.GetInstance(player) local itemJoint = globalPlayer:GetHeldItemJoint() if globalPlayer.currentActionTick == 0 then self.wasSwingAtCenter = false SoundUtils.PlaySound(Reg.SoundID("weapon"), player.centerXi, player.centerYi) elseif globalPlayer.currentActionTick > 0.05 then -- destroy the map block local hitSolid, hasBlockDestroyed = MapUtils.WeaponCollideWithMap(itemJoint:getWorldObb(), true) if not hitSolid then local attack = player.baseAttack local resNpcIndex = EntityIndex.new() local hitNpc = NpcUtils.WeaponCollide(self.itemStack, 0, itemJoint:getWorldObb(), attack, resNpcIndex) if hitNpc then local npc = NpcUtils.Get(resNpcIndex) local hitAngle = 0.0 if not player.direction then hitAngle = math.pi end local looting = self.itemStack:GetEnchantmentLevel(Reg.EnchantmentID("looting")) npc:StrikeFromPlayer(player, attack, hitAngle, true, true, looting) if NetMode.current == NetMode.Server then -- TODO 耐久在创造模式不减 if USE_DECREASE_DURABLE > 0 then self.itemStack:LoseDurable(USE_DECREASE_DURABLE) end end end if not self.wasSwingAtCenter and globalPlayer.currentActionTick > 0.5 then self.wasSwingAtCenter = true if item.consumeMana > 0 and item.shootProjectileID > 0 then if player.mana >= item.consumeMana then player.mana = math.max(0, player.mana - item.consumeMana) local cx, cy = player.centerX, player.centerY local realShootAngle = not player.direction and math.pi or 0 local proj = ProjectileUtils.CreateFromPlayer(player, item.shootProjectileID, cx, cy, math.cos(realShootAngle) * item.speed, math.sin(realShootAngle) * item.speed, attack) proj.isCheckNpc = true end end end end -- test if false and NetMode.current == NetMode.Client then local tp = itemJoint.transform.worldMatrix:transformVector2(self.itemStack:GetItem():GetFirePoint(0)) local effect = EffectUtils.Create(Reg.EffectID("circle"), tp.x, tp.y, 0, 0, 0, 0.2) end end end function Sword:DrawIcon(position, color, spriteExData) self:_DrawIconRotated(position, color, spriteExData) end --function Sword:Save() -- return { -- test = 123, -- word = "hello world" -- } --end -- --function Sword:Load(tagTable) -- --print(tagTable.test, tagTable.word) --end return Sword ================================================ FILE: item_ai/Torch.json ================================================ { "Torch": { "script": { "path": "Torch.lua" } } } ================================================ FILE: item_ai/Torch.lua ================================================ ---@class TC.Torch:ModItem local Torch = class("Sword", ModItem) local GPlayer = require("player.GPlayer") local modTextureID = Reg.ModTextureID("torch_fire") local modTexture = ModTextureUtils.GetData(modTextureID) local modTextureLocation = modTexture.textureLocation function Torch:GetFirePoint(player) local globalPlayer = GPlayer.GetInstance(player) local itemJoint = globalPlayer:GetHeldItemJoint() return itemJoint.transform.worldMatrix:transformVector2(self.itemStack:GetItem():GetFirePoint(0)) end function Torch:OnHeld(player) local tp = self:GetFirePoint(player) local xi = Utils.Cell(tp.x) local yi = Utils.Cell(tp.y) local lightingAlpha, r, g, b = self:GetLightingValue() LightingUtils.AddDelay(xi, yi, 20, lightingAlpha, r, g, b) if player.tickTime % 16 == 0 then EffectUtils.Create(Reg.EffectID("fire_smoke"), tp.x, tp.y, Utils.RandSym(0.25), -0.85, Utils.RandSym(0.05), Utils.RandDoubleArea(0.95, 0.5), 0.8 ) end end function Torch:OnHeldRender(player) local tp = self:GetFirePoint(player) local style = math.floor(player.tickTime / 8) % 4 local cutRect = Rect.new(style * 16, 0, 16, 16) local drawX = tp.x - 8 - MiscUtils.screenX local drawY = tp.y - 12 - MiscUtils.screenY Sprite.draw(modTextureLocation, Vector2.new(drawX, drawY), cutRect, Color.White) end function Torch:GetLightingValue() return 30, 0, 0, 0 end return Torch ================================================ FILE: item_ai/cross_bow.json ================================================ { "cross_bow": { "script": { "path": "cross_bow.lua" }, "destroyFragileBlocks": false, "crossTiles": false, "consumeItems": true, "consumeMana": false, "directHitPlayer": false, "directHitNpc": false, "hitDecreaseDurable": 0.0, "shootDecreaseDurable": 1.0 } } ================================================ FILE: item_ai/cross_bow.lua ================================================ local CrossBow = class("CrossBow", ModItem) --function CrossBow:OnShootFromPlayer(itemSlot, player, hitbox, consumeItemID, projectileID, fireX, fireY, shootSpeed, shootAngle, -- baseAttack) -- local shootTimes = itemSlot.shootTimes -- if shootTimes == 1 then -- local multishotLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("multishot")) -- shootTimes = shootTimes + multishotLevel -- end -- if shootTimes > 1 then -- baseAttack.attack = math.ceil(baseAttack.attack * 0.75) -- end -- local piercingLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("piercing")) -- for i = 1, shootTimes do -- local angle = shootAngle + Utils.RandSym(itemSlot.deviation) -- local speed = shootSpeed -- local proj = ProjectileUtils.CreateFromPlayer(player, projectileID, fireX, fireY, math.cos(angle) * speed, -- math.sin(angle) * speed, baseAttack) -- proj.isCheckPlayer = true -- proj.isCheckNpc = true -- if proj.modData:DataOf("Arrow") then -- if i == 1 and consumeItemID > 0 then -- proj.modData.attachItemID = consumeItemID -- end -- proj.modData.piercingCount = math.floor(piercingLevel * 0.5) -- end -- end -- return true --end -- --function CrossBow:OnShootFromNpc(itemSlot, npc, hitbox, consumeItemID, projectileID, fireX, fireY, shootSpeed, shootAngle, -- baseAttack) -- local shootTimes = itemSlot.shootTimes -- if shootTimes == 1 then -- local multishotLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("multishot")) -- shootTimes = shootTimes + multishotLevel -- end -- local piercingLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("piercing")) -- for i = 1, shootTimes do -- local angle = shootAngle + Utils.RandSym(itemSlot.deviation) -- local speed = shootSpeed -- local proj = ProjectileUtils.CreateFromNpc(npc, projectileID, fireX, fireY, math.cos(angle) * speed, -- math.sin(angle) * speed, baseAttack) -- proj.isCheckPlayer = true -- proj.isCheckNpc = false -- if proj.modData:DataOf("Arrow") then -- if i == 1 and consumeItemID > 0 then -- proj.modData.attachItemID = consumeItemID -- end -- proj.modData.piercingCount = math.floor(piercingLevel * 0.5) -- end -- end -- return true --end return CrossBow ================================================ FILE: item_ai/dirt.json ================================================ { "dirt": { "script": { "path": "dirt.lua" } } } ================================================ FILE: item_ai/dirt.lua ================================================ ---@class TC.Dirt:ModItem local Dirt = class("Dirt", ModItem) function Dirt:Init() --print("hello dirt! you have", self.itemStack.stackSize) end function Dirt:DrawIcon(position, color, spriteExData) local item = self.itemStack:GetItem() local texture = item.iconTextureLocation local rectSource = TextureManager.getSourceRect(texture) spriteExData.originX = rectSource.width / 2 spriteExData.originY = rectSource.height / 2 Sprite.draw(texture, position, rectSource, color, spriteExData, 0) end function Dirt:OnHeld(player) --print("hhhhh", player.name) end return Dirt ================================================ FILE: item_ai/drill.json ================================================ { "drill": { "script": { "path": "drill.lua" }, "destroyFragileBlocks": true, "crossTiles": false, "consumeItems": false, "consumeMana": false, "directHitPlayer": true, "directHitNpc": true, "hitDecreaseDurable": 0.5, "shootDecreaseDurable": 0.0 } } ================================================ FILE: item_ai/drill.lua ================================================ local Drill = class("Drill", ModItem) --local e_fire_smoke = Reg.EffectID("fire_smoke") -- --function Drill:OnUseFromPlayer(itemSlot, player, hitbox, fireX, fireY) -- if player.tickTime % 4 == 0 then -- EffectUtils.Create(e_fire_smoke, fireX, fireY, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(0.05), -- Utils.RandDoubleArea(0.5, 0.5)) -- end --end -- --function Drill:OnUseFromNpc(itemSlot, npc, hitbox, fireX, fireY) -- if npc.tickTime % 4 == 0 then -- EffectUtils.Create(e_fire_smoke, fireX, fireY, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(0.05), -- Utils.RandDoubleArea(0.5, 0.5)) -- end --end return Drill ================================================ FILE: item_ai/fire_gun.json ================================================ { "fire_gun": { "script": { "path": "Gun.lua" }, "destroyFragileBlocks": false, "crossTiles": false, "consumeItems": false, "consumeMana": false, "directHitPlayer": false, "directHitNpc": false, "hitDecreaseDurable": 0.0, "shootDecreaseDurable": 1.0 } } ================================================ FILE: item_ai/fishing_rod.json ================================================ { "fishing_rod": { "script": { "path": "fishing_rod.lua" }, "destroyFragileBlocks": false, "crossTiles": false, "consumeItems": true, "consumeMana": false, "directHitPlayer": false, "directHitNpc": false, "hitDecreaseDurable": 0.0, "shootDecreaseDurable": 0.0 } } ================================================ FILE: item_ai/fishing_rod.lua ================================================ local FishingRod = class("FishingRod", ModItem) -- TODO -- So when will blueyoshi write the code for the fishing rod? return FishingRod ================================================ FILE: item_ai/laser_gun.json ================================================ { "laser_gun": { "script": { "path": "Gun.lua" }, "destroyFragileBlocks": false, "crossTiles": false, "consumeItems": false, "consumeMana": false, "directHitPlayer": false, "directHitNpc": false, "hitDecreaseDurable": 0.0, "shootDecreaseDurable": 1.0 } } ================================================ FILE: item_ai/magic_sword.json ================================================ { "magic_sword": { "script": { "path": "Sword.lua" }, "destroyFragileBlocks": true, "crossTiles": false, "consumeItems": false, "consumeMana": true, "directHitPlayer": true, "directHitNpc": true, "hitDecreaseDurable": 0.5, "shootDecreaseDurable": 0.0 } } ================================================ FILE: item_ai/rocket_launcher.json ================================================ { "rocket_launcher": { "script": { "path": "Gun.lua" }, "destroyFragileBlocks": false, "crossTiles": false, "consumeItems": true, "consumeMana": false, "directHitPlayer": false, "directHitNpc": false, "hitDecreaseDurable": 0.0, "shootDecreaseDurable": 1.0 } } ================================================ FILE: item_ai/saw.json ================================================ { "saw": { "script": { "path": "drill.lua" }, "destroyFragileBlocks": true, "crossTiles": false, "consumeItems": false, "consumeMana": false, "directHitPlayer": true, "directHitNpc": true, "hitDecreaseDurable": 0.5, "shootDecreaseDurable": 0.0 } } ================================================ FILE: item_ai/swordA.json ================================================ { "sword": { "script": { "path": "swordA.lua" }, "destroyFragileBlocks": true, "crossTiles": false, "consumeItems": false, "consumeMana": false, "directHitPlayer": true, "directHitNpc": true, "hitDecreaseDurable": 0.5, "shootDecreaseDurable": 0.0 } } ================================================ FILE: item_ai/swordA.lua ================================================ local Sword = class("Sword", ModItem) --function Sword:CheckHitNpc(itemSlot, npcTarget, hitbox, fireX, fireY, hitAngle, baseAttack) -- -- check enchantments -- local arthropodsLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("bane_of_arthropods")) -- local fireAspectLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("fire_aspect")) -- local smiteLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("smite")) -- -- if fireAspectLevel > 0 then -- npcTarget:AddBuff(Reg.BuffID("fire"), fireAspectLevel * 60) -- end -- if arthropodsLevel > 0 and npcTarget.type == NPC_TYPE_ARTHROPODS then -- baseAttack.attack = baseAttack.attack + arthropodsLevel * 2 -- end -- if smiteLevel > 0 and npcTarget.type == NPC_TYPE_SMITE then -- baseAttack.attack = baseAttack.attack + smiteLevel * 2 -- end -- -- return true --end -- --function Sword:CheckHitPlayer(itemSlot, playerTarget, hitbox, fireX, fireY, hitAngle, baseAttack) -- -- check enchantments -- local fireAspectLevel = itemSlot:GetEnchantmentLevel(Reg.EnchantmentID("fire_aspect")) -- if fireAspectLevel > 0 then -- playerTarget:AddBuff(Reg.BuffID("fire"), fireAspectLevel * 60) -- end -- return true --end return Sword ================================================ FILE: items/accessory/blue_talisman.json ================================================ { "blue_talisman": { "type": "MATERIALS", "ai": "BlueTalisman", "iconTextureData": "blue_talisman.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/accessory/gold_talisman.json ================================================ { "gold_talisman": { "type": "MATERIALS", "iconTextureData": "gold_talisman.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/accessory/heart_talisman.json ================================================ { "heart_talisman": { "type": "MATERIALS", "ai": "RedTalisman", "iconTextureData": "heart_talisman.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/accessory/lava_necklace.json ================================================ { "lava_necklace": { "type": "MATERIALS", "iconTextureData": "lava_necklace.png", "ai": "LavaNecklace", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/accessory/lighting_talisman.json ================================================ { "lighting_talisman": { "type": "MATERIALS", "ai": "LightingTalisman", "iconTextureData": "lighting_talisman.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/accessory/rocket_boost.json ================================================ { "rocket_boost": { "type": "MATERIALS", "ai": "RocketBoost", "iconTextureData": "rocket_boost.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/armors/ancient/ancient_chestplate.json ================================================ { "ancient_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate14.png", "textureData": "body14.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 8, "durable": 3160 } } ================================================ FILE: items/armors/ancient/ancient_helmet.json ================================================ { "ancient_helmet": { "type": "TOOLS", "iconTextureData": "ihat14.png", "textureData": "hat14.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 6, "durable": 3160 } } ================================================ FILE: items/armors/ancient/ancient_leggings.json ================================================ { "ancient_leggings": { "type": "TOOLS", "iconTextureData": "leggings14.png", "textureData": "leg14.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 7, "durable": 3160 } } ================================================ FILE: items/armors/bronze/bronze_chestplate.json ================================================ { "bronze_chestplate": { "type": "TOOLS", "iconTextureData": "bronze_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 5, "durable": 624 } } ================================================ FILE: items/armors/bronze/bronze_helmet.json ================================================ { "bronze_helmet": { "type": "TOOLS", "iconTextureData": "bronze_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 3, "durable": 624 } } ================================================ FILE: items/armors/bronze/bronze_leggings.json ================================================ { "bronze_leggings": { "type": "TOOLS", "iconTextureData": "bronze_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 4, "durable": 624 } } ================================================ FILE: items/armors/copper/copper_chestplate.json ================================================ { "copper_chestplate": { "type": "TOOLS", "iconTextureData": "copper_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 3, "durable": 412 } } ================================================ FILE: items/armors/copper/copper_helmet.json ================================================ { "copper_helmet": { "type": "TOOLS", "iconTextureData": "copper_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 2, "durable": 412 } } ================================================ FILE: items/armors/copper/copper_leggings.json ================================================ { "copper_leggings": { "type": "TOOLS", "iconTextureData": "copper_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 2, "durable": 412 } } ================================================ FILE: items/armors/diamond/diamond_chestplate.json ================================================ { "diamond_chestplate": { "type": "TOOLS", "iconTextureData": "diamond_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "subGroup": "SUB_GROUP_DIAMOND", "toolType": "CHESTPLATE", "isArmor": true, "defense": 7, "durable": 1552 } } ================================================ FILE: items/armors/diamond/diamond_helmet.json ================================================ { "diamond_helmet": { "type": "TOOLS", "iconTextureData": "diamond_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "subGroup": "SUB_GROUP_DIAMOND", "toolType": "HELMET", "isArmor": true, "defense": 5, "durable": 1552 } } ================================================ FILE: items/armors/diamond/diamond_leggings.json ================================================ { "diamond_leggings": { "type": "TOOLS", "iconTextureData": "diamond_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "subGroup": "SUB_GROUP_DIAMOND", "toolType": "LEGGINGS", "isArmor": true, "defense": 6, "durable": 1552 } } ================================================ FILE: items/armors/fine_tin/fine_tin_chestplate.json ================================================ { "fine_tin_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate4.png", "textureData": "body4.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 5, "durable": 788 } } ================================================ FILE: items/armors/fine_tin/fine_tin_helmet.json ================================================ { "fine_tin_helmet": { "type": "TOOLS", "iconTextureData": "ihat4.png", "textureData": "hat4.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 3, "durable": 788 } } ================================================ FILE: items/armors/fine_tin/fine_tin_leggings.json ================================================ { "fine_tin_leggings": { "type": "TOOLS", "iconTextureData": "leggings4.png", "textureData": "leg4.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 4, "durable": 788 } } ================================================ FILE: items/armors/flesh/flesh_chestplate.json ================================================ { "flesh_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate7.png", "textureData": "body7.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 6, "durable": 1560 } } ================================================ FILE: items/armors/flesh/flesh_helmet.json ================================================ { "flesh_helmet": { "type": "TOOLS", "iconTextureData": "ihat7.png", "textureData": "hat7.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 4, "durable": 1560 } } ================================================ FILE: items/armors/flesh/flesh_leggings.json ================================================ { "flesh_leggings": { "type": "TOOLS", "iconTextureData": "leggings7.png", "textureData": "leg7.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 5, "durable": 1560 } } ================================================ FILE: items/armors/gold/golden_chestplate.json ================================================ { "golden_chestplate": { "type": "TOOLS", "iconTextureData": "golden_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 6, "durable": 788 } } ================================================ FILE: items/armors/gold/golden_helmet.json ================================================ { "golden_helmet": { "type": "TOOLS", "iconTextureData": "golden_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 4, "durable": 788 } } ================================================ FILE: items/armors/gold/golden_leggings.json ================================================ { "golden_leggings": { "type": "TOOLS", "iconTextureData": "golden_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 5, "durable": 788 } } ================================================ FILE: items/armors/iron/iron_chestplate.json ================================================ { "iron_chestplate": { "type": "TOOLS", "iconTextureData": "iron_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 4, "durable": 500 } } ================================================ FILE: items/armors/iron/iron_helmet.json ================================================ { "iron_helmet": { "type": "TOOLS", "iconTextureData": "iron_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 2, "durable": 500 } } ================================================ FILE: items/armors/iron/iron_leggings.json ================================================ { "iron_leggings": { "type": "TOOLS", "iconTextureData": "iron_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 3, "durable": 500 } } ================================================ FILE: items/armors/knight/knight_chestplate.json ================================================ { "knight_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate5.png", "textureData": "body5.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 6, "durable": 1552 } } ================================================ FILE: items/armors/knight/knight_helmet.json ================================================ { "knight_helmet": { "type": "TOOLS", "iconTextureData": "ihat5.png", "textureData": "hat5.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 4, "durable": 1552 } } ================================================ FILE: items/armors/knight/knight_leggings.json ================================================ { "knight_leggings": { "type": "TOOLS", "iconTextureData": "leggings5.png", "textureData": "leg5.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 5, "durable": 1552 } } ================================================ FILE: items/armors/lava/lava_chestplate.json ================================================ { "lava_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate8.png", "textureData": "body8.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 6, "durable": 1552 } } ================================================ FILE: items/armors/lava/lava_helmet.json ================================================ { "lava_helmet": { "type": "TOOLS", "iconTextureData": "ihat8.png", "textureData": "hat8.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 4, "durable": 1552 } } ================================================ FILE: items/armors/lava/lava_leggings.json ================================================ { "lava_leggings": { "type": "TOOLS", "iconTextureData": "leggings8.png", "textureData": "leg8.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 5, "durable": 1552 } } ================================================ FILE: items/armors/lead/lead_chestplate.json ================================================ { "lead_chestplate": { "type": "TOOLS", "iconTextureData": "lead_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 4, "durable": 500 } } ================================================ FILE: items/armors/lead/lead_helmet.json ================================================ { "lead_helmet": { "type": "TOOLS", "iconTextureData": "lead_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 3, "durable": 500 } } ================================================ FILE: items/armors/lead/lead_leggings.json ================================================ { "lead_leggings": { "type": "TOOLS", "iconTextureData": "lead_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 3, "durable": 500 } } ================================================ FILE: items/armors/leather/leather_chestplate.json ================================================ { "leather_chestplate": { "type": "TOOLS", "iconTextureData": "leather_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 2, "durable": 64 } } ================================================ FILE: items/armors/leather/leather_helmet.json ================================================ { "leather_helmet": { "type": "TOOLS", "iconTextureData": "leather_helmet_icon.png", "textureData": "hat.png", "showHair": true, "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 1, "durable": 64 } } ================================================ FILE: items/armors/leather/leather_leggings.json ================================================ { "leather_leggings": { "type": "TOOLS", "iconTextureData": "leather_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 1, "durable": 64 } } ================================================ FILE: items/armors/magic_gold/magic_gold_chestplate.json ================================================ { "magic_gold_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate2.png", "textureData": "body2.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 6, "durable": 1440 } } ================================================ FILE: items/armors/magic_gold/magic_gold_helmet.json ================================================ { "magic_gold_helmet": { "type": "TOOLS", "iconTextureData": "ihat2.png", "textureData": "hat2.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 4, "durable": 1440 } } ================================================ FILE: items/armors/magic_gold/magic_gold_leggings.json ================================================ { "magic_gold_leggings": { "type": "TOOLS", "iconTextureData": "leggings2.png", "textureData": "leg2.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 5, "durable": 1440 } } ================================================ FILE: items/armors/magic_shadow/magic_shadow_chestplate.json ================================================ { "magic_shadow_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate11.png", "textureData": "body11.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 6, "durable": 2022 } } ================================================ FILE: items/armors/magic_shadow/magic_shadow_helmet.json ================================================ { "magic_shadow_helmet": { "type": "TOOLS", "iconTextureData": "ihat11.png", "textureData": "hat11.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 4, "durable": 2022 } } ================================================ FILE: items/armors/magic_shadow/magic_shadow_leggings.json ================================================ { "magic_shadow_leggings": { "type": "TOOLS", "iconTextureData": "leggings11.png", "textureData": "leg11.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 5, "durable": 2022 } } ================================================ FILE: items/armors/magic_silver/magic_silver_chestplate.json ================================================ { "magic_silver_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate1.png", "textureData": "body1.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 6, "durable": 1440 } } ================================================ FILE: items/armors/magic_silver/magic_silver_helmet.json ================================================ { "magic_silver_helmet": { "type": "TOOLS", "iconTextureData": "ihat1.png", "textureData": "hat1.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 4, "durable": 1440 } } ================================================ FILE: items/armors/magic_silver/magic_silver_leggings.json ================================================ { "magic_silver_leggings": { "type": "TOOLS", "iconTextureData": "leggings1.png", "textureData": "leg1.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 5, "durable": 1440 } } ================================================ FILE: items/armors/nether/nether_chestplate.json ================================================ { "nether_chestplate": { "type": "TOOLS", "iconTextureData": "nether_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "subGroup": "SUB_GROUP_NETHERITE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 7, "durable": 2020, "antiLava": true } } ================================================ FILE: items/armors/nether/nether_helmet.json ================================================ { "nether_helmet": { "type": "TOOLS", "iconTextureData": "nether_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "subGroup": "SUB_GROUP_NETHERITE", "toolType": "HELMET", "isArmor": true, "defense": 5, "durable": 2020, "antiLava": true } } ================================================ FILE: items/armors/nether/nether_leggings.json ================================================ { "nether_leggings": { "type": "TOOLS", "iconTextureData": "nether_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "subGroup": "SUB_GROUP_NETHERITE", "toolType": "LEGGINGS", "isArmor": true, "defense": 6, "durable": 2020, "antiLava": true } } ================================================ FILE: items/armors/pumpkin/pumpkin_helmet.json ================================================ { "pumpkin_helmet": { "type": "TOOLS", "iconTextureData": "pumpkin_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 1, "durable": 64 } } ================================================ FILE: items/armors/shadow/shadow_chestplate.json ================================================ { "shadow_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate3.png", "textureData": "body3.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 6, "durable": 788 } } ================================================ FILE: items/armors/shadow/shadow_helmet.json ================================================ { "shadow_helmet": { "type": "TOOLS", "iconTextureData": "ihat3.png", "textureData": "hat3.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 4, "durable": 788 } } ================================================ FILE: items/armors/shadow/shadow_leggings.json ================================================ { "shadow_leggings": { "type": "TOOLS", "iconTextureData": "leggings3.png", "textureData": "leg3.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 5, "durable": 788 } } ================================================ FILE: items/armors/silver/silver_chestplate.json ================================================ { "silver_chestplate": { "type": "TOOLS", "iconTextureData": "silver_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 6, "durable": 788 } } ================================================ FILE: items/armors/silver/silver_helmet.json ================================================ { "silver_helmet": { "type": "TOOLS", "iconTextureData": "silver_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 4, "durable": 788 } } ================================================ FILE: items/armors/silver/silver_leggings.json ================================================ { "silver_leggings": { "type": "TOOLS", "iconTextureData": "silver_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 5, "durable": 788 } } ================================================ FILE: items/armors/star/star_chestplate.json ================================================ { "star_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate6.png", "textureData": "body6.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 6, "durable": 3160 } } ================================================ FILE: items/armors/star/star_helmet.json ================================================ { "star_helmet": { "type": "TOOLS", "iconTextureData": "ihat6.png", "textureData": "hat6.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 4, "durable": 3160 } } ================================================ FILE: items/armors/star/star_leggings.json ================================================ { "star_leggings": { "type": "TOOLS", "iconTextureData": "leggings6.png", "textureData": "leg6.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 5, "durable": 3160 } } ================================================ FILE: items/armors/steel/steel_chestplate.json ================================================ { "steel_chestplate": { "type": "TOOLS", "iconTextureData": "steel_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 5, "durable": 624 } } ================================================ FILE: items/armors/steel/steel_helmet.json ================================================ { "steel_helmet": { "type": "TOOLS", "iconTextureData": "steel_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 3, "durable": 624 } } ================================================ FILE: items/armors/steel/steel_leggings.json ================================================ { "steel_leggings": { "type": "TOOLS", "iconTextureData": "steel_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 4, "durable": 624 } } ================================================ FILE: items/armors/super_diamond/super_diamond_chestplate.json ================================================ { "super_diamond_chestplate": { "type": "TOOLS", "iconTextureData": "chestplate10.png", "textureData": "body10.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 7, "durable": 1552 } } ================================================ FILE: items/armors/super_diamond/super_diamond_helmet.json ================================================ { "super_diamond_helmet": { "type": "TOOLS", "iconTextureData": "ihat10.png", "textureData": "hat10.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 5, "durable": 1552 } } ================================================ FILE: items/armors/super_diamond/super_diamond_leggings.json ================================================ { "super_diamond_leggings": { "type": "TOOLS", "iconTextureData": "leggings10.png", "textureData": "leg10.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 6, "durable": 1552 } } ================================================ FILE: items/armors/tin/tin_chestplate.json ================================================ { "tin_chestplate": { "type": "TOOLS", "iconTextureData": "tin_chestplate_icon.png", "textureData": "body.png", "group": "GROUP_CHESTPLATE", "toolType": "CHESTPLATE", "isArmor": true, "defense": 3, "durable": 412 } } ================================================ FILE: items/armors/tin/tin_helmet.json ================================================ { "tin_helmet": { "type": "TOOLS", "iconTextureData": "tin_helmet_icon.png", "textureData": "hat.png", "group": "GROUP_HELMET", "toolType": "HELMET", "isArmor": true, "defense": 2, "durable": 412 } } ================================================ FILE: items/armors/tin/tin_leggings.json ================================================ { "tin_leggings": { "type": "TOOLS", "iconTextureData": "tin_leggings_icon.png", "textureData": "leg.png", "group": "GROUP_LEGGINGS", "toolType": "LEGGINGS", "isArmor": true, "defense": 2, "durable": 412 } } ================================================ FILE: items/arrows/blood_arrow.json ================================================ { "blood_arrow": { "type": "PROJECTILES", "iconTextureData": "blood_arrow_icon.png", "group": "GROUP_ARROW", "ammo": "arrow", "ammoLevel": 3, "projectileId": "blood_arrow", "speed": 1.0, "shootable": true, "damage": 1, "knockBack": 1 } } ================================================ FILE: items/arrows/blue_arrow.json ================================================ { "blue_arrow": { "type": "PROJECTILES", "iconTextureData": "blue_arrow.png", "group": "GROUP_ARROW", "ammo": "arrow", "ammoLevel": 6, "projectileId": "blue_arrow", "speed": 2.0, "shootable": true, "damage": 3, "knockBack": 1 } } ================================================ FILE: items/arrows/ice_arrow.json ================================================ { "ice_arrow": { "type": "PROJECTILES", "iconTextureData": "ice_arrow_icon.png", "group": "GROUP_ARROW", "ammo": "arrow", "ammoLevel": 4, "projectileId": "ice_arrow", "speed": 2.0, "shootable": true, "damage": 1, "knockBack": 1 } } ================================================ FILE: items/arrows/lighting_arrow.json ================================================ { "lighting_arrow": { "type": "PROJECTILES", "iconTextureData": "lighting_arrow_icon.png", "group": "GROUP_ARROW", "ammo": "arrow", "ammoLevel": 1, "projectileId": "lighting_arrow", "speed": 1.0, "shootable": true, "damage": 2, "knockBack": 1 } } ================================================ FILE: items/arrows/star_arrow.json ================================================ { "star_arrow": { "type": "PROJECTILES", "iconTextureData": "star_arrow_icon.png", "group": "GROUP_ARROW", "ammo": "arrow", "ammoLevel": 2, "projectileId": "star_arrow", "speed": 1.0, "shootable": true, "damage": 2, "knockBack": 1 } } ================================================ FILE: items/arrows/sword_arrow.json ================================================ { "sword_arrow": { "type": "PROJECTILES", "iconTextureData": "sword_arrow_icon.png", "group": "GROUP_ARROW", "ammo": "arrow", "ammoLevel": 5, "projectileId": "sword_arrow", "speed": 0.0, "shootable": true, "damage": 1, "knockBack": 1 } } ================================================ FILE: items/arrows/wooden_arrow.json ================================================ { "wooden_arrow": { "type": "PROJECTILES", "iconTextureData": "wooden_arrow_icon.png", "group": "GROUP_ARROW", "ammo": "arrow", "ammoLevel": 0, "projectileId": "wooden_arrow", "speed": 0.0, "shootable": true, "damage": 2, "knockBack": 1 } } ================================================ FILE: items/axes/bronze_axe.json ================================================ { "bronze_axe": { "type": "TOOLS", "iconTextureData": "bronze_axe_entity.png", "textureData": "bronze_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "GOLD", "efficiency": 3.5, "ai": "Axe", "coldTime": 18, "entityWidth": 22, "entityHeight": 40, "handX": 8, "handY": 32, "holdType": "NORMAL", "durable": 1248, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/axes/copper_axe.json ================================================ { "copper_axe": { "type": "TOOLS", "iconTextureData": "copper_axe_entity.png", "textureData": "copper_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "IRON", "efficiency": 2.5, "ai": "Axe", "coldTime": 18, "entityWidth": 22, "entityHeight": 40, "handX": 8, "handY": 32, "holdType": "NORMAL", "durable": 824, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/axes/diamond_axe.json ================================================ { "diamond_axe": { "type": "TOOLS", "iconTextureData": "diamond_axe_entity.png", "textureData": "diamond_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "DIAMOND", "efficiency": 5.0, "ai": "Axe", "coldTime": 16, "entityWidth": 22, "entityHeight": 40, "handX": 8, "handY": 32, "holdType": "NORMAL", "durable": 4040, "damage": 5, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/axes/golden_axe.json ================================================ { "golden_axe": { "type": "TOOLS", "iconTextureData": "golden_axe_entity.png", "textureData": "golden_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "GOLD", "efficiency": 4.0, "ai": "Axe", "coldTime": 18, "entityWidth": 22, "entityHeight": 40, "handX": 8, "handY": 32, "holdType": "NORMAL", "durable": 1856, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/axes/grass_axe.json ================================================ { "grass_axe": { "type": "TOOLS", "iconTextureData": "grass_axe_entity.png", "textureData": "grass_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "GRASS", "efficiency": 1.0, "ai": "Axe", "coldTime": 20, "entityWidth": 20, "entityHeight": 30, "handX": 5, "handY": 26, "holdType": "NORMAL", "durable": 128, "damage": 1, "knockBack": 1, "crit": 0, "isNoBreaking": true, "enchantments": [ { "id": "phyton", "level": 1 } ] } } ================================================ FILE: items/axes/iron_axe.json ================================================ { "iron_axe": { "type": "TOOLS", "iconTextureData": "iron_axe_entity.png", "textureData": "iron_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "IRON", "efficiency": 3.0, "ai": "Axe", "coldTime": 18, "entityWidth": 20, "entityHeight": 36, "handX": 8, "handY": 32, "holdType": "NORMAL", "durable": 1000, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/axes/lead_axe.json ================================================ { "lead_axe": { "type": "TOOLS", "iconTextureData": "lead_axe_entity.png", "textureData": "lead_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "IRON", "efficiency": 3.0, "ai": "Axe", "coldTime": 18, "entityWidth": 22, "entityHeight": 40, "handX": 8, "handY": 32, "holdType": "NORMAL", "durable": 1000, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/axes/nether_axe.json ================================================ { "nether_axe": { "type": "TOOLS", "iconTextureData": "nether_axe_entity.png", "textureData": "nether_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "DIAMOND", "efficiency": 5.5, "ai": "Axe", "coldTime": 16, "entityWidth": 22, "entityHeight": 40, "handX": 8, "handY": 32, "holdType": "NORMAL", "durable": 4896, "damage": 5, "knockBack": 1, "crit": 0, "antiLava": true } } ================================================ FILE: items/axes/silver_axe.json ================================================ { "silver_axe": { "type": "TOOLS", "iconTextureData": "silver_axe_entity.png", "textureData": "silver_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "GOLD", "efficiency": 4.0, "ai": "Axe", "coldTime": 18, "entityWidth": 22, "entityHeight": 40, "handX": 8, "handY": 32, "holdType": "NORMAL", "durable": 1856, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/axes/steel_axe.json ================================================ { "steel_axe": { "type": "TOOLS", "iconTextureData": "steel_axe_entity.png", "textureData": "steel_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "GOLD", "efficiency": 3.5, "ai": "Axe", "coldTime": 18, "entityWidth": 22, "entityHeight": 40, "handX": 8, "handY": 32, "holdType": "NORMAL", "durable": 1248, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/axes/stone_axe.json ================================================ { "stone_axe": { "type": "TOOLS", "iconTextureData": "stone_axe_entity.png", "textureData": "stone_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "STONE", "efficiency": 2.0, "ai": "Axe", "coldTime": 20, "entityWidth": 20, "entityHeight": 36, "handX": 7, "handY": 28, "holdType": "NORMAL", "durable": 524, "damage": 3, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/axes/tin_axe.json ================================================ { "tin_axe": { "type": "TOOLS", "iconTextureData": "tin_axe_entity.png", "textureData": "tin_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "IRON", "efficiency": 2.5, "ai": "Axe", "coldTime": 18, "entityWidth": 22, "entityHeight": 40, "handX": 8, "handY": 32, "holdType": "NORMAL", "durable": 824, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/axes/wooden_axe.json ================================================ { "wooden_axe": { "type": "TOOLS", "iconTextureData": "wooden_axe_entity.png", "textureData": "wooden_axe_entity.png", "group": "GROUP_AXE", "toolType": "AXE", "toolGrade": "WOOD", "efficiency": 1.5, "ai": "Axe", "coldTime": 20, "entityWidth": 18, "entityHeight": 30, "handX": 5, "handY": 26, "holdType": "NORMAL", "durable": 280, "damage": 2, "knockBack": 1, "crit": 0, "fuelTime": 40 } } ================================================ FILE: items/bombs/bomb.json ================================================ { "bomb": { "type": "PROJECTILES", "iconTextureData": "bomb_icon.png", "group": "GROUP_BOMB", "projectileId": "bomb", "speed": 5.0, "canThrow": true, "damage": 12, "knockBack": 8, "coldTime": 180, "shootable": true } } ================================================ FILE: items/bombs/glow_bomb.json ================================================ { "glow_bomb": { "type": "PROJECTILES", "iconTextureData": "glow_bomb_icon.png", "group": "GROUP_BOMB", "projectileId": "glow_bomb", "speed": 6.0, "canThrow": true, "damage": 3, "knockBack": 8, "coldTime": 400, "shootable": true } } ================================================ FILE: items/bombs/grenade.json ================================================ { "grenade": { "type": "PROJECTILES", "iconTextureData": "grenade_icon.png", "group": "GROUP_BOMB", "projectileId": "grenade", "speed": 6.0, "canThrow": true, "damage": 5, "knockBack": 5, "coldTime": 180, "shootable": true } } ================================================ FILE: items/boomerangs/boomerang.json ================================================ { "boomerang": { "type": "TOOLS", "iconTextureData": "boomerang_icon.png", "group": "GROUP_BOOMERANG", "toolType": "BOOMERANG", "projectileId": "boomerang", "speed": 8.0, "damage": 7, "knockBack": 8, "coldTime": 40, "durable": 256, "canThrow": true, "attachThrowable": true } } ================================================ FILE: items/boomerangs/fire_boomerang.json ================================================ { "fire_boomerang": { "type": "TOOLS", "iconTextureData": "fire_boomerang_icon.png", "group": "GROUP_BOOMERANG", "toolType": "BOOMERANG", "projectileId": "fire_boomerang", "speed": 12.0, "damage": 5, "knockBack": 6, "coldTime": 20, "durable": 256, "canThrow": true, "attachThrowable": true } } ================================================ FILE: items/boomerangs/wooden_boomerang.json ================================================ { "wooden_boomerang": { "type": "TOOLS", "iconTextureData": "wooden_boomerang_icon.png", "group": "GROUP_BOOMERANG", "toolType": "BOOMERANG", "projectileId": "wooden_boomerang", "speed": 8.0, "damage": 5, "knockBack": 6, "coldTime": 40, "canThrow": true, "durable": 64, "attachThrowable": true, "fuelTime": 40 } } ================================================ FILE: items/bows/blood_bow.json ================================================ { "blood_bow": { "type": "TOOLS", "iconTextureData": "blood_bow_icon.png", "textureData": "blood_bow_entity.png", "group": "GROUP_BOW", "toolType": "BOW", "ai": "Bow", "ammo": "arrow", "entityWidth": 22, "entityHeight": 36, "handX": 12, "handY": 18, "firePoints": [[22,18]], "noConsumeChance": 0.0, "speed": 14.0, "deviation": 0.05, "shootTimes": 1, "ammoLevel": 3, "shootProjectileId": "blood_arrow", "usePosture": 1, "useSound": "bow", "coldTime": 50, "holdType": "NORMAL", "twoHands": true, "durable": 512, "damage": 14, "knockBack": 5, "crit": 3 } } ================================================ FILE: items/bows/blue_shot_bow.json ================================================ { "blue_shot_bow": { "type": "TOOLS", "iconTextureData": "blue_shot_bow.png", "textureData": "blue_shot_bow.png", "group": "GROUP_CROSS_BOW", "toolType": "CROSS_BOW", "ai": "Gun", "ammo": "arrow", "entityWidth": 60, "entityHeight": 28, "handX": 10, "handY": 20, "firePoints": [[60,12]], "noConsumeChance": 0.60, "speed": 12.0, "deviation": 0.05, "shootTimes": 3, "ammoLevel": 6, "shootProjectileId": "blue_arrow", "usePosture": 0, "useSound": "bow", "coldTime": 30, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": false, "durable": 1000, "damage": 13, "knockBack": 5, "crit": 3 } } ================================================ FILE: items/bows/blue_stone_bow.json ================================================ { "blue_stone_bow": { "type": "TOOLS", "iconTextureData": "blue_stone_bow_icon.png", "textureData": "blue_stone_bow_entity.png", "group": "GROUP_BOW", "toolType": "BOW", "ai": "Bow", "ammo": "arrow", "entityWidth": 20, "entityHeight": 32, "handX": 11, "handY": 16, "firePoints": [[20,16]], "noConsumeChance": 0.0, "speed": 16.0, "deviation": 0.05, "shootTimes": 1, "ammoLevel": 0, "shootProjectileId": "wooden_arrow", "usePosture": 1, "useSound": "bow", "coldTime": 45, "holdType": "NORMAL", "twoHands": true, "durable": 1024, "damage": 15, "knockBack": 5, "crit": 3 } } ================================================ FILE: items/bows/chast_bow.json ================================================ { "chast_bow": { "type": "TOOLS", "iconTextureData": "chast_bow_icon.png", "textureData": "chast_bow_entity.png", "group": "GROUP_BOW", "toolType": "BOW", "ai": "Bow", "ammo": "arrow", "entityWidth": 20, "entityHeight": 42, "handX": 8, "handY": 24, "firePoints": [[20,21]], "noConsumeChance": 0.0, "speed": 8.0, "deviation": 0.05, "shootTimes": 1, "ammoLevel": 5, "shootProjectileId": "sword_arrow", "usePosture": 1, "useSound": "bow", "coldTime": 50, "holdType": "NORMAL", "twoHands": true, "durable": 1024, "damage": 11, "knockBack": 5, "crit": 3 } } ================================================ FILE: items/bows/cross_bow.json ================================================ { "cross_bow": { "type": "TOOLS", "iconTextureData": "cross_bow_icon.png", "textureData": "cross_bow_entity.png", "group": "GROUP_CROSS_BOW", "toolType": "CROSS_BOW", "ai": "Bow", "ammo": "arrow", "entityWidth": 48, "entityHeight": 18, "handX": 12, "handY": 14, "firePoints": [[48,8]], "noConsumeChance": 0.0, "speed": 12.0, "deviation": 0.06, "shootTimes": 1, "ammoLevel": 0, "shootProjectileId": "wooden_arrow", "usePosture": 0, "useSound": "bow", "coldTime": 32, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": false, "durable": 1000, "damage": 14, "knockBack": 5, "crit": 3 } } ================================================ FILE: items/bows/curse_bow.json ================================================ { "curse_bow": { "type": "TOOLS", "iconTextureData": "curse_bow.png", "textureData": "curse_bow.png", "group": "GROUP_BOW", "toolType": "BOW", "ai": "InfBow", "entityWidth": 24, "entityHeight": 36, "handX": 10, "handY": 18, "firePoints": [[24,18]], "noConsumeChance": 0.0, "speed": 8.0, "deviation": 0.05, "shootTimes": 3, "shootProjectileId": "cursed_arrow", "usePosture": 0, "useSound": "bow", "coldTime": 30, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": false, "damage": 8, "knockBack": 3, "crit": 3, "consumeMana": 8 } } ================================================ FILE: items/bows/ice_bow.json ================================================ { "ice_bow": { "type": "TOOLS", "iconTextureData": "ice_bow_icon.png", "textureData": "ice_bow_entity.png", "group": "GROUP_BOW", "toolType": "BOW", "ai": "Bow", "ammo": "arrow", "entityWidth": 18, "entityHeight": 36, "handX": 8, "handY": 18, "firePoints": [[18,18]], "noConsumeChance": 0.0, "speed": 14.0, "deviation": 0.05, "shootTimes": 1, "ammoLevel": 4, "shootProjectileId": "ice_arrow", "usePosture": 1, "useSound": "bow", "coldTime": 50, "holdType": "NORMAL", "twoHands": true, "durable": 866, "damage": 11, "knockBack": 5, "crit": 3 } } ================================================ FILE: items/bows/lighting_bow.json ================================================ { "lighting_bow": { "type": "TOOLS", "iconTextureData": "lighting_bow_icon.png", "textureData": "lighting_bow_entity.png", "group": "GROUP_BOW", "toolType": "BOW", "ai": "Bow", "ammo": "arrow", "entityWidth": 14, "entityHeight": 40, "handX": 8, "handY": 20, "firePoints": [[14,20]], "noConsumeChance": 0.0, "speed": 12.0, "deviation": 0.05, "shootTimes": 1, "ammoLevel": 1, "shootProjectileId": "lighting_arrow", "usePosture": 1, "useSound": "bow", "coldTime": 55, "holdType": "NORMAL", "twoHands": true, "durable": 368, "damage": 14, "knockBack": 5, "crit": 3 } } ================================================ FILE: items/bows/shot_bow.json ================================================ { "shot_bow": { "type": "TOOLS", "iconTextureData": "shot_bow_icon.png", "textureData": "shot_bow_entity.png", "group": "GROUP_CROSS_BOW", "toolType": "CROSS_BOW", "ai": "Bow", "ammo": "arrow", "entityWidth": 60, "entityHeight": 28, "handX": 14, "handY": 22, "firePoints": [[60,12]], "noConsumeChance": 0.0, "speed": 12.0, "deviation": 0.2, "shootTimes": 3, "ammoLevel": 0, "shootProjectileId": "wooden_arrow", "usePosture": 0, "useSound": "bow", "coldTime": 54, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": false, "durable": 1000, "damage": 13, "knockBack": 5, "crit": 3 } } ================================================ FILE: items/bows/super_cross_bow.json ================================================ { "super_cross_bow": { "type": "TOOLS", "iconTextureData": "super_cross_bow_icon.png", "textureData": "super_cross_bow_entity.png", "group": "GROUP_CROSS_BOW", "toolType": "CROSS_BOW", "ai": "Bow", "ammo": "arrow", "entityWidth": 48, "entityHeight": 28, "handX": 14, "handY": 24, "firePoints": [[48,12]], "noConsumeChance": 0.0, "speed": 14.0, "deviation": 0.06, "shootTimes": 1, "ammoLevel": 0, "shootProjectileId": "wooden_arrow", "usePosture": 0, "useSound": "bow", "coldTime": 24, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": false, "durable": 1000, "damage": 15, "knockBack": 5, "crit": 6 } } ================================================ FILE: items/bows/super_fire_shot_bow.json ================================================ { "super_fire_shot_bow": { "type": "TOOLS", "iconTextureData": "super_fire_shot_bow.png", "textureData": "super_fire_shot_bow.png", "group": "GROUP_CROSS_BOW", "toolType": "CROSS_BOW", "ai": "Gun", "ammo": "arrow", "entityWidth": 60, "entityHeight": 28, "handX": 10, "handY": 20, "firePoints": [[60,12]], "noConsumeChance": 0.0, "speed": 16.0, "deviation": 0.05, "shootTimes": 3, "ammoLevel": 0, "shootProjectileId": "fire_arrow", "usePosture": 0, "useSound": "bow", "coldTime": 40, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": false, "durable": 1000, "damage": 13, "knockBack": 5, "crit": 3 } } ================================================ FILE: items/bows/super_spike_shot_bow.json ================================================ { "super_spike_shot_bow": { "type": "TOOLS", "iconTextureData": "super_spike_shot_bow.png", "textureData": "super_spike_shot_bow.png", "group": "GROUP_CROSS_BOW", "toolType": "CROSS_BOW", "ai": "Gun", "ammo": "arrow", "entityWidth": 60, "entityHeight": 28, "handX": 10, "handY": 20, "firePoints": [[60,12]], "noConsumeChance": 0.0, "speed": 16.0, "deviation": 0.05, "shootTimes": 3, "ammoLevel": 0, "shootProjectileId": "spike", "usePosture": 0, "useSound": "bow", "coldTime": 40, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": false, "durable": 1000, "damage": 13, "knockBack": 5, "crit": 3 } } ================================================ FILE: items/bows/wooden_bow.json ================================================ { "wooden_bow": { "type": "TOOLS", "iconTextureData": "wooden_bow_icon.png", "textureData": "wooden_bow_entity.png", "group": "GROUP_BOW", "toolType": "BOW", "ai": "Bow", "ammo": "arrow", "entityWidth": 16, "entityHeight": 32, "handX": 8, "handY": 15, "firePoints": [[16,16]], "noConsumeChance": 0.0, "speed": 11.0, "deviation": 0.05, "shootTimes": 1, "ammoLevel": 0, "shootProjectileId": "wooden_arrow", "usePosture": 1, "useSound": "bow", "coldTime": 60, "holdType": "NORMAL", "twoHands": true, "durable": 256, "damage": 14, "knockBack": 5, "crit": 3, "fuelTime": 60 } } ================================================ FILE: items/buckets/bucket_empty.json ================================================ { "bucket_empty": { "type": "MATERIALS", "iconTextureData": "bucket_empty_icon.png", "group": "GROUP_BUCKET" } } ================================================ FILE: items/buckets/bucket_lava.json ================================================ { "bucket_lava": { "type": "MATERIALS", "iconTextureData": "bucket_lava_icon.png", "group": "GROUP_BUCKET", "liquidId": "lava", "fuelTime": 4000, "fuelReturnId": "bucket_empty" } } ================================================ FILE: items/buckets/bucket_milk.json ================================================ { "bucket_milk": { "type": "MATERIALS", "iconTextureData": "bucket_milk_icon.png", "group": "GROUP_BUCKET", "eatReturnId": "bucket_empty" } } ================================================ FILE: items/buckets/bucket_water.json ================================================ { "bucket_water": { "type": "MATERIALS", "iconTextureData": "bucket_water_icon.png", "group": "GROUP_BUCKET", "liquidId": "water" } } ================================================ FILE: items/bullets/fire_bullet.json ================================================ { "fire_bullet": { "type": "PROJECTILES", "iconTextureData": "fire_bullet_icon.png", "group": "GROUP_BULLET", "ammo": "bullet", "ammoLevel": 0, "projectileId": "bullet", "speed": 0.0, "shootable": true, "damage": 3, "knockBack": 1 } } ================================================ FILE: items/bullets/iron_bullet.json ================================================ { "iron_bullet": { "type": "PROJECTILES", "iconTextureData": "iron_bullet_icon.png", "group": "GROUP_BULLET", "ammo": "bullet", "ammoLevel": 0, "projectileId": "bullet", "speed": 0.0, "shootable": true, "damage": 6, "knockBack": 1 } } ================================================ FILE: items/bullets/silver_bullet.json ================================================ { "silver_bullet": { "type": "PROJECTILES", "iconTextureData": "silver_bullet_icon.png", "group": "GROUP_BULLET", "ammo": "bullet", "ammoLevel": 0, "projectileId": "bullet", "speed": 1.0, "shootable": true, "damage": 8, "knockBack": 1 } } ================================================ FILE: items/dyes/dye_black.json ================================================ { "dye_black": { "type": "MATERIALS", "iconTextureData": "dye_black_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_blue.json ================================================ { "dye_blue": { "type": "MATERIALS", "iconTextureData": "dye_blue_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_brown.json ================================================ { "dye_brown": { "type": "MATERIALS", "iconTextureData": "dye_brown_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_cyan.json ================================================ { "dye_cyan": { "type": "MATERIALS", "iconTextureData": "dye_cyan_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_gray.json ================================================ { "dye_gray": { "type": "MATERIALS", "iconTextureData": "dye_gray_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_green.json ================================================ { "dye_green": { "type": "MATERIALS", "iconTextureData": "dye_green_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_light_blue.json ================================================ { "dye_light_blue": { "type": "MATERIALS", "iconTextureData": "dye_light_blue_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_light_gray.json ================================================ { "dye_light_gray": { "type": "MATERIALS", "iconTextureData": "dye_light_gray_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_lime.json ================================================ { "dye_lime": { "type": "MATERIALS", "iconTextureData": "dye_lime_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_magenta.json ================================================ { "dye_magenta": { "type": "MATERIALS", "iconTextureData": "dye_magenta_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_orange.json ================================================ { "dye_orange": { "type": "MATERIALS", "iconTextureData": "dye_orange_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_pink.json ================================================ { "dye_pink": { "type": "MATERIALS", "iconTextureData": "dye_pink_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_purple.json ================================================ { "dye_purple": { "type": "MATERIALS", "iconTextureData": "dye_purple_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_red.json ================================================ { "dye_red": { "type": "MATERIALS", "iconTextureData": "dye_red_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_white.json ================================================ { "dye_white": { "type": "MATERIALS", "iconTextureData": "dye_white_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/dyes/dye_yellow.json ================================================ { "dye_yellow": { "type": "MATERIALS", "iconTextureData": "dye_yellow_icon.png", "group": "GROUP_DYE" } } ================================================ FILE: items/foods/apple.json ================================================ { "apple": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "apple_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 20, "foodSaturation": 24 } } ================================================ FILE: items/foods/baked_potato.json ================================================ { "baked_potato": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "baked_potato_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 30, "foodSaturation": 60 } } ================================================ FILE: items/foods/beetroot.json ================================================ { "beetroot": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "beetroot_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 12 } } ================================================ FILE: items/foods/bread.json ================================================ { "bread": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "bread_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 25, "foodSaturation": 60 } } ================================================ FILE: items/foods/cake_piece.json ================================================ { "cake_piece": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "cake_piece_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 5 } } ================================================ FILE: items/foods/carrot.json ================================================ { "carrot": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "carrot_icon.png", "group": "GROUP_FOOD", "isSeed": true, "eatable": true, "useSoundGroup": "eat", "food": 15, "foodSaturation": 36, "blockId": "carrot" } } ================================================ FILE: items/foods/chorus_fruit.json ================================================ { "chorus_fruit": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "chorus_fruit_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 20, "foodSaturation": 24 } } ================================================ FILE: items/foods/cooked_chicken.json ================================================ { "cooked_chicken": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "cooked_chicken_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 30, "foodSaturation": 72 } } ================================================ FILE: items/foods/cooked_cod.json ================================================ { "cooked_cod": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "cooked_cod_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 25, "foodSaturation": 60 } } ================================================ FILE: items/foods/cooked_mutton.json ================================================ { "cooked_mutton": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "cooked_mutton_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 30, "foodSaturation": 96 } } ================================================ FILE: items/foods/cooked_porkchop.json ================================================ { "cooked_porkchop": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "cooked_porkchop_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 40, "foodSaturation": 100 } } ================================================ FILE: items/foods/cooked_rabbit.json ================================================ { "cooked_rabbit": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "cooked_rabbit_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 25, "foodSaturation": 60 } } ================================================ FILE: items/foods/cooked_salmon.json ================================================ { "cooked_salmon": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "cooked_salmon_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 25, "foodSaturation": 60 } } ================================================ FILE: items/foods/cookie.json ================================================ { "cookie": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "cookie_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 4 } } ================================================ FILE: items/foods/golden_apple.json ================================================ { "golden_apple": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "golden_apple_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 20, "foodSaturation": 96, "buffs": [ { "id": "absorption", "time": 7200 }, { "id": "regeneration", "time": 300 } ] } } ================================================ FILE: items/foods/golden_carrot.json ================================================ { "golden_carrot": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "golden_carrot_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 30, "foodSaturation": 100 } } ================================================ FILE: items/foods/melon_slice.json ================================================ { "melon_slice": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "melon_slice_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 12 } } ================================================ FILE: items/foods/mushroom_stew.json ================================================ { "mushroom_stew": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "mushroom_stew_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "eatReturnId": "bowl", "food": 30, "foodSaturation": 72 } } ================================================ FILE: items/foods/potato.json ================================================ { "potato": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "potato_icon.png", "group": "GROUP_FOOD", "isSeed": true, "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 6, "blockId": "potato" } } ================================================ FILE: items/foods/pufferfish.json ================================================ { "pufferfish": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "pufferfish_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 12, "buffs": [ { "id": "hunger", "time": 900 }, { "id": "poison", "time": 3600 } ] } } ================================================ FILE: items/foods/pumpkin_pie.json ================================================ { "pumpkin_pie": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "pumpkin_pie_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 40, "foodSaturation": 48 } } ================================================ FILE: items/foods/raw_beef.json ================================================ { "raw_beef": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "raw_beef_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 15, "foodSaturation": 18 } } ================================================ FILE: items/foods/raw_chicken.json ================================================ { "raw_chicken": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "raw_chicken_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 15, "foodSaturation": 12, "buffs": [ { "id": "hunger", "time": 10 } ] } } ================================================ FILE: items/foods/raw_cod.json ================================================ { "raw_cod": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "raw_cod_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 4 } } ================================================ FILE: items/foods/raw_mutton.json ================================================ { "raw_mutton": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "raw_mutton_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 12 } } ================================================ FILE: items/foods/raw_porkchop.json ================================================ { "raw_porkchop": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "raw_porkchop_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 15, "foodSaturation": 18 } } ================================================ FILE: items/foods/raw_rabbit.json ================================================ { "raw_rabbit": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "raw_rabbit_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 18 } } ================================================ FILE: items/foods/raw_salmon.json ================================================ { "raw_salmon": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "raw_salmon_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 4 } } ================================================ FILE: items/foods/steak.json ================================================ { "steak": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "steak_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 40, "foodSaturation": 100 } } ================================================ FILE: items/guns/fire_gun.json ================================================ { "fire_gun": { "type": "TOOLS", "iconTextureData": "fire_gun_entity.png", "textureData": "fire_gun_entity.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "fire_gun", "entityWidth": 40, "entityHeight": 22, "handX": 14, "handY": 14, "firePoints": [[40,5]], "noConsumeChance": 0.0, "speed": 10.0, "deviation": 0.15, "shootTimes": 1, "special": 2, "shootProjectileId": "gun_fire", "usePosture": 0, "coldTime": 2, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "durable": 2020, "damage": 2, "knockBack": 0, "crit": 3, "noEnchanted": true } } ================================================ FILE: items/guns/fire_shooter.json ================================================ { "fire_shooter": { "type": "TOOLS", "iconTextureData": "fire_shooter.png", "textureData": "fire_shooter.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "Gun", "entityWidth": 50, "entityHeight": 22, "handX": 12, "handY": 18, "firePoints": [[50,6]], "noConsumeChance": 0.0, "speed": 12.0, "deviation": 0.05, "shootTimes": 1, "special": 2, "shootProjectileId": "super_fire", "usePosture": 0, "coldTime": 1, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "durable": 2020, "damage": 2, "knockBack": 0, "crit": 3, "noEnchanted": true } } ================================================ FILE: items/guns/handgun.json ================================================ { "handgun": { "type": "TOOLS", "iconTextureData": "handgun_entity.png", "textureData": "handgun_entity.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "Gun", "ammo": "bullet", "entityWidth": 36, "entityHeight": 20, "handX": 13, "handY": 14, "firePoints": [[35,4]], "noConsumeChance": 0.0, "speed": 20.0, "deviation": 0.02, "shootTimes": 1, "ammoLevel": 0, "special": 1, "shootProjectileId": "bullet", "usePosture": 0, "useSound": "pistol_fire", "coldTime": 30, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "durable": 512, "damage": 6, "knockBack": 1, "crit": 3, "noEnchanted": true } } ================================================ FILE: items/guns/rifle.json ================================================ { "rifle": { "type": "TOOLS", "iconTextureData": "rifle_entity.png", "textureData": "rifle_entity.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "Gun", "ammo": "bullet", "entityWidth": 56, "entityHeight": 22, "handX": 22, "handY": 14, "firePoints": [[55,8]], "noConsumeChance": 0.43, "speed": 22.0, "deviation": 0.03, "shootTimes": 1, "ammoLevel": 0, "special": 1, "shootProjectileId": "bullet", "usePosture": 0, "useSound": "chain_gun_fire", "coldTime": 8, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "durable": 2048, "damage": 5, "knockBack": 1, "crit": 3, "noEnchanted": true } } ================================================ FILE: items/guns/rocket_launcher.json ================================================ { "rocket_launcher": { "type": "TOOLS", "iconTextureData": "rocket_launcher_entity.png", "textureData": "rocket_launcher_entity.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "rocket_launcher", "ammo": "rocket", "entityWidth": 50, "entityHeight": 28, "handX": 24, "handY": 22, "firePoints": [[50,12]], "noConsumeChance": 0.0, "speed": 8.0, "deviation": 0.05, "shootTimes": 1, "ammoLevel": 0, "special": 1, "shootProjectileId": "rocket", "usePosture": 0, "useSound": "launch", "coldTime": 40, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "durable": 256, "damage": 5, "knockBack": 3, "crit": 4, "noEnchanted": true } } ================================================ FILE: items/guns/shotgun.json ================================================ { "shotgun": { "type": "TOOLS", "iconTextureData": "shotgun_entity.png", "textureData": "shotgun_entity.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "Gun", "ammo": "bullet", "entityWidth": 50, "entityHeight": 22, "handX": 16, "handY": 14, "firePoints": [[48,3]], "noConsumeChance": 0.0, "speed": 24.0, "deviation": 0.09, "shootTimes": 3, "ammoLevel": 0, "special": 1, "shootProjectileId": "bullet", "usePosture": 0, "useSound": "shotgun_fire", "coldTime": 32, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "durable": 1024, "damage": 8, "knockBack": 1, "crit": 3, "noEnchanted": true } } ================================================ FILE: items/guns/sniper.json ================================================ { "sniper": { "type": "TOOLS", "iconTextureData": "sniper.png", "textureData": "sniper.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "Gun", "entityWidth": 56, "entityHeight": 22, "handX": 28, "handY": 15, "firePoints": [[56,8]], "noConsumeChance": 0.7, "speed": 22.0, "deviation": 0.085, "shootTimes": 1, "special": 2, "shootProjectileId": "bullet_super", "usePosture": 0, "coldTime": 64, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "durable": 2020, "damage": 20, "knockBack": 0, "crit": 3, "noEnchanted": true, "ammo": "bullet", "ammoLevel": 0, "useSound": "shotgun_fire" } } ================================================ FILE: items/hoes/stone_hoe.json ================================================ { "stone_hoe": { "type": "TOOLS", "iconTextureData": "stone_hoe_icon.png", "textureData": "stone_hoe_entity.png", "group": "GROUP_HOE", "toolType": "HOE", "toolGrade": "STONE", "efficiency": 2.0, "coldTime": 16, "entityWidth": 26, "entityHeight": 36, "handX": 13, "handY": 26, "holdType": "NORMAL", "durable": 256, "oreDictionary": [ "OD_HOE" ] } } ================================================ FILE: items/hoes/wooden_hoe.json ================================================ { "wooden_hoe": { "type": "TOOLS", "iconTextureData": "wooden_hoe_icon.png", "textureData": "wooden_hoe_entity.png", "group": "GROUP_HOE", "toolType": "HOE", "toolGrade": "STONE", "efficiency": 2.0, "coldTime": 16, "entityWidth": 26, "entityHeight": 36, "handX": 13, "handY": 26, "holdType": "NORMAL", "durable": 128, "oreDictionary": [ "OD_HOE" ] } } ================================================ FILE: items/ingots/aluminum_ingot.json ================================================ { "aluminum_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 100, 160, 190 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/antimony_ingot.json ================================================ { "antimony_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 190, 190, 200 ], "iconColor2": [ 255, 240, 240, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/beryllium_ingot.json ================================================ { "beryllium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 100, 180, 100 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/bismuth_ingot.json ================================================ { "bismuth_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 80, 140, 140 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/bronze_ingot.json ================================================ { "bronze_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 255, 128, 0 ], "group": "GROUP_INGOT", "iconColor2": [ 255, 255, 166, 80 ] } } ================================================ FILE: items/ingots/chromium_ingot.json ================================================ { "chromium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 220, 200, 200 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/cobalt_ingot.json ================================================ { "cobalt_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 80, 80, 255 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/copper_ingot.json ================================================ { "copper_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 226, 89, 0 ], "group": "GROUP_INGOT", "iconColor2": [ 255, 255, 210, 180 ] } } ================================================ FILE: items/ingots/gallium_ingot.json ================================================ { "gallium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 195, 195, 223 ], "group": "GROUP_INGOT", "iconColor2": [ 255, 240, 240, 255 ] } } ================================================ FILE: items/ingots/gold_ingot.json ================================================ { "gold_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 255, 255, 0 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/indium_ingot.json ================================================ { "indium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 100, 0, 200 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/iridium_ingot.json ================================================ { "iridium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 180, 180, 191 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/iron_ingot.json ================================================ { "iron_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 255, 255, 255 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT", "oreDictionary": [ "OD_IRON_INGOT" ] } } ================================================ FILE: items/ingots/lead_ingot.json ================================================ { "lead_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 110, 80, 110 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/lithium_ingot.json ================================================ { "lithium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 180, 180, 200 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/magnesium_ingot.json ================================================ { "magnesium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 255, 200, 200 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/manganese_ingot.json ================================================ { "manganese_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 200, 200, 200 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/molybdenum_ingot.json ================================================ { "molybdenum_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 160, 160, 200 ], "group": "GROUP_INGOT", "iconColor2": [ 255, 255, 255, 255 ] } } ================================================ FILE: items/ingots/netherite_ingot.json ================================================ { "netherite_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 90, 87, 90 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT", "antiLava": true } } ================================================ FILE: items/ingots/nickel_ingot.json ================================================ { "nickel_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 200, 200, 255 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/niobium_ingot.json ================================================ { "niobium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 160, 150, 170 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/osmium_ingot.json ================================================ { "osmium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 40, 40, 222 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/palladium_ingot.json ================================================ { "palladium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 110, 110, 110 ], "group": "GROUP_INGOT", "iconColor2": [ 255, 222, 222, 222 ] } } ================================================ FILE: items/ingots/platinum_ingot.json ================================================ { "platinum_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 222, 222, 160 ], "group": "GROUP_INGOT", "iconColor2": [ 255, 255, 255, 240 ] } } ================================================ FILE: items/ingots/redstone_ingot.json ================================================ { "redstone_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 255, 120, 120 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/rhenium_ingot.json ================================================ { "rhenium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 66, 66, 66 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/silver_ingot.json ================================================ { "silver_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 240, 240, 255 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/sodium_ingot.json ================================================ { "sodium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 66, 66, 255 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/steel_ingot.json ================================================ { "steel_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 128, 128, 128 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/tantalum_ingot.json ================================================ { "tantalum_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 210, 210, 210 ], "group": "GROUP_INGOT", "iconColor2": [ 255, 255, 255, 255 ] } } ================================================ FILE: items/ingots/tin_ingot.json ================================================ { "tin_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 172, 172, 172 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/titanium_ingot.json ================================================ { "titanium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 220, 160, 240 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/vanadium_ingot.json ================================================ { "vanadium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 50, 50, 50 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/vibranium_ingot.json ================================================ { "vibranium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 200, 210, 220 ], "group": "GROUP_INGOT", "iconColor2": [ 255, 255, 255, 255 ] } } ================================================ FILE: items/ingots/wolfram_ingot.json ================================================ { "wolfram_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 48, 48, 48 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/yttrium_ingot.json ================================================ { "yttrium_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 180, 220, 180 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/ingots/zinc_ingot.json ================================================ { "zinc_ingot": { "ai": "Ingot", "type": "MATERIALS", "iconTextureData": "ingot_icon.png", "iconColor": [ 255, 250, 250, 240 ], "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_INGOT" } } ================================================ FILE: items/loots/guardian.json ================================================ { "guardian": { "type": "MATERIALS", "iconTextureData": "guardian_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/loots/nether_destroyer_loot.json ================================================ { "nether_destroyer_loot": { "type": "MATERIALS", "iconTextureData": "nether_destroyer_loot_icon.png", "group": "GROUP_LOOT", "antiLava": true } } ================================================ FILE: items/loots/snow_queen_loot.json ================================================ { "snow_queen_loot": { "type": "MATERIALS", "iconTextureData": "snow_queen_loot_icon.png", "group": "GROUP_LOOT", "antiLava": true } } ================================================ FILE: items/magic/bone_gun.json ================================================ { "bone_gun": { "type": "TOOLS", "iconTextureData": "bone_gun.png", "textureData": "bone_gun.png", "group": "GROUP_STAFF", "oreDictionary": [ "OD_STAFF" ], "toolType": "BOW", "ai": "InfBow", "entityWidth": 56, "entityHeight": 28, "handX": 10, "handY": 24, "firePoints": [[56,14]], "noConsumeChance": 0.0, "speed": 8.0, "deviation": 0.05, "shootProjectileId": "bone", "usePosture": 0, "useSound": "bow", "coldTime": 40, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": false, "damage": 14, "knockBack": 3, "crit": 3, "consumeMana": 17 } } ================================================ FILE: items/magic/dark_staff.json ================================================ { "dark_staff": { "type": "TOOLS", "iconTextureData": "dark_staff.png", "textureData": "dark_staff.png", "group": "GROUP_STAFF", "oreDictionary": [ "OD_STAFF" ], "toolType": "STAFF", "ai": "Staff", "speed": 6.0, "deviation": 0.00, "shootTimes": 1, "shootProjectileId": "black_hole", "usePosture": 1, "coldTime": 128, "entityWidth": 16, "entityHeight": 48, "handX": 8, "handY": 32, "firePoints": [[4,4]], "holdType": "HOLD_STAFF", "twoHands": false, "damage": 3, "knockBack": 1, "crit": 3, "consumeMana": 17, "useSound": "fireball" } } ================================================ FILE: items/magic/fire_book.json ================================================ { "fire_book": { "type": "TOOLS", "iconTextureData": "fire_book.png", "textureData": "fire_book.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "InfBow", "entityWidth": 32, "entityHeight": 32, "handX": 8, "handY": 16, "firePoints": [[32,16]], "noConsumeChance": 0.0, "speed": 8.0, "deviation": 0.05, "shootTimes": 1, "special": 2, "shootProjectileId": "fire_element", "usePosture": 0, "coldTime": 24, "holdType": "FOLLOW_MOUSE", "twoHands": false, "backForce": true, "damage": 12, "knockBack": 0, "crit": 3, "noEnchanted": true, "useSound": "fireball", "consumeMana": 8 } } ================================================ FILE: items/magic/mini_laser_gun.json ================================================ { "mini_laser_gun": { "type": "TOOLS", "iconTextureData": "mini_laser_gun.png", "textureData": "mini_laser_gun.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "InfBow", "entityWidth": 38, "entityHeight": 22, "handX": 5, "handY": 15, "firePoints": [[32,8]], "noConsumeChance": 0.0, "speed": 24.0, "deviation": 0.085, "shootTimes": 1, "special": 2, "shootProjectileId": "light_bullet_laser", "usePosture": 0, "coldTime": 12, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "damage": 14, "knockBack": 0, "crit": 3, "noEnchanted": true, "consumeMana": 18, "useSound": "sys3" } } ================================================ FILE: items/magic/mini_rocket_launcher.json ================================================ { "mini_rocket_launcher": { "type": "TOOLS", "iconTextureData": "mini_rocket_launcher.png", "textureData": "mini_rocket_launcher.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "InfBow", "entityWidth": 56, "entityHeight": 28, "handX": 30, "handY": 24, "firePoints": [[56,14]], "noConsumeChance": 0.0, "speed": 8.0, "deviation": 0.085, "shootTimes": 3, "special": 2, "shootProjectileId": "mini_rocket", "usePosture": 0, "coldTime": 64, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "durable": 2020, "damage": 12, "knockBack": 0, "crit": 3, "noEnchanted": true, "useSound": "launch", "consumeMana": 18 } } ================================================ FILE: items/magic/soul_laserer.json ================================================ { "soul_laserer": { "type": "TOOLS", "iconTextureData": "soul_laserer.png", "textureData": "soul_laserer.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "InfBow", "entityWidth": 56, "entityHeight": 22, "handX": 5, "handY": 15, "firePoints": [[56,8]], "noConsumeChance": 0.0, "speed": 16.0, "deviation": 0.085, "shootTimes": 1, "special": 2, "shootProjectileId": "magic_wave3", "usePosture": 0, "coldTime": 42, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "damage": 24, "knockBack": 0, "crit": 3, "noEnchanted": true, "consumeMana": 20, "useSound": "cannon" } } ================================================ FILE: items/magic/super_shark.json ================================================ { "super_shark": { "type": "TOOLS", "iconTextureData": "super_shark.png", "textureData": "super_shark.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "InfBow", "entityWidth": 56, "entityHeight": 22, "handX": 15, "handY": 15, "firePoints": [[56,8]], "noConsumeChance": 0.0, "speed": 6.0, "deviation": 0.085, "shootTimes": 1, "special": 2, "shootProjectileId": "lighting_bullet_red_invert2", "usePosture": 0, "coldTime": 32, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "damage": 14, "knockBack": 0, "crit": 3, "noEnchanted": true, "useSound": "fireball", "consumeMana": 10 } } ================================================ FILE: items/magic/super_shark_ghost.json ================================================ { "super_shark_ghost": { "type": "TOOLS", "iconTextureData": "super_shark.png", "textureData": "super_shark.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "Gun", "entityWidth": 56, "entityHeight": 22, "handX": 15, "handY": 15, "firePoints": [[56,8]], "noConsumeChance": 0.0, "speed": 2.0, "deviation": 0.085, "shootTimes": 1, "special": 2, "shootProjectileId": "lighting_bullet_red_invert2", "usePosture": 0, "coldTime": 12, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "damage": 8, "knockBack": 0, "crit": 3, "noEnchanted": true, "useSound": "sys3" } } ================================================ FILE: items/magic/sword_fish.json ================================================ { "sword_fish": { "type": "TOOLS", "iconTextureData": "sword_fish.png", "textureData": "sword_fish.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "InfBow", "entityWidth": 64, "entityHeight": 26, "handX": 5, "handY": 15, "firePoints": [[32,8]], "noConsumeChance": 0.0, "speed": 24.0, "deviation": 0.085, "shootTimes": 1, "special": 2, "shootProjectileId": "light_bullet_laser", "usePosture": 0, "coldTime": 12, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "damage": 7, "knockBack": 0, "crit": 3, "noEnchanted": true, "useSound": "sys3", "consumeMana": 4 } } ================================================ FILE: items/magic/sword_fish_gun.json ================================================ { "sword_fish_gun": { "type": "TOOLS", "iconTextureData": "sword_fish_gun.png", "textureData": "sword_fish_gun.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "InfBow", "entityWidth": 56, "entityHeight": 22, "handX": 25, "handY": 15, "firePoints": [[56,8]], "noConsumeChance": 0.0, "speed": 8.0, "deviation": 0.085, "shootTimes": 1, "special": 2, "shootProjectileId": "air_wave", "usePosture": 0, "coldTime": 24, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "damage": 12, "knockBack": 0, "crit": 3, "noEnchanted": true, "consumeMana": 6, "useSound": "sys3" } } ================================================ FILE: items/magic/water_book.json ================================================ { "water_book": { "type": "TOOLS", "iconTextureData": "water_book.png", "textureData": "water_book.png", "group": "GROUP_GUN", "toolType": "GUN", "ai": "InfBow", "entityWidth": 32, "entityHeight": 32, "handX": 8, "handY": 16, "firePoints": [[32,16]], "noConsumeChance": 0.0, "speed": 8.0, "deviation": 0.05, "shootTimes": 1, "special": 2, "shootProjectileId": "water_flow", "usePosture": 0, "coldTime": 24, "holdType": "FOLLOW_MOUSE", "twoHands": true, "backForce": true, "damage": 16, "knockBack": 0, "crit": 3, "noEnchanted": true, "consumeMana": 8 } } ================================================ FILE: items/misc/blaze_powder.json ================================================ { "blaze_powder": { "type": "MATERIALS", "iconTextureData": "blaze_powder_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/blaze_rod.json ================================================ { "blaze_rod": { "type": "MATERIALS", "iconTextureData": "blaze_rod_icon.png", "group": "GROUP_MATERIAL", "fuelTime": 480 } } ================================================ FILE: items/misc/bone.json ================================================ { "bone": { "type": "MATERIALS", "iconTextureData": "bone_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/bone_meal.json ================================================ { "bone_meal": { "type": "MATERIALS", "iconTextureData": "bone_meal_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/book.json ================================================ { "book": { "type": "MATERIALS", "iconTextureData": "book_icon.png", "group": "GROUP_MATERIAL", "fuelTime": 20 } } ================================================ FILE: items/misc/bowl.json ================================================ { "bowl": { "type": "MATERIALS", "iconTextureData": "bowl_icon.png", "group": "GROUP_MATERIAL", "fuelTime": 20 } } ================================================ FILE: items/misc/charcoal.json ================================================ { "charcoal": { "type": "MATERIALS", "iconTextureData": "charcoal_icon.png", "group": "GROUP_MATERIAL", "fuelTime": 160 } } ================================================ FILE: items/misc/clay.json ================================================ { "clay": { "type": "MATERIALS", "iconTextureData": "clay_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/coal.json ================================================ { "coal": { "type": "MATERIALS", "iconTextureData": "coal_icon.png", "group": "GROUP_MATERIAL", "fuelTime": 320 } } ================================================ FILE: items/misc/cocoa_bean.json ================================================ { "cocoa_bean": { "type": "MATERIALS", "iconTextureData": "cocoa_bean_icon.png", "group": "GROUP_SEED" } } ================================================ FILE: items/misc/diamond.json ================================================ { "diamond": { "type": "MATERIALS", "iconTextureData": "diamond_icon.png", "group": "GROUP_DIAMOND" } } ================================================ FILE: items/misc/dried_kelp.json ================================================ { "dried_kelp": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "dried_kelp_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 6 } } ================================================ FILE: items/misc/egg.json ================================================ { "egg": { "type": "MATERIALS", "iconTextureData": "egg_icon.png", "group": "GROUP_FOOD" } } ================================================ FILE: items/misc/emerald.json ================================================ { "emerald": { "type": "MATERIALS", "iconTextureData": "emerald_icon.png", "group": "GROUP_EMERALD" } } ================================================ FILE: items/misc/enchanted_book.json ================================================ { "enchanted_book": { "type": "TOOLS", "iconTextureData": "enchanted_book_icon.png", "group": "GROUP_BOOK", "toolType": "BOOK" } } ================================================ FILE: items/misc/ender_eye.json ================================================ { "ender_eye": { "type": "MATERIALS", "iconTextureData": "ender_eye_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/ender_pearl.json ================================================ { "ender_pearl": { "type": "MATERIALS", "iconTextureData": "ender_pearl_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/feather.json ================================================ { "feather": { "type": "MATERIALS", "iconTextureData": "feather_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/fermented_spider_eye.json ================================================ { "fermented_spider_eye": { "type": "MATERIALS", "iconTextureData": "fermented_spider_eye_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/fire_charge.json ================================================ { "fire_charge": { "type": "MATERIALS", "iconTextureData": "fire_charge_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/firework_rocket.json ================================================ { "firework_rocket": { "type": "MATERIALS", "iconTextureData": "firework_rocket_icon.png", "group": "GROUP_MATERIAL", "onTest": true } } ================================================ FILE: items/misc/fishing_rod.json ================================================ { "fishing_rod": { "type": "TOOLS", "iconTextureData": "fishing_rod_icon.png", "textureData": "fishing_rod_entity.png", "group": "GROUP_FISHINGROD", "toolType": "FISHING_ROD", "ai": "fishing_rod", "coldTime": 60, "entityWidth": 38, "entityHeight": 42, "handX": 6, "handY": 30, "firePoints": [[36,1]], "holdType": "FOLLOW_MOUSE", "twoHands": true, "durable": 256, "fuelTime": 60, "onTest": true } } ================================================ FILE: items/misc/flint.json ================================================ { "flint": { "type": "MATERIALS", "iconTextureData": "flint_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/ghast_tear.json ================================================ { "ghast_tear": { "type": "MATERIALS", "iconTextureData": "ghast_tear_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/glistering_melon_slice.json ================================================ { "glistering_melon_slice": { "type": "MATERIALS", "iconTextureData": "glistering_melon_slice_icon.png", "group": "GROUP_FOOD" } } ================================================ FILE: items/misc/glow_ball.json ================================================ { "glow_ball": { "type": "PROJECTILES", "iconTextureData": "glow_ball_icon.png", "group": "GROUP_DROPABLE", "projectileId": "glow_ball", "speed": 6.0, "canThrow": true, "damage": 3, "knockBack": 2, "coldTime": 1000, "shootable": true } } ================================================ FILE: items/misc/glowstone_dust.json ================================================ { "glowstone_dust": { "type": "MATERIALS", "iconTextureData": "glowstone_dust_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/gray_feather.json ================================================ { "gray_feather": { "type": "MATERIALS", "iconTextureData": "gray_feather_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/gunpowder.json ================================================ { "gunpowder": { "type": "MATERIALS", "iconTextureData": "gunpowder_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/heart_of_sea.json ================================================ { "heart_of_sea": { "type": "MATERIALS", "iconTextureData": "heart_of_sea_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/ink_sac.json ================================================ { "ink_sac": { "type": "MATERIALS", "iconTextureData": "ink_sac_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/kelp.json ================================================ { "kelp": { "type": "BLOCKS", "iconTextureData": "kelp_icon.png", "group": "GROUP_FOOD", "blockId": "kelp" } } ================================================ FILE: items/misc/lapis_lazuli.json ================================================ { "lapis_lazuli": { "type": "MATERIALS", "iconTextureData": "lapis_lazuli_icon.png", "group": "GROUP_LAPIS" } } ================================================ FILE: items/misc/leather.json ================================================ { "leather": { "type": "MATERIALS", "iconTextureData": "leather_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/lighter.json ================================================ { "lighter": { "type": "TOOLS", "iconTextureData": "lighter_icon.png", "textureData": "lighter_entity.png", "group": "GROUP_LIGHTER", "toolType": "SWORD", "ai": "sword", "coldTime": 22, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 128, "onTest": true } } ================================================ FILE: items/misc/magma_cream.json ================================================ { "magma_cream": { "type": "MATERIALS", "iconTextureData": "magma_cream_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/mana_piece.json ================================================ { "mana_piece": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "mana_piece_icon.png", "group": "GROUP_MANA", "eatable": true, "useSoundGroup": "eat", "addMagic": 10, "addMaxMagic": 10 } } ================================================ FILE: items/misc/map_paper.json ================================================ { "map_paper": { "type": "TOOLS", "iconTextureData": "map_icon.png", "textureData": "map_entity.png", "group": "GROUP_MAP", "toolType": "SWORD", "ai": "sword", "coldTime": 22, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 128, "onTest": true } } ================================================ FILE: items/misc/nautilus_shell.json ================================================ { "nautilus_shell": { "type": "MATERIALS", "iconTextureData": "nautilus_shell_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/nether_brick.json ================================================ { "nether_brick": { "type": "MATERIALS", "iconTextureData": "nether_brick_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/nether_star.json ================================================ { "nether_star": { "type": "MATERIALS", "iconTextureData": "nether_star_icon.png", "group": "GROUP_MATERIAL", "onTest": true } } ================================================ FILE: items/misc/nether_wart.json ================================================ { "nether_wart": { "type": "MATERIALS", "iconTextureData": "nether_wart_icon.png", "group": "GROUP_MATERIAL", "isSeed": true, "blockId": "nether_wart" } } ================================================ FILE: items/misc/netherite_scrap.json ================================================ { "netherite_scrap": { "type": "MATERIALS", "iconTextureData": "netherite_scrap_icon.png", "group": "GROUP_MATERIAL", "antiLava": true } } ================================================ FILE: items/misc/paper.json ================================================ { "paper": { "type": "MATERIALS", "iconTextureData": "paper_icon.png", "group": "GROUP_MATERIAL", "fuelTime": 20 } } ================================================ FILE: items/misc/phantom_membrane.json ================================================ { "phantom_membrane": { "type": "MATERIALS", "iconTextureData": "phantom_membrane_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/popped_chorus_fruits.json ================================================ { "popped_chorus_fruits": { "type": "MATERIALS", "iconTextureData": "popped_chorus_fruits_icon.png", "group": "GROUP_FOOD" } } ================================================ FILE: items/misc/prismarine_crystals.json ================================================ { "prismarine_crystals": { "type": "MATERIALS", "iconTextureData": "prismarine_crystals_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/prismarine_shard.json ================================================ { "prismarine_shard": { "type": "MATERIALS", "iconTextureData": "prismarine_shard_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/quartz.json ================================================ { "quartz": { "type": "MATERIALS", "iconTextureData": "quartz_icon.png", "group": "GROUP_QUARTZ" } } ================================================ FILE: items/misc/rabbit_foot.json ================================================ { "rabbit_foot": { "type": "MATERIALS", "iconTextureData": "rabbit_foot_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/rabbit_hide.json ================================================ { "rabbit_hide": { "type": "MATERIALS", "iconTextureData": "rabbit_hide_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/red_brick.json ================================================ { "red_brick": { "type": "MATERIALS", "iconTextureData": "brick_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/redstone.json ================================================ { "redstone": { "type": "MATERIALS", "iconTextureData": "redstone_icon.png", "group": "GROUP_REDSTONE" } } ================================================ FILE: items/misc/rocket.json ================================================ { "rocket": { "type": "PROJECTILES", "iconTextureData": "rocket_icon.png", "group": "GROUP_ROCKET", "ammo": "rocket", "ammoLevel": 0, "projectileId": "rocket", "speed": 0.0, "shootable": true, "damage": 10, "knockBack": 1 } } ================================================ FILE: items/misc/rotten_flesh.json ================================================ { "rotten_flesh": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "rotten_flesh_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 20, "foodSaturation": 8, "buffs": [ { "id": "hunger", "time": 1440 } ] } } ================================================ FILE: items/misc/scute.json ================================================ { "scute": { "type": "MATERIALS", "iconTextureData": "scute_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/shears.json ================================================ { "shears": { "type": "TOOLS", "iconTextureData": "shears_icon.png", "textureData": "shears_entity.png", "group": "GROUP_SHEARS", "toolType": "SHEARS", "toolGrade": "STONE", "efficiency": 2.0, "coldTime": 20, "entityWidth": 20, "entityHeight": 32, "handX": 10, "handY": 22, "holdType": "NORMAL", "durable": 128 } } ================================================ FILE: items/misc/shulker_shell.json ================================================ { "shulker_shell": { "type": "MATERIALS", "iconTextureData": "shulker_shell_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/slimeball.json ================================================ { "slimeball": { "type": "MATERIALS", "iconTextureData": "slimeball_icon.png", "group": "GROUP_MATERIAL", "fuelTime": 20 } } ================================================ FILE: items/misc/snowball.json ================================================ { "snowball": { "type": "MATERIALS", "iconTextureData": "snowball_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/spider_eye.json ================================================ { "spider_eye": { "ai": "Food", "type": "MATERIALS", "iconTextureData": "spider_eye_icon.png", "group": "GROUP_FOOD", "eatable": true, "useSoundGroup": "eat", "food": 10, "foodSaturation": 32, "buffs": [ { "id": "poison", "time": 240 } ] } } ================================================ FILE: items/misc/stick.json ================================================ { "stick": { "type": "MATERIALS", "iconTextureData": "stick_icon.png", "group": "GROUP_STICK", "fuelTime": 20 } } ================================================ FILE: items/misc/string.json ================================================ { "string": { "type": "MATERIALS", "iconTextureData": "string_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/sugar_cane.json ================================================ { "sugar_cane": { "type": "BLOCKS", "iconTextureData": "sugar_cane_icon.png", "group": "GROUP_SEED", "isSeed": true, "blockId": "sugar_cane" } } ================================================ FILE: items/misc/suger.json ================================================ { "suger": { "type": "MATERIALS", "iconTextureData": "suger_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/totem_of_undying.json ================================================ { "totem_of_undying": { "type": "MATERIALS", "iconTextureData": "totem_of_undying_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/vine.json ================================================ { "vine": { "type": "MATERIALS", "iconTextureData": "vine_icon.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc/wheat.json ================================================ { "wheat": { "type": "MATERIALS", "iconTextureData": "wheat_icon.png", "group": "GROUP_FOOD" } } ================================================ FILE: items/misc/wire_cutter.json ================================================ { "wire_cutter": { "type": "TOOLS", "iconTextureData": "wire_cutter_icon.png", "textureData": "wire_cutter_entity.png", "group": "GROUP_WIRE_CUTTER", "toolType": "WIRE_CUTTER", "toolGrade": "STONE", "efficiency": 2.0, "coldTime": 16, "entityWidth": 20, "entityHeight": 32, "handX": 10, "handY": 28, "holdType": "NORMAL", "durable": 512 } } ================================================ FILE: items/misc2/ancient_ingot.json ================================================ { "ancient_ingot": { "type": "MATERIALS", "iconTextureData": "ancient_ingot.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/ancient_sample.json ================================================ { "ancient_sample": { "type": "MATERIALS", "iconTextureData": "ancient_sample.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/blood.json ================================================ { "blood": { "type": "MATERIALS", "iconTextureData": "blood.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/blue_crystal.json ================================================ { "blue_crystal": { "type": "MATERIALS", "iconTextureData": "blue_crystal.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/dark_shadow_ingot.json ================================================ { "dark_shadow_ingot": { "type": "MATERIALS", "iconTextureData": "dark_shadow_ingot.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/dark_shadow_part.json ================================================ { "dark_shadow_part": { "type": "MATERIALS", "iconTextureData": "dark_shadow_part.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/diamond_ingot.json ================================================ { "diamond_ingot": { "type": "MATERIALS", "iconTextureData": "diamond_ingot.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/ender_mirror.json ================================================ { "ender_mirror": { "ai": "EnderMirror", "type": "TOOLS", "iconTextureData": "ender_mirror.png", "textureData": "ender_mirror.png", "group": "GROUP_MATERIAL", "toolType": "ENDER_MIRROR", "entityWidth": 32, "entityHeight": 32, "handX": 10, "handY": 20 } } ================================================ FILE: items/misc2/evil_part.json ================================================ { "evil_part": { "type": "MATERIALS", "iconTextureData": "evil_part.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/flesh_ingot.json ================================================ { "flesh_ingot": { "type": "MATERIALS", "iconTextureData": "flesh_ingot.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/flesh_machine_part.json ================================================ { "flesh_machine_part": { "type": "MATERIALS", "iconTextureData": "flesh_machine_part.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/flesh_part.json ================================================ { "flesh_part": { "type": "MATERIALS", "iconTextureData": "flesh_part.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/ghost.json ================================================ { "ghost": { "type": "MATERIALS", "iconTextureData": "ghost.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/ghost_crystal.json ================================================ { "ghost_crystal": { "type": "MATERIALS", "iconTextureData": "ghost_crystal.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/ghost_element.json ================================================ { "ghost_element": { "type": "MATERIALS", "iconTextureData": "ghost_element.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/ice_element.json ================================================ { "ice_element": { "type": "MATERIALS", "iconTextureData": "ice_element.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/ice_element_ball.json ================================================ { "ice_element_ball": { "type": "MATERIALS", "iconTextureData": "ice_element_ball.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/knight_ingot.json ================================================ { "knight_ingot": { "type": "MATERIALS", "iconTextureData": "knight_ingot.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/machine_part.json ================================================ { "machine_part": { "type": "MATERIALS", "iconTextureData": "machine_part.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/magic_cell.json ================================================ { "magic_cell": { "type": "MATERIALS", "iconTextureData": "magic_cell.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/magic_cell_group.json ================================================ { "magic_cell_group": { "type": "MATERIALS", "iconTextureData": "magic_cell_group.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/magic_crystal.json ================================================ { "magic_crystal": { "type": "MATERIALS", "iconTextureData": "magic_crystal.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/magic_silver_ingot.json ================================================ { "magic_silver_ingot": { "type": "MATERIALS", "iconTextureData": "magic_silver_ingot.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/magma_gold_ingot.json ================================================ { "magma_gold_ingot": { "type": "MATERIALS", "iconTextureData": "magma_gold_ingot.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/nether_destroyer.json ================================================ { "dungeon_eater": { "ai": "DungeonEater", "type": "MATERIALS", "iconTextureData": "dungeon_eater.png", "group": "GROUP_BOSS" } } ================================================ FILE: items/misc2/pure_red_stone.json ================================================ { "pure_red_stone": { "type": "MATERIALS", "iconTextureData": "pure_red_stone.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/red_crystal.json ================================================ { "red_crystal": { "type": "MATERIALS", "iconTextureData": "red_crystal.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/red_gold_ingot.json ================================================ { "red_gold_ingot": { "type": "MATERIALS", "iconTextureData": "red_gold_ingot.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/soul_element.json ================================================ { "soul_element": { "type": "MATERIALS", "iconTextureData": "soul_element.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/star_ingot.json ================================================ { "star_ingot": { "type": "MATERIALS", "iconTextureData": "star_ingot.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/strange_eye.json ================================================ { "strange_eye": { "ai": "CrisonEye", "type": "MATERIALS", "iconTextureData": "strange_eye.png", "group": "GROUP_BOSS" } } ================================================ FILE: items/misc2/strange_len.json ================================================ { "strange_len": { "type": "MATERIALS", "iconTextureData": "strange_len.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/tower_core.json ================================================ { "tower_core": { "type": "TOOLS", "iconTextureData": "tower_core.png", "textureData": "tower_core.png", "group": "GROUP_TOWER_CORE", "toolType": "TOWER_CORE", "durable": 2000 } } ================================================ FILE: items/misc2/white_crystal.json ================================================ { "white_crystal": { "type": "MATERIALS", "iconTextureData": "white_crystal.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/misc2/yellow_crystal.json ================================================ { "yellow_crystal": { "type": "MATERIALS", "iconTextureData": "yellow_crystal.png", "group": "GROUP_MATERIAL" } } ================================================ FILE: items/nuggets/gold_nugget.json ================================================ { "gold_nugget": { "type": "MATERIALS", "iconTextureData": "nugget_icon.png", "iconColor": [ 255, 255, 255, 0 ], "group": "GROUP_NUGGET" } } ================================================ FILE: items/nuggets/iron_nugget.json ================================================ { "iron_nugget": { "type": "MATERIALS", "iconTextureData": "nugget_icon.png", "iconColor": [ 255, 255, 255, 255 ], "group": "GROUP_NUGGET" } } ================================================ FILE: items/pickaxes/bronze_pickaxe.json ================================================ { "bronze_pickaxe": { "type": "TOOLS", "iconTextureData": "bronze_pickaxe_entity.png", "textureData": "bronze_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "GOLD", "efficiency": 3.5, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 38, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 1248, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/pickaxes/copper_pickaxe.json ================================================ { "copper_pickaxe": { "type": "TOOLS", "iconTextureData": "copper_pickaxe_entity.png", "textureData": "copper_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "IRON", "efficiency": 2.5, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 38, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 824, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/pickaxes/diamond_pickaxe.json ================================================ { "diamond_pickaxe": { "type": "TOOLS", "iconTextureData": "diamond_pickaxe_entity.png", "textureData": "diamond_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "DIAMOND", "efficiency": 5.0, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 38, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 4040, "damage": 5, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/pickaxes/golden_pickaxe.json ================================================ { "golden_pickaxe": { "type": "TOOLS", "iconTextureData": "golden_pickaxe_entity.png", "textureData": "golden_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "GOLD", "efficiency": 4.0, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 38, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 1856, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/pickaxes/grass_pickaxe.json ================================================ { "grass_pickaxe": { "type": "TOOLS", "iconTextureData": "grass_pickaxe_entity.png", "textureData": "grass_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "GRASS", "efficiency": 1.0, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 36, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 128, "damage": 1, "knockBack": 1, "crit": 0, "isNoBreaking": true, "enchantments": [ { "id": "phyton", "level": 1 } ] } } ================================================ FILE: items/pickaxes/iron_pickaxe.json ================================================ { "iron_pickaxe": { "type": "TOOLS", "iconTextureData": "iron_pickaxe_entity.png", "textureData": "iron_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "IRON", "efficiency": 3.0, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 36, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 1000, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/pickaxes/lead_pickaxe.json ================================================ { "lead_pickaxe": { "type": "TOOLS", "iconTextureData": "lead_pickaxe_entity.png", "textureData": "lead_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "IRON", "efficiency": 3.0, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 38, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 1000, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/pickaxes/nether_pickaxe.json ================================================ { "nether_pickaxe": { "type": "TOOLS", "iconTextureData": "nether_pickaxe_entity.png", "textureData": "nether_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "DIAMOND", "efficiency": 5.5, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 38, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 4896, "damage": 5, "knockBack": 1, "crit": 0, "antiLava": true } } ================================================ FILE: items/pickaxes/silver_pickaxe.json ================================================ { "silver_pickaxe": { "type": "TOOLS", "iconTextureData": "silver_pickaxe_entity.png", "textureData": "silver_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "GOLD", "efficiency": 4.0, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 38, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 1856, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/pickaxes/steel_pickaxe.json ================================================ { "steel_pickaxe": { "type": "TOOLS", "iconTextureData": "steel_pickaxe_entity.png", "textureData": "steel_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "GOLD", "efficiency": 3.5, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 38, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 1248, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/pickaxes/stone_pickaxe.json ================================================ { "stone_pickaxe": { "type": "TOOLS", "iconTextureData": "stone_pickaxe_entity.png", "textureData": "stone_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "STONE", "efficiency": 2.0, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 26, "entityHeight": 36, "handX": 13, "handY": 28, "holdType": "NORMAL", "durable": 524, "damage": 3, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/pickaxes/tin_pickaxe.json ================================================ { "tin_pickaxe": { "type": "TOOLS", "iconTextureData": "tin_pickaxe_entity.png", "textureData": "tin_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "IRON", "efficiency": 2.5, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 38, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 824, "damage": 4, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/pickaxes/wooden_pickaxe.json ================================================ { "wooden_pickaxe": { "type": "TOOLS", "iconTextureData": "wooden_pickaxe_entity.png", "textureData": "wooden_pickaxe_entity.png", "group": "GROUP_PICKAXE", "toolType": "PICKAXE", "toolGrade": "WOOD", "efficiency": 1.5, "ai": "Pickaxe", "coldTime": 16, "entityWidth": 30, "entityHeight": 36, "handX": 16, "handY": 26, "holdType": "NORMAL", "durable": 280, "fuelTime": 40, "damage": 2, "knockBack": 1, "crit": 0 } } ================================================ FILE: items/potions/glass_bottle.json ================================================ { "glass_bottle": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_icon.png", "iconColor2": [ 0, 255, 255, 255 ], "group": "GROUP_MATERIAL" } } ================================================ FILE: items/potions/potion_awkward.json ================================================ { "potion_awkward": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 90, 140, 255 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle" } } ================================================ FILE: items/potions/potion_fire_resistance.json ================================================ { "potion_fire_resistance": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_4_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 228, 150, 50 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "fire_defense", "time": 10800 } ] } } ================================================ FILE: items/potions/potion_fire_resistance_long.json ================================================ { "potion_fire_resistance_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_5_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 228, 150, 50 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "fire_defense", "time": 28800 } ] } } ================================================ FILE: items/potions/potion_glowing.json ================================================ { "potion_glowing": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 244, 244, 64 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "glowing", "time": 10800 } ] } } ================================================ FILE: items/potions/potion_glowing_long.json ================================================ { "potion_glowing_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_4_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 244, 244, 64 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "glowing", "time": 28800 } ] } } ================================================ FILE: items/potions/potion_harming.json ================================================ { "potion_harming": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_6_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 120, 60, 60 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "addHealth": -30 } } ================================================ FILE: items/potions/potion_harming_super.json ================================================ { "potion_harming_super": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_3_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 120, 60, 60 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "addHealth": -60 } } ================================================ FILE: items/potions/potion_healing.json ================================================ { "potion_healing": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_2_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 255, 22, 22 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "addHealth": 50, "buffs": [ { "id": "health_cold", "time": 1800 } ] } } ================================================ FILE: items/potions/potion_healing_super.json ================================================ { "potion_healing_super": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_3_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 255, 22, 22 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "addHealth": 100, "buffs": [ { "id": "health_cold", "time": 2400 } ] } } ================================================ FILE: items/potions/potion_invisibility.json ================================================ { "potion_invisibility": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_6_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 130, 130, 140 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "invisibility", "time": 10800 } ] } } ================================================ FILE: items/potions/potion_invisibility_long.json ================================================ { "potion_invisibility_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_2_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 130, 130, 140 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "invisibility", "time": 28800 } ] } } ================================================ FILE: items/potions/potion_leaping.json ================================================ { "potion_leaping": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 24, 255, 67 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "jump_boost", "time": 10800 } ] } } ================================================ FILE: items/potions/potion_leaping_long.json ================================================ { "potion_leaping_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_4_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 24, 255, 67 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "jump_boost", "time": 28800 } ] } } ================================================ FILE: items/potions/potion_night_vision.json ================================================ { "potion_night_vision": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 80, 80, 240 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "vision", "time": 10800 } ] } } ================================================ FILE: items/potions/potion_night_vision_long.json ================================================ { "potion_night_vision_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_4_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 80, 80, 240 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "vision", "time": 28800 } ] } } ================================================ FILE: items/potions/potion_poison.json ================================================ { "potion_poison": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_6_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 70, 150, 40 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "poison", "time": 600 } ] } } ================================================ FILE: items/potions/potion_poison_long.json ================================================ { "potion_poison_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_3_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 70, 150, 40 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "poison", "time": 1800 } ] } } ================================================ FILE: items/potions/potion_regeneration.json ================================================ { "potion_regeneration": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_4_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 212, 74, 170 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "regeneration", "time": 3600 }, { "id": "health_cold", "time": 6000 } ], "addHealth": 20 } } ================================================ FILE: items/potions/potion_regeneration_long.json ================================================ { "potion_regeneration_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_5_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 212, 74, 170 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "regeneration", "time": 6000 }, { "id": "health_cold", "time": 9400 } ], "addHealth": 20 } } ================================================ FILE: items/potions/potion_slow_falling.json ================================================ { "potion_slow_falling": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_4_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 255, 250, 210 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "slow_falling", "time": 3600 } ] } } ================================================ FILE: items/potions/potion_slow_falling_long.json ================================================ { "potion_slow_falling_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_5_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 255, 250, 210 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "slow_falling", "time": 10800 } ] } } ================================================ FILE: items/potions/potion_slowness.json ================================================ { "potion_slowness": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_2_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 87, 105, 126 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "slowness", "time": 10800 } ] } } ================================================ FILE: items/potions/potion_slowness_long.json ================================================ { "potion_slowness_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_3_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 87, 105, 126 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "slowness", "time": 28800 } ] } } ================================================ FILE: items/potions/potion_strength.json ================================================ { "potion_strength": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_3_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 220, 50, 45 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "strength", "time": 10800 } ] } } ================================================ FILE: items/potions/potion_strength_long.json ================================================ { "potion_strength_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_5_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 220, 50, 45 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "strength", "time": 28800 } ] } } ================================================ FILE: items/potions/potion_swiftness.json ================================================ { "potion_swiftness": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_6_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 124, 178, 200 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "speed", "time": 10800 } ] } } ================================================ FILE: items/potions/potion_swiftness_long.json ================================================ { "potion_swiftness_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_4_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 124, 178, 200 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "speed", "time": 28800 } ] } } ================================================ FILE: items/potions/potion_water.json ================================================ { "potion_water": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 90, 140, 255 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle" } } ================================================ FILE: items/potions/potion_water_breathing.json ================================================ { "potion_water_breathing": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_6_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 60, 100, 200 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "water_breathing", "time": 10800 } ] } } ================================================ FILE: items/potions/potion_water_breathing_long.json ================================================ { "potion_water_breathing_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_2_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 60, 100, 200 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "water_breathing", "time": 28800 } ] } } ================================================ FILE: items/potions/potion_weakness.json ================================================ { "potion_weakness": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_6_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 130, 140, 120 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "weak", "time": 3600 } ] } } ================================================ FILE: items/potions/potion_weakness_long.json ================================================ { "potion_weakness_long": { "ai": "Potion", "type": "MATERIALS", "iconTextureData": "glass_bottle_super_icon.png", "group": "GROUP_POTION", "iconColor2": [ 255, 130, 140, 120 ], "eatable": true, "useSound": "drink", "eatReturnId": "glass_bottle", "buffs": [ { "id": "weak", "time": 10800 } ] } } ================================================ FILE: items/seeds/melon_seed.json ================================================ { "melon_seed": { "type": "MATERIALS", "iconTextureData": "melon_seed_icon.png", "group": "GROUP_SEED", "isSeed": true, "blockId": "melon_stem" } } ================================================ FILE: items/seeds/pumpkin_seed.json ================================================ { "pumpkin_seed": { "type": "MATERIALS", "iconTextureData": "pumpkin_seed_icon.png", "group": "GROUP_SEED", "isSeed": true, "blockId": "pumpkin_stem" } } ================================================ FILE: items/seeds/seed.json ================================================ { "seed": { "type": "MATERIALS", "iconTextureData": "seed_icon.png", "group": "GROUP_SEED", "isSeed": true, "blockId": "wheat" } } ================================================ FILE: items/staffs/amethyst_staff.json ================================================ { "amethyst_staff": { "type": "TOOLS", "iconTextureData": "amethyst_staff_entity.png", "textureData": "amethyst_staff_entity.png", "group": "GROUP_STAFF", "oreDictionary": [ "OD_STAFF" ], "toolType": "STAFF", "ai": "Staff", "speed": 6.0, "deviation": 0.03, "shootTimes": 1, "shootProjectileId": "amethyst_magic", "usePosture": 1, "useSound": "wand1", "coldTime": 36, "entityWidth": 12, "entityHeight": 48, "handX": 6, "handY": 32, "firePoints": [[6,6]], "holdType": "HOLD_STAFF", "twoHands": false, "damage": 12, "knockBack": 5, "crit": 3, "consumeMana": 4 } } ================================================ FILE: items/staffs/fire_staff.json ================================================ { "fire_staff": { "type": "TOOLS", "iconTextureData": "fire_staff.png", "textureData": "fire_staff.png", "group": "GROUP_STAFF", "oreDictionary": [ "OD_STAFF" ], "toolType": "STAFF", "ai": "Staff", "speed": 12.0, "deviation": 0.05, "shootTimes": 1, "shootProjectileId": "fire_flow", "usePosture": 1, "coldTime": 8, "entityWidth": 20, "entityHeight": 52, "handX": 10, "handY": 32, "firePoints": [[4,4]], "holdType": "HOLD_STAFF", "twoHands": false, "damage": 5, "knockBack": 1, "crit": 3, "consumeMana": 4 } } ================================================ FILE: items/staffs/frosen_staff.json ================================================ { "frosen_staff": { "type": "TOOLS", "iconTextureData": "frosen_staff.png", "textureData": "frosen_staff.png", "group": "GROUP_STAFF", "oreDictionary": [ "OD_STAFF" ], "toolType": "STAFF", "ai": "Staff", "speed": 12.0, "deviation": 0.05, "shootTimes": 1, "shootProjectileId": "ice_magic", "usePosture": 1, "coldTime": 48, "entityWidth": 16, "entityHeight": 48, "handX": 8, "handY": 36, "firePoints": [[4,4]], "holdType": "HOLD_STAFF", "twoHands": false, "damage": 16, "knockBack": 5, "crit": 3, "consumeMana": 10, "useSound": "wand1" } } ================================================ FILE: items/staffs/ice_staff.json ================================================ { "ice_staff": { "type": "TOOLS", "iconTextureData": "ice_staff_entity.png", "textureData": "ice_staff_entity.png", "group": "GROUP_STAFF", "oreDictionary": [ "OD_STAFF" ], "toolType": "STAFF", "ai": "Staff", "speed": 10.0, "deviation": 0.03, "shootTimes": 1, "shootProjectileId": "ice_magic", "usePosture": 1, "useSound": "wand1", "coldTime": 40, "entityWidth": 16, "entityHeight": 48, "handX": 8, "handY": 32, "firePoints": [[8,8]], "holdType": "HOLD_STAFF", "twoHands": false, "damage": 12, "knockBack": 5, "crit": 3, "consumeMana": 5 } } ================================================ FILE: items/staffs/lighting_staff.json ================================================ { "lighting_staff": { "type": "TOOLS", "iconTextureData": "lighting_staff_entity.png", "textureData": "lighting_staff_entity.png", "group": "GROUP_STAFF", "oreDictionary": [ "OD_STAFF" ], "toolType": "STAFF", "ai": "Staff", "speed": 6.0, "deviation": 0.03, "shootTimes": 1, "shootProjectileId": "star", "usePosture": 1, "useSound": "wand1", "coldTime": 36, "entityWidth": 8, "entityHeight": 48, "handX": 4, "handY": 32, "firePoints": [[4,4]], "holdType": "HOLD_STAFF", "twoHands": false, "damage": 12, "knockBack": 5, "crit": 3, "consumeMana": 6 } } ================================================ FILE: items/staffs/shadow_staff.json ================================================ { "shadow_staff": { "type": "TOOLS", "iconTextureData": "shadow_staff_entity.png", "textureData": "shadow_staff_entity.png", "group": "GROUP_STAFF", "oreDictionary": [ "OD_STAFF" ], "toolType": "STAFF", "ai": "Staff", "speed": 6.0, "deviation": 0.05, "shootTimes": 1, "shootProjectileId": "shadow_magic", "usePosture": 1, "useSound": "wand1", "coldTime": 40, "entityWidth": 16, "entityHeight": 48, "handX": 8, "handY": 32, "firePoints": [[8,8]], "holdType": "HOLD_STAFF", "twoHands": false, "damage": 12, "knockBack": 5, "crit": 3, "consumeMana": 6 } } ================================================ FILE: items/staffs/soul_staff.json ================================================ { "soul_staff": { "type": "TOOLS", "iconTextureData": "soul_staff.png", "textureData": "soul_staff.png", "group": "GROUP_STAFF", "oreDictionary": [ "OD_STAFF" ], "toolType": "STAFF", "ai": "Staff", "speed": 8.0, "deviation": 0.05, "shootTimes": 1, "shootProjectileId": "magic_wave3", "usePosture": 1, "coldTime": 58, "entityWidth": 16, "entityHeight": 56, "handX": 8, "handY": 46, "firePoints": [[4,4]], "holdType": "HOLD_STAFF", "twoHands": false, "damage": 18, "knockBack": 1, "crit": 3, "consumeMana": 7, "useSound": "wand1" } } ================================================ FILE: items/staffs/water_staff.json ================================================ { "water_staff": { "type": "TOOLS", "iconTextureData": "water_staff_entity.png", "textureData": "water_staff_entity.png", "group": "GROUP_STAFF", "oreDictionary": [ "OD_STAFF" ], "toolType": "STAFF", "ai": "Staff", "speed": 12.0, "deviation": 0.05, "shootTimes": 1, "shootProjectileId": "water_magic", "usePosture": 1, "coldTime": 4, "entityWidth": 8, "entityHeight": 48, "handX": 4, "handY": 32, "firePoints": [[4,4]], "holdType": "HOLD_STAFF", "twoHands": false, "damage": 1, "knockBack": 1, "crit": 3, "consumeMana": 1 } } ================================================ FILE: items/swords/air_sword.json ================================================ { "air_sword": { "type": "TOOLS", "iconTextureData": "air_sword_entity.png", "textureData": "air_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "magic_sword", "coldTime": 24, "speed": 8.0, "deviation": 0.04, "shootTimes": 1, "shootProjectileId": "small_air_bullet", "entityWidth": 18, "entityHeight": 56, "firePoints": [[8,8]], "handX": 9, "handY": 48, "holdType": "NORMAL", "durable": 512, "damage": 8, "knockBack": 4, "crit": 4, "consumeMana": 4 } } ================================================ FILE: items/swords/bronze_sword.json ================================================ { "bronze_sword": { "type": "TOOLS", "iconTextureData": "bronze_sword_entity.png", "textureData": "bronze_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "firePoints": [[10,0]], "holdType": "NORMAL", "durable": 624, "damage": 11, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/copper_sword.json ================================================ { "copper_sword": { "type": "TOOLS", "iconTextureData": "copper_sword_entity.png", "textureData": "copper_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 412, "damage": 9, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/diamond_sword.json ================================================ { "diamond_sword": { "type": "TOOLS", "iconTextureData": "diamond_sword_entity.png", "textureData": "diamond_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 1552, "damage": 14, "knockBack": 5, "crit": 5 } } ================================================ FILE: items/swords/ghost_sword.json ================================================ { "ghost_sword": { "type": "TOOLS", "iconTextureData": "ghost_sword_entity.png", "textureData": "ghost_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 16, "entityWidth": 14, "entityHeight": 76, "handX": 8, "handY": 66, "holdType": "NORMAL", "durable": 624, "damage": 8, "knockBack": 1, "crit": 4, "enchantments": [ { "id": "smite", "level": 4 } ] } } ================================================ FILE: items/swords/golden_sword.json ================================================ { "golden_sword": { "type": "TOOLS", "iconTextureData": "golden_sword_entity.png", "textureData": "golden_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 22, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 788, "damage": 12, "knockBack": 4, "crit": 5 } } ================================================ FILE: items/swords/grass_sword.json ================================================ { "grass_sword": { "type": "TOOLS", "iconTextureData": "grass_sword_entity.png", "textureData": "grass_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 46, "handX": 10, "handY": 40, "firePoints": [[10,0]], "holdType": "NORMAL", "durable": 128, "damage": 3, "knockBack": 2, "crit": 3, "isNoBreaking": true, "enchantments": [ { "id": "phyton", "level": 1 } ] } } ================================================ FILE: items/swords/iron_sword.json ================================================ { "iron_sword": { "type": "TOOLS", "iconTextureData": "iron_sword_entity.png", "textureData": "iron_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 500, "damage": 10, "knockBack": 4, "crit": 4 } } ================================================ FILE: items/swords/lava_sword.json ================================================ { "lava_sword": { "type": "TOOLS", "iconTextureData": "lava_sword.png", "textureData": "lava_sword.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "LavaSword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 412, "damage": 12, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/lead_sword.json ================================================ { "lead_sword": { "type": "TOOLS", "iconTextureData": "lead_sword_entity.png", "textureData": "lead_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 500, "damage": 10, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/nether_sword.json ================================================ { "nether_sword": { "type": "TOOLS", "iconTextureData": "nether_sword_entity.png", "textureData": "nether_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 1820, "damage": 15, "knockBack": 5, "crit": 5, "antiLava": true } } ================================================ FILE: items/swords/silver_sword.json ================================================ { "silver_sword": { "type": "TOOLS", "iconTextureData": "silver_sword_entity.png", "textureData": "silver_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 788, "damage": 12, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/steel_sword.json ================================================ { "steel_sword": { "type": "TOOLS", "iconTextureData": "steel_sword_entity.png", "textureData": "steel_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 624, "damage": 11, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/stone_sword.json ================================================ { "stone_sword": { "type": "TOOLS", "iconTextureData": "stone_sword_entity.png", "textureData": "stone_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 26, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 262, "damage": 7, "knockBack": 4, "crit": 4 } } ================================================ FILE: items/swords/super_air_sword.json ================================================ { "super_air_sword": { "type": "TOOLS", "iconTextureData": "super_air_sword_entity.png", "textureData": "super_air_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "magic_sword", "coldTime": 20, "speed": 10.0, "deviation": 0.04, "shootTimes": 1, "shootProjectileId": "air_bullet", "entityWidth": 26, "entityHeight": 66, "firePoints": [[13,8]], "handX": 13, "handY": 54, "holdType": "NORMAL", "durable": 723, "damage": 10, "knockBack": 5, "crit": 4, "consumeMana": 5, "antiLava": true } } ================================================ FILE: items/swords/super_bronze_sword.json ================================================ { "super_bronze_sword": { "type": "TOOLS", "iconTextureData": "super_bronze_sword_entity.png", "textureData": "super_bronze_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 676, "damage": 12, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/super_copper_sword.json ================================================ { "super_copper_sword": { "type": "TOOLS", "iconTextureData": "super_copper_sword_entity.png", "textureData": "super_copper_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 456, "damage": 10, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/super_diamond_sword.json ================================================ { "super_diamond_sword": { "type": "TOOLS", "iconTextureData": "super_diamond_sword_entity.png", "textureData": "super_diamond_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 62, "handX": 10, "handY": 54, "holdType": "NORMAL", "durable": 1642, "damage": 15, "knockBack": 5, "crit": 5 } } ================================================ FILE: items/swords/super_golden_sword.json ================================================ { "super_golden_sword": { "type": "TOOLS", "iconTextureData": "super_golden_sword_entity.png", "textureData": "super_golden_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 22, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 820, "damage": 13, "knockBack": 4, "crit": 5 } } ================================================ FILE: items/swords/super_iron_sword.json ================================================ { "super_iron_sword": { "type": "TOOLS", "iconTextureData": "super_iron_sword_entity.png", "textureData": "super_iron_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 558, "damage": 11, "knockBack": 4, "crit": 4 } } ================================================ FILE: items/swords/super_lead_sword.json ================================================ { "super_lead_sword": { "type": "TOOLS", "iconTextureData": "super_lead_sword_entity.png", "textureData": "super_lead_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 558, "damage": 11, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/super_nether_sword.json ================================================ { "super_nether_sword": { "type": "TOOLS", "iconTextureData": "super_nether_sword_entity.png", "textureData": "super_nether_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 62, "handX": 10, "handY": 54, "holdType": "NORMAL", "durable": 2020, "damage": 16, "knockBack": 5, "crit": 5, "antiLava": true } } ================================================ FILE: items/swords/super_silver_sword.json ================================================ { "super_silver_sword": { "type": "TOOLS", "iconTextureData": "super_silver_sword_entity.png", "textureData": "super_silver_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 66, "handX": 10, "handY": 56, "holdType": "NORMAL", "durable": 820, "damage": 13, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/super_steel_sword.json ================================================ { "super_steel_sword": { "type": "TOOLS", "iconTextureData": "super_steel_sword_entity.png", "textureData": "super_steel_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 16, "entityWidth": 22, "entityHeight": 72, "handX": 10, "handY": 62, "holdType": "NORMAL", "durable": 676, "damage": 11, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/super_tin_sword.json ================================================ { "super_tin_sword": { "type": "TOOLS", "iconTextureData": "super_tin_sword_entity.png", "textureData": "super_tin_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 456, "damage": 10, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/tin_sword.json ================================================ { "tin_sword": { "type": "TOOLS", "iconTextureData": "tin_sword_entity.png", "textureData": "tin_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 24, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 412, "damage": 9, "knockBack": 3, "crit": 4 } } ================================================ FILE: items/swords/wooden_sword.json ================================================ { "wooden_sword": { "type": "TOOLS", "iconTextureData": "wooden_sword_entity.png", "textureData": "wooden_sword_entity.png", "group": "GROUP_SWORD", "oreDictionary": [ "OD_SWORD" ], "toolType": "SWORD", "ai": "Sword", "coldTime": 28, "entityWidth": 22, "entityHeight": 56, "handX": 10, "handY": 48, "holdType": "NORMAL", "durable": 140, "damage": 5, "knockBack": 3, "crit": 4, "fuelTime": 40 } } ================================================ FILE: items/wires/blue_wire.json ================================================ { "blue_wire": { "type": "WIRES", "iconTextureData": "blue_wire_icon.png", "wireId": 3, "group": "GROUP_REDSTONE_WIRE" } } ================================================ FILE: items/wires/green_wire.json ================================================ { "green_wire": { "type": "WIRES", "iconTextureData": "green_wire_icon.png", "wireId": 2, "group": "GROUP_REDSTONE_WIRE" } } ================================================ FILE: items/wires/red_wire.json ================================================ { "red_wire": { "type": "WIRES", "iconTextureData": "red_wire_icon.png", "wireId": 1, "group": "GROUP_REDSTONE_WIRE" } } ================================================ FILE: items/wires/yellow_wire.json ================================================ { "yellow_wire": { "type": "WIRES", "iconTextureData": "yellow_wire_icon.png", "wireId": 4, "group": "GROUP_REDSTONE_WIRE" } } ================================================ FILE: languages/Locale.lua ================================================ local Locale = { BACK = "", DESC = "", WEB = "", OK = "", SINGLE_PLAYER = "", MULTI_PLAYER = "", MOD_LIST = "", COMMUNITY = "", SETTING = "", EXIT_GAME = "", COPYRIGHT = "", MOD_LOADER_INFO = "", ENGINE_VERSION = "", OPEN_MOD_FOLDER = "", MANAGER_SOURCES = "", ALL_MOD_LOADED = "", MOD_VERSION = "", MOD_AUTHORS = "", MOD_FOLDER_UNSUPPORTED = "", WEB_SOURCE_GITHUB = "", WEB_HOME = "", BACK_TO_GAME = "", RECIPE_SEARCH = "", ADVANCEMENT = "", SAVE_AND_EXIT = "", GAME_MENU = "", LOADING = "", SELECT_LANGUAGE = "", LANGUAGE_LIST = "", LANGUAGE_MAY_WRONG = "", SELECT_PLAYER = "", ARRANGE = "", QUICK_PICK = "", QUICK_PUSH = "", QUICK_STACK = "", STORAGE = "", PRE_ITEM = "", SEARCH_FROM_OUTPUT = "", SEARCH_FROM_INPUT = "", SOUND = "", SETTING_PANEL = "", CREATE_WORLD = "", MORE_SETTINGS = "", SURVIVAL_MODE = "", BP_SHARED_MODE = "", WORLD_SEED_Q = "", WORLD_NAME_Q = "", CREATE_NEW_WORLD = "", ENTER_WORLD = "", NEW_WORLD_B = "", SELECT_WORLD = "", CHANGE_POSTURE = "", NAME_Q = "", CREATE_PLAYER = "", NEW_PLAYER_B = "", TIPS = "", GET_ADVANCEMENT = "", EQUIPMENT = "", CRAFT = "", APPEAR_ACCESSORY = "", INVENTORY = "", FURNACE = "", ENCHANT = "", REPAIR = "", BREWING_STAND = "", YOU_DIED = "", PENDING_SAVING = "", PENDING_NO_CONNECTION = "", RESPAWNING = "", GAME_VER = "", FORCE_NEW_PLAYER_MODE = "", SURE_TO_DELETE_WORLD_1 = "", SURE_TO_DELETE_WORLD_2 = "", SURE_TO_DELETE_PLAYER_1 = "", SURE_TO_DELETE_PLAYER_2 = "", TIME_COST = "", BURN_TIME_COST = "", } return Locale ================================================ FILE: languages/LocaleHelper.lua ================================================ local LocaleHelper = class("LocaleHelper") function LocaleHelper.reload(locale) for name, _ in pairs(locale) do local modText = LangUtils.ModText(name) if modText ~= nil and modText ~= "" then locale[name] = modText end local content = locale[name] if content == "" then locale[name] = string.format("@[%s]", name) print("Locale Missing: " .. locale[name]) end end end return LocaleHelper ================================================ FILE: languages/chinese.json ================================================ { "modTexts": [ [ "BACK", "返回" ], [ "DESC", "描述" ], [ "WEB", "网站" ], [ "OK", "确定" ], [ "SINGLE_PLAYER", "单人游戏" ], [ "MULTI_PLAYER", "多人游戏" ], [ "MOD_LIST", "模组列表"], [ "COMMUNITY", "社区" ], [ "SETTING", "选项" ], [ "EXIT_GAME", "退出游戏" ], [ "COPYRIGHT", "BlueYoshi.cn/TerraCraft 进击的蓝耀西(Bilibili)" ], [ "MOD_LOADER_INFO", "[模组加载器] 已加载%d个模组" ], [ "ENGINE_VERSION", "引擎版本 %s" ], [ "OPEN_MOD_FOLDER", "打开模组文件夹" ], [ "MANAGER_SOURCES", "管理源码.." ], [ "ALL_MOD_LOADED", "所有模组(已加载:%d)" ], [ "MOD_VERSION", "模组版本" ], [ "MOD_AUTHORS", "模组作者" ], [ "MOD_FOLDER_UNSUPPORTED", "移动端不支持打开模组文件夹功能。" ], [ "WEB_SOURCE_GITHUB", "源代码仓库(Github)" ], [ "WEB_HOME", "主页" ], [ "BACK_TO_GAME", "返回游戏" ], [ "RECIPE_SEARCH", "配方查询" ], [ "ADVANCEMENT", "成就" ], [ "SAVE_AND_EXIT", "保存并退出" ], [ "GAME_MENU", "游戏菜单" ], [ "LOADING", "加载中" ], [ "SELECT_LANGUAGE", "选择语言" ], [ "LANGUAGE_LIST", "语言列表" ], [ "LANGUAGE_MAY_WRONG", "翻译并不是100%准确,如发现文本错误,请联系我们。" ], [ "SELECT_PLAYER", "选择玩家" ], [ "ARRANGE", "整理" ], [ "QUICK_PICK", "快速取出" ], [ "QUICK_PUSH", "快速放入" ], [ "QUICK_STACK", "快速堆叠" ], [ "STORAGE", "存储" ], [ "PRE_ITEM", "上一项" ], [ "SEARCH_FROM_OUTPUT", "从产物搜索" ], [ "SEARCH_FROM_INPUT", "从原料搜索" ], [ "SOUND", "音频" ], [ "SETTING_PANEL", "设置面板" ], [ "CREATE_WORLD", "创建世界" ], [ "MORE_SETTINGS", "更多设置.." ], [ "SURVIVAL_MODE", "生存模式" ], [ "BP_SHARED_MODE", "背包共享模式" ], [ "WORLD_SEED_Q", "世界种子:" ], [ "WORLD_NAME_Q", "世界名称:" ], [ "CREATE_NEW_WORLD", "创建新世界" ], [ "ENTER_WORLD", "进入世界!" ], [ "NEW_WORLD_B", "新世界.." ], [ "SELECT_WORLD", "选择世界" ], [ "CHANGE_POSTURE", "换个姿势" ], [ "NAME_Q", "名称:" ], [ "CREATE_PLAYER", "创建玩家" ], [ "NEW_PLAYER_B", "新玩家.." ], [ "TIPS", "提示" ], [ "GET_ADVANCEMENT", "获得成就!" ], [ "EQUIPMENT", "装备" ], [ "CRAFT", "合成" ], [ "APPEAR_ACCESSORY", "外观/饰品" ], [ "INVENTORY", "背包" ], [ "FURNACE", "熔炉" ], [ "ENCHANT", "附魔" ], [ "REPAIR", "修复" ], [ "BREWING_STAND", "酿造台" ], [ "YOU_DIED", "你 死 了" ], [ "PENDING_SAVING", "保存数据中...请不要断开电源" ], [ "PENDING_NO_CONNECTION", "与服务器连接中断,已安全退出..." ], [ "RESPAWNING", "重生中... %d" ], [ "GAME_VER", "(电脑/手机互通版)游戏版本 %s" ], [ "FORCE_NEW_PLAYER_MODE", "强制开荒模式" ], [ "SURE_TO_DELETE_WORLD_1", "确定删除" ], [ "SURE_TO_DELETE_WORLD_2", "吗?该世界将被永远删除!" ], [ "SURE_TO_DELETE_PLAYER_1", "确定删除" ], [ "SURE_TO_DELETE_PLAYER_2", "吗?该玩家将被永远删除!" ], [ "TIME_COST", "耗时: %.2f秒" ], [ "BURN_TIME_COST", "燃烧耗时: %.2f秒" ], [ "help:kill", "杀死自己" ], [ "help:killp", "杀死指定玩家" ], [ "help:buff", "添加BUFF并设定时长" ], [ "help:buffp", "添加BUFF到指定玩家并设定时长" ], [ "help:spawn", "传送到出生点" ], [ "help:home", "传送到重生点" ], [ "help:ex", "增加经验值" ], [ "help:exp", "增加指定玩家经验值" ], [ "help:give", "给予物品并设定数量" ], [ "help:givep", "给予玩家物品并设定数量" ], [ "help:gamemode", "设定自己的游戏模式" ], [ "help:gamemodep", "设定指定玩家的游戏模式" ], [ "help:gamemodew", "设定世界的游戏模式" ], [ "help:npc", "在指定位置生成一个NPC" ], [ "help:effect", "在指定位置生成一个特效" ], [ "help:tp", "传送到指定位置" ], [ "help:tpp", "传送玩家到指定位置" ], [ "help:me", "显示一条关于自己的信息" ], [ "help:msg", "向指定玩家发送一条私信" ], [ "help:say", "广播一条消息" ], [ "help:clear", "清空背包" ], [ "help:clearp", "清空指定玩家的背包" ], [ "help:day", "设置当日时间" ], [ "help:dayf", "依次设置当日时间的 小时 分钟 秒" ], [ "help:dayspeed", "设置时间的流逝速度" ], [ "help:daylock", "锁定昼夜更替时间" ], [ "help:dayunlock", "取消锁定昼夜更替时间" ], [ "help:wea", "设置天气时间" ], [ "help:stopwea", "取消天气事件" ], [ "help:admin", "赋予指定玩家管理员权限" ], [ "help:noadmin", "取消指定玩家管理员权限" ], [ "help:master", "赋予指定玩家服主权限" ], [ "help:nomaster", "取消指定玩家服主权限" ], [ "help:save", "立即保存世界全部数据" ], [ "help:autosave-on", "开启自动保存功能" ], [ "help:autosave-off", "取消自动保存功能" ], [ "help:port", "查看服务器端口号" ], [ "help:state", "查看服务器运行状态" ], [ "help:pvp-on", "开启PVP模式" ], [ "help:pvp-off", "关闭PVP模式" ], [ "help:safeblow-on", "开启爆炸保护模式" ], [ "help:safeblow-off", "关闭爆炸保护模式" ], [ "help:players", "查看所有在线玩家" ], [ "help:kick", "将指定玩家踢出游戏" ], [ "help:kickall", "将全部玩家踢出游戏" ], [ "help:banip", "将指定IP加入服务器黑名单" ], [ "help:nobanip", "将指定IP移出服务器黑名单" ], [ "help:blacklist", "查看游戏黑名单" ], [ "help:enchant", "对手持物品进行附魔并设置附魔等级" ], [ "help:blueyoshiiscool", "神秘指令" ], [ "ex_ok", "给予玩家 %s 经验值 %d" ], [ "buff_ok", "给予玩家 %s 状态效果 %s 时长 %d 秒" ], [ "em_ok", "给予玩家 %s 手持物品 %s 附魔 %s 等级 %d" ], [ "em_fail", "附魔失败" ], [ "spawn_ok", "传送玩家 %s 到出生点" ], [ "home_ok", "传送玩家 %s 到重生点" ], [ "home_fail", "玩家 %s 没有重生点记录" ], [ "give_ok", "给予 %s 物品 %s * %d" ], [ "clear_ok", "已清空玩家 %s 的背包" ], [ "day_ok", "已设置当前日间时间为 %02d:%02d:%02d" ], [ "dayspeed_ok", "已设置时间流逝速度为 %.2f 倍" ], [ "wea_ok", "当前天气进度 %d%%" ], [ "admin_ok", "已将玩家 %s 设置为管理员" ], [ "noadmin_ok", "已取消玩家 %s 的管理员权限" ], [ "master_ok", "已将玩家 %s 设置为服主" ], [ "nomaster_ok", "已取消玩家 %s 的服主权限" ], [ "save_ok", "已将 [立即保存] 加入服务端处理队列" ], [ "player_info", "(%d) %s (%s:%d)" ], [ "players_ok", "总共 %d 人在线" ], [ "autosave_on_ok", "已开启 [自动保存] 功能" ], [ "autosave_off_ok", "已关闭 [自动保存] 功能" ], [ "pvp_on_ok", "已开启PVP" ], [ "pvp_off_ok", "已关闭PVP" ], [ "safeblow_on_ok", "已开启 [爆炸保护] 功能" ], [ "safeblow_off_ok", "已关闭 [爆炸保护] 功能" ], [ "port_ok", "服务器端口号为 %d" ], [ "kick_ok", "已踢出 %s" ], [ "blacklist_info", "(%d) %s" ], [ "blacklist_ok", "黑名单共有 %d 项" ], [ "banip_ok", "已封禁 IP %s 并加入到服务器黑名单" ], [ "nobanip_ok", "已将 IP %s 移出服务器黑名单" ], [ "nobanip_fail", "IP %s 不存在于服务器黑名单" ], [ "gamemodep_s_ok", "玩家 %s 的游戏模式已变更为生存模式" ], [ "gamemodep_c_ok", "玩家 %s 的游戏模式已变更为创造模式" ], [ "gamemodep_a_ok", "玩家 %s 的游戏模式已变更为冒险模式" ], [ "gamemodew_s_ok", "当前世界的游戏模式已变更为生存模式" ], [ "gamemodew_c_ok", "当前世界的游戏模式已变更为创造模式" ], [ "gamemodew_a_ok", "当前世界的游戏模式已变更为冒险模式" ], [ "msg_content", "[来自玩家 %s 的私信] %s" ], [ "msg_server_content", "[来自服务端的私信] %s" ], [ "msg_to_content", "[给玩家 %s 的私信] %s" ], [ "msg_server_to_content", "[给玩家 %s 的私信] %s" ], [ "say", "[服务器] %s" ], [ "npc_ok", "已生成 %s 于 (%d, %d)" ], [ "tp_ok", "将玩家 %s 传送到 (%d, %d)" ], [ "blueyoshiiscool_ok", "蓝耀西真酷!!!" ] ], "enchantments": [ [ "silk_touch", "精准采集" ], [ "fortune", "时运" ], [ "phyton", "再生" ], [ "unbreaking", "耐久" ], [ "efficiency", "效率" ], [ "aqua_affinity", "水下速掘" ], [ "bane_of_arthropods", "节肢杀手" ], [ "blast_protection", "爆炸保护" ], [ "curse_of_binding", "绑定诅咒" ], [ "curse_of_vanishing", "消失诅咒" ], [ "depth_strider", "深海探索者" ], [ "feather_falling", "摔落保护" ], [ "fire_aspect", "火焰附加" ], [ "fire_protection", "火焰保护" ], [ "flame", "火矢" ], [ "frost_walker", "冰霜使者" ], [ "infinity", "无限" ], [ "knockback", "击退" ], [ "looting", "抢夺" ], [ "luck_of_the_sea", "海之眷顾" ], [ "lure", "饵钓" ], [ "multishot", "多重射击" ], [ "piercing", "穿透" ], [ "power", "力量" ], [ "projectile_protection", "弹射物保护" ], [ "protection", "保护" ], [ "punch", "冲击" ], [ "quick_charge", "快速装填" ], [ "respiration", "水下呼吸" ], [ "sharpness", "锋利" ], [ "smite", "亡灵杀手" ], [ "thorns", "荆棘" ] ], "buffs": [ [ "absorption", "吸血" ], [ "blindness", "失明" ], [ "fire", "着火" ], [ "fire_defense", "防火" ], [ "glowing", "发光" ], [ "happiness", "高兴" ], [ "health_boost", "生命提升" ], [ "hunger", "饥饿" ], [ "hurt", "受伤" ], [ "invisibility", "隐身" ], [ "jump_boost", "跳跃提升" ], [ "levitation", "漂浮" ], [ "luck", "幸运" ], [ "mining_fatique", "急迫" ], [ "nausea", "反胃" ], [ "poison", "中毒" ], [ "regeneration", "生命恢复" ], [ "resistance", "抗性提升" ], [ "sadness", "伤心" ], [ "slow_falling", "缓降" ], [ "slow_mining", "挖掘疲劳" ], [ "slowness", "缓慢" ], [ "speed", "速度" ], [ "strength", "力量" ], [ "vision", "夜视" ], [ "water_breathing", "水下呼吸" ], [ "weak", "虚弱" ], [ "wither", "凋零" ], [ "health_cold", "回复冷却" ] ], "advancements": [ [ "inventory", "开始冒险", "初次进入泰拉世界" ], [ "wood", "获得木头", "使用斧头砍倒一棵树以获得木头方块" ], [ "crafting_table", "这是?工作台!", "用四个木板来制作一个工作台" ], [ "farm", "耕种时间到!", "使用木板和木棍来制作木锄" ], [ "bread", "烤面包", "用小麦来做面包" ], [ "cake", "蛋糕是个谎言", "小麦、糖、牛奶和鸡蛋!" ], [ "bow", "弓箭手!", "使用丝线和木棍制作一把弓" ], [ "crossbow", "弩箭手!", "制作一把驽" ], [ "mine", "采矿时间到!", "使用木板和木棍来制作木镐" ], [ "stone", "石器时代", "用你的新镐挖掘石头" ], [ "mine_up", "获得升级", "制作一把更好的石镐" ], [ "furnace", "热门话题", "用八个圆石来制作一个熔炉" ], [ "iron", "来硬的", "冶炼出一块金属锭" ], [ "sword", "出击时间到!", "使用木板和木棍来制作一把木剑!" ], [ "leather", "斗牛士", "获得一些皮革" ], [ "hunter", "怪物猎人", "攻击并消灭一只怪物" ], [ "staff", "魔力法杖", "制作一个消耗魔力的法杖" ], [ "magic_limit", "魔法师", "吃掉一个提高魔法上限的魔法碎片" ], [ "ender_pearl", "小黑杀手", "获得一个末影珍珠" ], [ "steel", "精炼铁!", "烧制铁锭得到一个钢锭" ], [ "bronze", "青铜时代", "获得一个青铜锭" ], [ "diamond", "钻石!", "挖一些钻石吧" ], [ "enchant", "附魔师", "使用书、黑曜石以及钻石来制作一个附魔台" ], [ "nether", "还需要更深一些", "深入地狱层" ], [ "blaze_rod", "与火共舞", "得到烈焰人的烈焰棒" ], [ "brew", "本地的酿造厂", "制造一个酿造台" ], [ "ghast", "见鬼去吧!", "干掉一只恶魂" ], [ "netherite", "深藏不露", "获得远古残骸" ], [ "gun", "军火商", "在地狱要塞中获得一把枪支" ], [ "redstone", "发现红石!", "获得一个红石粉末" ], [ "redstone_wire", "红石科技", "制作一根红石电线" ], [ "lava", "超级燃料", "盛装一桶岩浆" ], [ "pumpkin_helmet", "万圣节!", "制作一个万圣节风格的南瓜头盔" ], [ "ender_chest", "异度空间", "制作一个末影箱" ], [ "guardian", "入侵者!", "击败一只海底守卫者" ], [ "snow_queen", "冰雪女王!", "从冰雪女王球中唤醒冰雪女王" ], [ "snow_queen_killed", "解放极光宫殿", "击杀冰雪女王" ], [ "nether_destroyer", "毁灭地狱!", "破坏地狱祭坛释放地狱毁灭者" ], [ "nether_destroyer_killed", "拯救地狱", "击杀地狱毁灭者" ], [ "diamond_wear", "用钻石包裹我", "穿上全套钻石盔甲" ], [ "netherite_full_wear", "残骸裹身", "穿上一整套下界合金盔甲" ], [ "go_ghost_house", "别惹鬼魂!", "探索鬼屋" ], [ "go_bone_dungeon", "挺进骷髅地牢!", "探索骷髅地牢" ], [ "go_dark_dungeon", "暗黑地牢!", "探索暗黑地牢" ], [ "go_deep_snow", "可怕的雪洞!", "探索雪洞" ], [ "go_ice_dungeon", "发现冰雪地牢!", "探索冰雪地牢" ], [ "go_lava_dungeon", "庞大的熔岩城堡!", "探索熔岩城堡" ], [ "go_desert_dungeon", "深入金字塔!", "探索金字塔" ], [ "strange_len", "晶状体提取者", "杀死一个恶魔眼" ], [ "crison_eye", "克苏鲁之眼!", "制作克苏鲁之眼召唤物,召唤克苏鲁之眼" ], [ "crison_eye_killed", "盯着你", "打败克苏鲁之眼" ], [ "dungeon_eater", "吃掉地牢!", "在暗黑地牢召唤地牢吞噬者" ], [ "dungeon_eater_killed", "地牢英雄", "打败地牢吞噬者" ], [ "rocket_boost", "我能飞了!", "找到或制作火箭靴" ], [ "snow_guard", "极光宫殿入门", "杀死一个冰雪守卫" ], [ "portal", "传送门!", "使用一次传送门" ], [ "mine_copper", "获得升级II", "制作一把铜镐或锡镐" ], [ "mine_iron", "获得升级III", "制作一把铁镐或铅镐" ], [ "mine_bronze", "获得升级IV", "制作一把青铜镐或钢镐" ], [ "mine_gold", "获得升级V", "制作一把金镐或银镐" ], [ "mine_diamond", "极速挖掘", "制作一把钻石镐" ], [ "mine_netherite", "镐子终结者", "制作一把下届合金镐" ], [ "repair", "耐久修复学", "制作一个铁砧" ], [ "recipe_book", "快速合成!", "使用配方书进行快速合成" ], [ "mirror", "回家的诱惑", "使用末影魔镜快速传送回家" ], [ "gold", "黄金!", "获得一个金锭" ], [ "gold_wear", "金色传说", "穿上全套金盔甲" ], [ "super_diamond_sword", "锋利的钻石", "制作一把强化钻石剑" ], [ "ghost_crystal", "塔防入门", "杀死迷你幽魂,获得一个幽魂碎片" ], [ "ghost", "压榨劳动力!", "制作一个幽魂" ], [ "ice_element_ball", "冰雪元素球", "制作一个冰雪元素球" ], [ "diamond_ingot", "魔法钻石!", "使用四种水晶和钻石合成一颗魔法钻石" ], [ "ancient_ingot", "远古力量!", "获得一块远古合金" ], [ "ancient_wear", "毕业了?", "穿上全套远古套装" ], [ "super_diamond_wear", "魔法钻石包裹我", "穿上全套强化钻石套装" ], [ "knight_ingot", "神秘的骑士锭", "获得一块骑士锭" ], [ "knight_wear", "真正的骑士", "穿上全套骑士套装" ], [ "star_wear", "星空!", "穿上全套星空套装" ], [ "flesh_ingot", "染血的金属", "获得一个血腥锭" ], [ "flesh_wear", "嗜血套装", "穿上全套血腥盔甲" ], [ "magic_gold_wear", "魔法金色传说", "穿上全套魔金盔甲" ] ], "npcs": [ [ "pig", "猪" ], [ "zombie", "僵尸" ], [ "husk", "尸壳" ], [ "mummy", "木乃伊" ], [ "waste_mummy", "废土木乃伊" ], [ "villager_zombie", "僵尸村民" ], [ "arrow_zombie", "中箭僵尸" ], [ "bald_zombie", "秃头僵尸" ], [ "doge_zombie", "狗头僵尸" ], [ "iron_zombie", "钢铁僵尸" ], [ "skeleton", "骷髅" ], [ "tainted_skeleton", "腐化骷髅" ], [ "blood_skeleton", "血腥骷髅" ], [ "angry_skeleton", "愤怒的骷髅" ], [ "black_skeleton", "黝黑骷髅" ], [ "boney_skeleton", "多骨骷髅" ], [ "creeper", "苦力怕" ], [ "flower_creeper", "花花苦力怕" ], [ "tainted_creeper", "腐化苦力怕" ], [ "spider", "蜘蛛" ], [ "bat", "蝙蝠" ], [ "jungle_bat", "丛林蝙蝠" ], [ "large_jungle_bat", "吐舌丛林蝙蝠" ], [ "blood_bat", "血腥蝙蝠" ], [ "man_eater", "食人花" ], [ "blood_eye", "血腥之眼" ], [ "chicken", "鸡" ], [ "cow", "牛" ], [ "sheep", "羊" ], [ "red_mushroom_cow", "红哞菇" ], [ "brown_mushroom_cow", "棕哞菇" ], [ "cat", "猫咪" ], [ "white_rabbit", "小白兔" ], [ "brown_rabbit", "小棕兔" ], [ "black_rabbit", "小黑兔" ], [ "yellow_rabbit", "小黄兔" ], [ "squid", "鱿鱼" ], [ "turtle", "乌龟" ], [ "pufferfish", "河豚" ], [ "dolphin", "海豚" ], [ "wolf", "狼" ], [ "enderman", "末影人" ], [ "zombie_pigman", "僵尸猪人" ], [ "blaze", "烈焰人" ], [ "drowned", "溺尸" ], [ "guardian", "守卫者" ], [ "ghast", "恶魂" ], [ "ice_elf", "冰精" ], [ "magma_elf", "熔岩精灵" ], [ "waste_ghost", "废土幽灵" ], [ "large_block_slime", "大方块史莱姆" ], [ "block_slime", "方块史莱姆" ], [ "large_ice_slime", "大冰块史莱姆" ], [ "ice_slime", "冰块史莱姆" ], [ "large_waste_block_slime", "大废土方块史莱姆" ], [ "waste_block_slime", "废土方块史莱姆" ], [ "green_slime", "绿史莱姆" ], [ "large_green_slime", "大型绿史莱姆" ], [ "large_black_slime", "大型黑史莱姆" ], [ "large_waste_slime", "大型废土史莱姆" ], [ "large_tainted_slime", "大型腐化史莱姆" ], [ "blood_slime", "血腥史莱姆" ], [ "yellow_slime", "黄史莱姆" ], [ "desert_slime", "沙漠史莱姆" ], [ "large_desert_slime", "大型沙漠史莱姆" ], [ "blue_slime", "蓝史莱姆" ], [ "purple_slime", "紫史莱姆" ], [ "snow_slime", "雪史莱姆" ], [ "tainted_slime", "腐化史莱姆" ], [ "magma_slime", "岩浆史莱姆" ], [ "phantom", "幻翼" ], [ "eagle", "老鹰" ], [ "magma_birdo", "烈焰鸟" ], [ "meteor", "陨石怪" ], [ "shulker", "潜影贝" ], [ "evoker", "唤魔者" ], [ "wither_skeleton", "凋灵骷髅" ], [ "ender_dragon", "末影龙" ], [ "light_blue_butterfly", "浅蓝色蝴蝶" ], [ "yellow_butterfly", "黄蝴蝶" ], [ "red_butterfly", "红蝴蝶" ], [ "worm_head", "地狱毁灭者" ], [ "worm_body", "地狱毁灭者" ], [ "worm_tail", "地狱毁灭者" ], [ "vine_man_eater_head", "食人蛇" ], [ "vine_man_eater_body", "食人蛇" ], [ "vine_man_eater_tail", "食人蛇" ], [ "snow_queen", "冰雪女王" ], [ "small_hell_eater", "地狱啃食者" ], [ "snow_guardian", "冰雪守卫" ], [ "snow_guardian_archer", "冰雪守卫弓箭手" ], [ "small_fire_hell_eater", "火焰啃食者" ] ], "projectiles": [ [ "wooden_arrow", "木箭" ], [ "lighting_arrow", "光灵箭" ], [ "star_arrow", "坠星箭" ], [ "blood_arrow", "血腥箭" ], [ "ice_arrow", "冰霜箭" ], [ "sword_arrow", "剑气" ], [ "air_bullet", "空气弹" ], [ "small_air_bullet", "空气弹" ], [ "amethyst_magic", "紫水晶魔法" ], [ "star", "星星魔法" ], [ "ice_magic", "冰霜魔法" ], [ "shadow_magic", "影流魔法" ], [ "water_magic", "水魔法" ], [ "fire_magic", "火焰魔法" ], [ "crystal_magic", "水晶魔法" ], [ "ice_bullet", "冰弹" ], [ "boomerang", "回旋镖" ], [ "wooden_boomerang", "木制回旋镖" ], [ "fire_boomerang", "烈焰回旋镖" ], [ "rocket", "火箭弹" ], [ "blaze_rod", "烈焰防护盾" ], [ "fire_charge", "火球" ], [ "shulker_bullet", "跟踪魔法" ], [ "bullet", "子弹" ], [ "gun_fire", "火焰" ], [ "bullet_laser", "激光" ], [ "bullet_super", "子弹" ], [ "tnt", "TNT" ], [ "bomb", "炸弹" ], [ "grenade", "手榴弹" ], [ "glow_bomb", "照明炸弹" ], [ "glow_ball", "光球" ], [ "snow_flake", "雪花" ] ], "items": [ [ "stone_axe", "石斧", "石制的斧头,比木制的更高效" ], [ "dirt", "泥土", "大量覆盖在地表的方块" ], [ "stone", "石头", "表面更平滑的石头" ], [ "cobblestone", "圆石", "基础石制材料,比石头稍稍粗糙" ], [ "stick", "木棍", "这是一根木制的棍子" ], [ "gravel", "沙砾", "混杂着各种杂质的沙砾" ], [ "sand", "沙子", "松软的沙子,玻璃的来源" ], [ "ore_coal", "煤矿石", "矿物原矿,需要进一步加工" ], [ "ore_iron", "铁矿石", "矿物原矿,需要进一步加工" ], [ "ore_gold", "金矿石", "矿物原矿,需要进一步加工" ], [ "ore_lapis", "青金石矿石", "矿物原矿,需要进一步加工" ], [ "ore_redstone", "红石矿石", "矿物原矿,需要进一步加工" ], [ "ore_diamond", "钻石矿石", "矿物原矿,需要进一步加工" ], [ "ore_emerald", "绿宝石矿石", "矿物原矿,需要进一步加工" ], [ "stone_pickaxe", "石镐", "石制的镐子" ], [ "stone_sword", "石剑", "石头打造而成的剑" ], [ "furnace", "熔炉", "烧炼或者烹饪物品" ], [ "chest", "箱子", "存储物品" ], [ "oak_plank", "橡木木板", "常用的木制建筑材料" ], [ "grass_axe", "杂草斧", "最初级的斧头,具有无尽的再生能力" ], [ "grass_pickaxe", "杂草镐", "最初级的镐子,具有无尽的再生能力" ], [ "grass_sword", "杂草剑", "一把弱不禁风的杂草剑" ], [ "iron_ingot", "铁锭", "" ], [ "gold_ingot", "金锭", "" ], [ "redstone_ingot", "红石锭", "" ], [ "copper_ingot", "铜锭", "" ], [ "tin_ingot", "锡锭", "" ], [ "bronze_ingot", "青铜锭", "" ], [ "lead_ingot", "铅锭", "" ], [ "silver_ingot", "银锭", "" ], [ "steel_ingot", "钢锭", "" ], [ "lithium_ingot", "锂锭", "" ], [ "beryllium_ingot", "铍锭", "" ], [ "sodium_ingot", "钠锭", "" ], [ "magnesium_ingot", "镁锭", "" ], [ "aluminum_ingot", "铝锭", "" ], [ "titanium_ingot", "钛锭", "" ], [ "vanadium_ingot", "钒锭", "" ], [ "chromium_ingot", "铬锭", "" ], [ "manganese_ingot", "锰锭", "" ], [ "cobalt_ingot", "钴锭", "" ], [ "nickel_ingot", "镍锭", "" ], [ "zinc_ingot", "锌锭", "" ], [ "gallium_ingot", "镓锭", "" ], [ "yttrium_ingot", "钇锭", "" ], [ "niobium_ingot", "铌锭", "" ], [ "molybdenum_ingot", "钼锭", "" ], [ "palladium_ingot", "钯锭", "" ], [ "indium_ingot", "铟锭", "" ], [ "antimony_ingot", "锑锭", "" ], [ "tantalum_ingot", "钽锭", "" ], [ "wolfram_ingot", "钨锭", "" ], [ "rhenium_ingot", "铼锭", "" ], [ "osmium_ingot", "锇锭", "" ], [ "iridium_ingot", "铱锭", "" ], [ "platinum_ingot", "铂锭", "" ], [ "bismuth_ingot", "铋锭", "" ], [ "vibranium_ingot", "振金锭", "" ], [ "andesite", "安山岩", "一种石头的变种,富含钙碱性" ], [ "andesite_polished", "磨制安山岩", "抛光后的安山岩材料" ], [ "clay", "粘土", "这是一个粘土球" ], [ "cobblestone_mossy", "青苔圆石", "布满青苔的圆石" ], [ "diorite", "闪长岩", "一种石头的变种" ], [ "diorite_polished", "磨制闪长岩", "抛光后的安山岩材料" ], [ "glass", "玻璃", "可透光的玻璃" ], [ "granite", "花岗岩", "一种石头的变种" ], [ "granite_polished", "磨制花岗岩", "抛光后的安山岩材料" ], [ "ice", "冰块", "寒冷又易碎的冰块" ], [ "ice_cobblestone", "碎冰石", "冷冻的石头,表面覆盖着坚硬的表层" ], [ "ice_packed", "浮冰", "易碎的浮冰,内部独特的结构使得它不会融化" ], [ "obsidian", "黑曜石", "岩浆遇水瞬间冷却形成,有着很高的硬度" ], [ "prismarine", "海晶石", "海底遗迹的建筑材料" ], [ "prismarine_brick", "海晶石砖", "有着锯齿条纹的海晶石砖" ], [ "prismarine_dark", "暗海晶石", "暗色的海晶石,有着网格状图案" ], [ "red_sand", "红沙", "富含氧化铁的红色沙子" ], [ "red_sand_carved", "錾制红沙石", "雕刻过的红沙石砖块" ], [ "red_sand_smooth", "平滑沙石", "表面平滑的红沙石砖块" ], [ "sandstone", "沙石", "硬质的沙子" ], [ "sandstone_carved", "錾制沙石", "雕刻过的沙石砖块" ], [ "sandstone_smooth", "平滑沙石", "表面平滑的沙石砖块" ], [ "snow", "雪块", "松软的雪块" ], [ "stone_brick", "石砖", "一种建筑用石制材料" ], [ "stone_brick_carved", "錾制石砖", "雕刻过的石制建筑材料" ], [ "stone_brick_cracked", "裂石砖", "布满裂痕的石制建筑材料" ], [ "stone_brick_mossy", "苔石砖", "布满青苔的石制建筑材料" ], [ "bucket_empty", "桶", "一个空桶,可以盛放液体" ], [ "bucket_water", "水桶", "一个装满水的桶, 左键以倒出水" ], [ "bucket_lava", "岩浆桶", "一个装满岩浆的桶, 左键以倒出岩浆" ], [ "bucket_milk", "牛奶桶", "一个装满牛奶的桶, 饮用牛奶可解除所有状态" ], [ "snowball", "雪球", "圆乎乎的雪球" ], [ "vine", "藤蔓", "这是一根藤蔓" ], [ "sugar_cane", "甘蔗", "制造蔗糖的原料" ], [ "suger", "糖", "尝起来甜甜的" ], [ "paper", "纸", "一张白纸" ], [ "leather", "皮革", "动物的毛皮" ], [ "book", "书", "这是一本书" ], [ "wheat", "小麦", "可加工成各种主食" ], [ "bread", "面包", "甜甜的面包" ], [ "bone", "骨头", "一根骨头" ], [ "bone_meal", "骨粉", "一撮骨头粉,可以用来催熟农作物" ], [ "crafting_table", "合成台", "使用 3x3 的方阵来合成更多的物品" ], [ "torch", "火把", "基础而廉价的照明工具" ], [ "coal", "煤炭", "" ], [ "charcoal", "木炭", "" ], [ "string", "线", "一根长长的细线" ], [ "wooden_bow", "木弓", "木制弓,适合远程攻击" ], [ "flint", "燧石", "尖锐的燧石" ], [ "feather", "羽毛", "这是一根羽毛" ], [ "wooden_arrow", "木箭", "木制的箭" ], [ "rocket_launcher", "火箭发射器", "摧毁一切!!!!" ], [ "redstone_lamp", "红石灯", "充能后照亮周围环境" ], [ "red_wire", "红色红石线缆", "放置以连接红石电路" ], [ "clay_block", "粘土块", "最具用途的建筑材料来源" ], [ "brick", "红砖方块", "最具用途的建筑材料" ], [ "spruce_plank", "云杉木板", "常用的木制建筑材料" ], [ "birch_plank", "桦树木板", "常用的木制建筑材料" ], [ "jungle_plank", "丛林木板", "常用的木制建筑材料" ], [ "acacia_plank", "金合欢木板", "常用的木制建筑材料" ], [ "dark_oak_plank", "深色橡木木板", "常用的木制建筑材料" ], [ "block_iron", "铁块", "铁锭压制而成的块" ], [ "block_gold", "金块", "金锭压制而成的块" ], [ "block_coal", "煤块", "煤炭压制而成的煤块,有着很大的燃值" ], [ "block_diamond", "钻石块", "钻石制成的方块" ], [ "block_emerald", "绿宝石块", "绿宝石制成的方块" ], [ "block_lapis", "青金石块", "青金石制成的方块" ], [ "block_redstone", "红石块", "红石压制而成的方块" ], [ "bone_block", "骨块", "钙质丰富的方块" ], [ "red_brick", "红砖", "粘土烧成的红色砖块" ], [ "brown_mushroom_block", "棕色蘑菇块", "巨型棕色蘑菇的伞块" ], [ "coarse_dirt", "灰化土", "泥土的变种,有着较强的酸性" ], [ "cobblestone_fence", "圆石墙", "石制的栅栏" ], [ "end_stone", "末地石", "末地的主要构成方块" ], [ "end_stone_brick", "末地石砖", "末地石打造的砖块" ], [ "farmland", "耕地", "可以在上面播种与收获作物" ], [ "fence_oak", "橡木栅栏", "木制的栅栏" ], [ "fence_birch", "桦树栅栏", "木制的栅栏" ], [ "fence_spruce", "云杉栅栏", "木制的栅栏" ], [ "fence_jungle", "丛林栅栏", "木制的栅栏" ], [ "fence_acacia", "金合欢栅栏", "木制的栅栏" ], [ "fence_dark_oak", "深色橡木栅栏", "木制的栅栏" ], [ "fence_nether", "地狱栅栏", "地狱的深黑色栅栏" ], [ "glowstone", "萤石", "会发光的石头" ], [ "hay_bale", "干草块", "一捆小麦" ], [ "ice_brick", "冰砖", "冰块做成的砖块" ], [ "iron_bar", "铁栅栏", "铁窗" ], [ "magma_block", "岩浆块", "固态岩浆" ], [ "mossy_cobblestone_fence", "苔石墙", "布满青苔的石制栅栏" ], [ "mushroom_stem", "蘑菇梗", "巨型蘑菇的梗" ], [ "netherrack", "地狱岩", "地狱的主要方块" ], [ "nether_brick_block", "地狱砖", "深黑色的地狱砖块" ], [ "purpur_block", "紫珀块", "紫珀制成的方块" ], [ "red_mushroom_block", "红蘑菇块", "巨型红蘑菇的伞块" ], [ "red_nether_brick", "红地狱砖", "深红色的地狱砖块" ], [ "red_sand_stone", "红沙石", "硬质的红沙" ], [ "sea_lantern", "海晶灯", "海中发光的方块" ], [ "slime_block", "史莱姆块", "黏糊糊的明胶方块" ], [ "snow_brick", "雪砖", "硬化的雪砖块" ], [ "soul_sand", "灵魂沙", "脆弱的沙块,内部似乎封印着灵魂" ], [ "sponge", "海绵", "蓬松的海绵块,能够大量吸收水分" ], [ "wet_sponge", "湿海绵", "吸过水的饱和海绵,烘干后可以循环使用" ], [ "terracotta_white", "白色陶瓦", "坚硬的陶瓦" ], [ "terracotta_orange", "橙色陶瓦", "坚硬的陶瓦" ], [ "terracotta_magenta", "品红色陶瓦", "坚硬的陶瓦" ], [ "terracotta_light_blue", "淡蓝色陶瓦", "坚硬的陶瓦" ], [ "terracotta_yellow", "黄色陶瓦", "坚硬的陶瓦" ], [ "terracotta_lime", "浅绿色陶瓦", "坚硬的陶瓦" ], [ "terracotta_pink", "粉红色陶瓦", "坚硬的陶瓦" ], [ "terracotta_gray", "灰色陶瓦", "坚硬的陶瓦" ], [ "terracotta_light_gray", "浅灰色陶瓦", "坚硬的陶瓦" ], [ "terracotta_cyan", "青色陶瓦", "坚硬的陶瓦" ], [ "terracotta_purple", "紫色陶瓦", "坚硬的陶瓦" ], [ "terracotta_blue", "蓝色陶瓦", "坚硬的陶瓦" ], [ "terracotta_brown", "棕色陶瓦", "坚硬的陶瓦" ], [ "terracotta_green", "绿色陶瓦", "坚硬的陶瓦" ], [ "terracotta_red", "红色陶瓦", "坚硬的陶瓦" ], [ "terracotta_black", "黑色陶瓦", "坚硬的陶瓦" ], [ "tnt", "TNT", "被激活后会发生爆炸" ], [ "wood_oak", "橡木木头", "刚砍下来的新鲜原木" ], [ "wood_birch", "桦树木头", "刚砍下来的新鲜原木" ], [ "wood_spruce", "云杉木头", "刚砍下来的新鲜原木" ], [ "wood_jungle", "丛林木头", "刚砍下来的新鲜原木" ], [ "wood_acacia", "金合欢木头", "刚砍下来的新鲜原木" ], [ "wood_dark_oak", "深色橡木木头", "刚砍下来的新鲜原木" ], [ "fishing_rod", "钓鱼竿", "愿者上钩" ], [ "wood_stripped_oak", "橡木去皮木头", "剥掉了树皮的原木" ], [ "wood_stripped_birch", "桦树去皮木头", "剥掉了树皮的原木" ], [ "wood_stripped_spruce", "云杉去皮木头", "剥掉了树皮的原木" ], [ "wood_stripped_jungle", "丛林去皮木头", "剥掉了树皮的原木" ], [ "wood_stripped_acacia", "金合欢去皮木头", "剥掉了树皮的原木" ], [ "wood_stripped_dark_oak", "深色橡木去皮木头", "剥掉了树皮的原木" ], [ "allium", "绒球葱", "一种小型花" ], [ "anvil", "铁砧", "用来修复破损的工具" ], [ "azure_bluet", "茜草花", "一种小型花" ], [ "wooden_bed_red", "红色床", "这是一张床,用于重置重生点" ], [ "blue_orchid", "兰花", "一种小型花" ], [ "book_block", "书堆", "知识的海洋" ], [ "bookcase_oak", "橡木书架", "摆放着很多书籍的书架,可存储物品" ], [ "brewing_stand", "酿造台", "酿造各种效果的药水" ], [ "brown_mushroom", "蘑菇", "一朵棕色蘑菇" ], [ "cake", "蛋糕", "奶油味的蛋糕,可切成蛋糕片食用" ], [ "candle", "蜡烛", "这是一支蜡烛" ], [ "candle_holder", "蜡烛台", "西方特色的蜡烛台" ], [ "cauldron", "炼药锅", "这是一个炼药锅" ], [ "chair_oak", "橡木椅子", "一张木制的椅子" ], [ "chandeliers", "水晶吊灯", "明亮而奢华的水晶吊灯" ], [ "stone_chest", "石制箱子", "存放物品" ], [ "cobweb", "蜘蛛网", "一张蜘蛛网,能够困住各种生物" ], [ "dandelion", "蒲公英", "一种小型花" ], [ "daylight_sensor", "日光传感器", "太阳光照射下持续输出红石信号" ], [ "daylight_sensor_inverted", "夜光传感器", "月光照射下持续输出红石信号" ], [ "dispenser", "发射器", "红石信号激活时发射一个物品" ], [ "ender_chest", "末影箱", "量子效应使得所有的末影箱共用一个空间" ], [ "fern", "蕨类", "一种孢子植物" ], [ "fire_lamp", "火焰吊灯", "提供明亮的照明" ], [ "wooden_pressure_plate", "木制压力板", "踩下后激活红石信号" ], [ "stone_pressure_plate", "石制压力板", "踩下后激活红石信号" ], [ "iron_pressure_plate", "铁制压力板", "踩下后激活红石信号" ], [ "golden_pressure_plate", "金制压力板", "踩下后激活红石信号" ], [ "jukebox", "唱片机", "放入唱片,享受音乐" ], [ "grass", "草", "野火烧不尽,春风吹又生" ], [ "iron_door", "铁门", "房子必不可少的部分" ], [ "lilac", "欧丁香", "一种大型植物" ], [ "orange_tulip", "橙色郁金香", "一种小型花" ], [ "red_tulip", "红色郁金香", "一种小型花" ], [ "white_tulip", "白色郁金香", "一种小型花" ], [ "pink_tulip", "粉红色郁金香", "一种小型花" ], [ "painting_2x2", "画 2x2", "目前收录MC原版画作,欢迎各位大大投稿 0w0" ], [ "peony", "牡丹", "一种大型植物" ], [ "poppy", "虞美人", "一种小型花" ], [ "pumpkin", "南瓜", "完整的南瓜" ], [ "pumpkin_carved", "雕刻的南瓜", "雕刻有万圣节图案的南瓜" ], [ "red_mushroom", "红蘑菇", "一朵红色的蘑菇" ], [ "rose_bush", "玫瑰丛", "一种大型植物" ], [ "sapling_oak", "橡木树苗", "一种树苗,种植后会成长为橡树" ], [ "sapling_birch", "桦树树苗", "一种树苗,种植后会成长为桦木树" ], [ "sapling_jungle", "丛林树苗", "一种树苗,种植后会成长为丛林树" ], [ "sapling_spruce", "云杉树苗", "一种树苗,种植后会成长为云杉树" ], [ "sapling_acacia", "金合欢树苗", "一种树苗,种植后会成长为金合欢树" ], [ "sapling_dark_oak", "深色橡木树苗", "一种树苗,种植后会成长为深色橡树" ], [ "sign", "牌子", "暂不可用" ], [ "stone_button", "石制开关", "控制红石电路的激活状态" ], [ "wooden_button", "木制开关", "控制红石电路的激活状态" ], [ "sunflower", "向日葵", "一种大型植物" ], [ "watermelon", "西瓜", "一个完整的西瓜,看起来十分饱满甜美" ], [ "wooden_door_oak", "橡木门", "房子必不可少的部分" ], [ "wooden_door_birch", "桦树门", "房子必不可少的部分" ], [ "wooden_door_spruce", "云杉门", "房子必不可少的部分" ], [ "wooden_door_jungle", "丛林门", "房子必不可少的部分" ], [ "wooden_door_acacia", "金合欢门", "房子必不可少的部分" ], [ "wooden_door_dark_oak", "深色橡木门", "房子必不可少的部分" ], [ "table_oak", "橡木木桌", "一张木桌" ], [ "cabinet_oak", "橡木桌柜", "一张桌柜,可存储物品" ], [ "apple", "苹果", "一个熟透的红苹果" ], [ "baked_potato", "烤马铃薯", "烤熟了的马铃薯" ], [ "blaze_powder", "烈焰粉", "药水酿造的热量来源" ], [ "blaze_rod", "烈焰棒", "这是一根烫手的烈焰棒" ], [ "bowl", "碗", "又大又圆的碗" ], [ "cake_piece", "蛋糕片", "一片蛋糕" ], [ "carrot", "胡萝卜", "富含维生素的胡萝卜" ], [ "chorus_fruit", "紫颂果", "紫颂树的果实" ], [ "cooked_chicken", "烤火鸡", "烤熟的火鸡,鸡肉味嘎嘣脆" ], [ "cookie", "曲奇", "一块曲奇饼干" ], [ "diamond", "钻石", "" ], [ "dried_kelp", "干海带", "硬邦邦的干燥海带" ], [ "egg", "蛋", "这是一个蛋" ], [ "emerald", "绿宝石", "" ], [ "ender_eye", "末影之眼", "你感受到了有什么东西在注视着你" ], [ "ender_pearl", "末影珍珠", "这是一颗释放着未知魔法能量的珍珠" ], [ "fermented_spider_eye", "发酵蜘蛛眼", "发酵过的蜘蛛眼" ], [ "ghast_tear", "恶灵之泪", "这是恶灵的泪水晶体" ], [ "glass_bottle", "玻璃瓶", "透明的玻璃瓶子" ], [ "glistering_melon_slice", "闪烁的西瓜片", "用于酿造,不可食用" ], [ "glowstone_dust", "萤石粉", "发光的萤石粉末" ], [ "golden_apple", "金苹果", "食用后有特殊效果加成" ], [ "golden_carrot", "金胡萝卜", "食用后有特殊效果加成" ], [ "gunpowder", "火药", "易燃的硫化混合物" ], [ "heart_of_sea", "海洋之心", "海洋的精华" ], [ "ink_sac", "墨囊", "这是一根墨鱼的触须" ], [ "lapis_lazuli", "青金石", "" ], [ "magma_cream", "岩浆膏", "一种岩浆胶状物" ], [ "melon_seed", "西瓜种子", "西瓜的种子,播种在耕地上可成长为西瓜" ], [ "melon_slice", "西瓜片", "这是一片西瓜,夏日必备" ], [ "mushroom_stew", "蘑菇煲", "一碗蘑菇汤" ], [ "nether_brick", "地狱砖头", "一个地狱砖头,可堆砌成地狱砖块" ], [ "nether_star", "下界之星", "凋零的掉落物" ], [ "nether_wart", "地狱疣", "地狱的特产作物" ], [ "phantom_membrane", "幻翼翅", "一个透明的幻翼翅膀" ], [ "popped_chorus_fruits", "爆浆紫颂果", "果汁真丰富" ], [ "potato", "马铃薯", "生的土豆" ], [ "prismarine_crystals", "海晶砂粒", "一块海晶的砂粒" ], [ "prismarine_shard", "海晶碎片", "一块海晶的碎片" ], [ "quartz", "石英", "" ], [ "pufferfish", "河豚", "一只味道十分甜美的河豚" ], [ "pumpkin_pie", "南瓜派", "一个南瓜饼" ], [ "pumpkin_seed", "南瓜种子", "南瓜的种子,播种在耕地上可成长为南瓜" ], [ "raw_beef", "生牛肉", "一块生的牛肉,烤过更好吃" ], [ "raw_chicken", "生鸡肉", "生的鸡肉,不烤熟了再吃吗?" ], [ "scute", "鳞甲", "乌龟的鳞甲片" ], [ "seed", "小麦种子", "小麦的种子,播种在耕地上来种植小麦" ], [ "shulker_shell", "潜影贝壳", "一块潜影贝的坚硬外壳" ], [ "slimeball", "史莱姆球", "看起来很好吃的样子" ], [ "steak", "牛排", "看起来很好吃的样子" ], [ "beetroot", "甜菜根", "这是一个甜菜根" ], [ "raw_cod", "生鳕鱼", "一条活蹦乱跳的鳕鱼" ], [ "cooked_cod", "熟鳕鱼", "一条美味的鳕鱼" ], [ "raw_mutton", "生羊肉", "生的羊肉" ], [ "cooked_mutton", "熟羊肉", "熟透了的羊肉" ], [ "raw_porkchop", "生猪肉", "这是一片生的猪肉" ], [ "cooked_porkchop", "猪排", "一片美味的猪排" ], [ "raw_rabbit", "生兔肉", "生的兔子肉" ], [ "cooked_rabbit", "熟兔肉", "熟透了的兔子肉" ], [ "raw_salmon", "生鲑鱼", "一条活蹦乱跳的鲑鱼" ], [ "cooked_salmon", "熟鲑鱼", "一条美味的三文鱼" ], [ "dye_white", "白色染料", "一种染料,可用来染色" ], [ "dye_orange", "橙色染料", "一种染料,可用来染色" ], [ "dye_magenta", "品红色染料", "一种染料,可用来染色" ], [ "dye_light_blue", "淡蓝色染料", "一种染料,可用来染色" ], [ "dye_yellow", "黄色染料", "一种染料,可用来染色" ], [ "dye_lime", "黄绿色染料", "一种染料,可用来染色" ], [ "dye_pink", "粉红色染料", "一种染料,可用来染色" ], [ "dye_gray", "灰色染料", "一种染料,可用来染色" ], [ "dye_light_gray", "浅灰色染料", "一种染料,可用来染色" ], [ "dye_cyan", "青色染料", "一种染料,可用来染色" ], [ "dye_purple", "紫色染料", "一种染料,可用来染色" ], [ "dye_blue", "蓝色染料", "一种染料,可用来染色" ], [ "dye_brown", "棕色染料", "一种染料,可用来染色" ], [ "dye_green", "绿色染料", "一种染料,可用来染色" ], [ "dye_red", "红色染料", "一种染料,可用来染色" ], [ "dye_black", "黑色染料", "一种染料,可用来染色" ], [ "fire_charge", "火焰弹", "一颗燃烧的火焰弹" ], [ "firework_rocket", "烟花火箭", "这是一个烟花火箭" ], [ "iron_nugget", "铁粒", "" ], [ "gold_nugget", "金粒", "" ], [ "kelp", "海带", "一根长长的海带" ], [ "lighter", "打火石", "让火焰燃烧得更猛烈些吧!" ], [ "map_paper", "地图", "记录每个区块的地图" ], [ "nautilus_shell", "鹦鹉海螺", "为什么不问问神奇的鹦鹉海螺呢" ], [ "rabbit_foot", "兔子脚", "兔子健壮的脚" ], [ "rabbit_hide", "兔子皮", "兔子毛茸茸的毛皮" ], [ "redstone", "红石", "" ], [ "rotten_flesh", "腐肉", "已经腐烂很久的肉块" ], [ "spider_eye", "蜘蛛眼", "一只蜘蛛的眼睛" ], [ "totem_of_undying", "不死图腾", "使用它来逃离一次死亡" ], [ "wool_white", "白色羊毛", "柔软有弹性的羊毛" ], [ "wool_orange", "橙色羊毛", "柔软有弹性的羊毛" ], [ "wool_magenta", "品红色羊毛", "柔软有弹性的羊毛" ], [ "wool_light_blue", "淡蓝色羊毛", "柔软有弹性的羊毛" ], [ "wool_yellow", "黄色羊毛", "柔软有弹性的羊毛" ], [ "wool_lime", "浅绿色羊毛", "柔软有弹性的羊毛" ], [ "wool_pink", "粉红色羊毛", "柔软有弹性的羊毛" ], [ "wool_gray", "灰色羊毛", "柔软有弹性的羊毛" ], [ "wool_light_gray", "浅灰色羊毛", "柔软有弹性的羊毛" ], [ "wool_cyan", "青色羊毛", "柔软有弹性的羊毛" ], [ "wool_purple", "紫色羊毛", "柔软有弹性的羊毛" ], [ "wool_blue", "蓝色羊毛", "柔软有弹性的羊毛" ], [ "wool_brown", "棕色羊毛", "柔软有弹性的羊毛" ], [ "wool_green", "绿色羊毛", "柔软有弹性的羊毛" ], [ "wool_red", "红色羊毛", "柔软有弹性的羊毛" ], [ "wool_black", "黑色羊毛", "柔软有弹性的羊毛" ], [ "wooden_axe", "木斧", "木制的斧头" ], [ "wooden_pickaxe", "木镐", "木制的镐子" ], [ "wooden_sword", "木剑", "木头制成的剑" ], [ "platform_oak", "橡木平台", "一种木制的平台" ], [ "platform_birch", "桦树平台", "一种木制的平台" ], [ "platform_spruce", "云杉平台", "一种木制的平台" ], [ "platform_jungle", "丛林平台", "一种木制的平台" ], [ "platform_acacia", "金合欢平台", "一种木制的平台" ], [ "platform_dark_oak", "深色橡木平台", "一种木制的平台" ], [ "iron_axe", "铁斧", "铁制的斧头" ], [ "iron_pickaxe", "铁镐", "铁制的镐子" ], [ "iron_sword", "铁剑", "铁器打造成的剑" ], [ "golden_axe", "金斧", "金制的斧头" ], [ "golden_pickaxe", "金镐", "金制的镐子" ], [ "golden_sword", "金剑", "黄金炼成的剑" ], [ "diamond_axe", "钻石斧", "钻石制成的斧头" ], [ "diamond_pickaxe", "钻石镐", "钻石制成的镐子" ], [ "diamond_sword", "钻石剑", "锋利的钻石剑" ], [ "leather_helmet", "皮革帽子", "皮革制成的帽子" ], [ "leather_chestplate", "皮革衣服", "皮革制成的衣服" ], [ "leather_leggings", "皮革裤子", "皮革制成的裤子" ], [ "iron_helmet", "铁头盔", "铁皮制成的头盔" ], [ "iron_chestplate", "铁胸甲", "铁皮制成的胸甲" ], [ "iron_leggings", "铁护胫", "铁皮制成的裤甲" ], [ "golden_helmet", "金头盔", "黄金制成的头盔" ], [ "golden_chestplate", "金胸甲", "黄金制成的胸甲" ], [ "golden_leggings", "金护胫", "黄金制成的裤甲" ], [ "diamond_helmet", "钻石头盔", "钻石制成的头盔" ], [ "diamond_chestplate", "钻石胸甲", "钻石制成的胸甲" ], [ "diamond_leggings", "钻石护胫", "钻石制成的裤甲" ], [ "potion_water", "水瓶", "一瓶水,可酿造为各种效果的药水" ], [ "potion_awkward", "粗制的药水", "一瓶粗制的药水,将不同材料提炼后可得到不同效果的药水" ], [ "potion_strength", "力量药水", "一瓶充满力量的药水" ], [ "potion_strength_long", "长效力量药水", "一瓶充满力量的药水" ], [ "potion_swiftness", "迅捷药水", "一瓶饮用后行动更快的药水" ], [ "potion_swiftness_long", "长效迅捷药水", "一瓶饮用后行动更快的药水" ], [ "potion_slowness", "迟缓药水", "一瓶慢节奏的药水" ], [ "potion_slowness_long", "长效迟缓药水", "一瓶慢节奏的药水" ], [ "potion_leaping", "跳跃药水", "一瓶提高跳跃力的药水" ], [ "potion_leaping_long", "长效跳跃药水", "一瓶提高跳跃力的药水" ], [ "potion_healing", "治疗药水", "一瓶瞬间恢复生命值的药水" ], [ "potion_healing_super", "强力治疗药水", "一瓶瞬间恢复生命值的药水" ], [ "potion_harming", "伤害药水", "一瓶含有各种有害物质的药水" ], [ "potion_harming_super", "强力伤害药水", "一瓶含有各种有害物质的药水" ], [ "potion_poison", "剧毒药水", "一瓶有毒的药水" ], [ "potion_poison_long", "长效剧毒药水", "一瓶有毒的药水" ], [ "potion_regeneration", "再生药水", "一瓶持续提高生命力的药水" ], [ "potion_regeneration_long", "长效再生药水", "一瓶持续提高生命力的药水" ], [ "potion_fire_resistance", "抗火药水", "一瓶饮用后免疫火焰和岩浆的药水" ], [ "potion_fire_resistance_long", "长效抗火药水", "一瓶饮用后免疫火焰和岩浆的药水" ], [ "potion_water_breathing", "水肺药水", "一瓶饮用后可在水中呼吸的药水" ], [ "potion_water_breathing_long", "长效水肺药水", "一瓶饮用后可在水中呼吸的药水" ], [ "potion_night_vision", "夜视药水", "一瓶可以看透黑暗的药水" ], [ "potion_night_vision_long", "长效夜视药水", "一瓶可以看透黑暗的药水" ], [ "potion_invisibility", "隐身药水", "一瓶不科学的药水" ], [ "potion_invisibility_long", "长效隐身药水", "一瓶不科学的药水" ], [ "potion_slow_falling", "缓降药水", "一瓶饮用后缓慢降落的药水" ], [ "potion_slow_falling_long", "长效缓降药水", "一瓶饮用后缓慢降落的药水" ], [ "potion_weakness", "虚弱药水", "一瓶饮用后会虚脱的药水" ], [ "potion_weakness_long", "长效虚弱药水", "一瓶饮用后会虚脱的药水" ], [ "enchantment_table", "附魔台", "给工具附魔!" ], [ "enchanted_book", "附魔书", "一本写满了魔咒的书" ], [ "shears", "剪刀", "用来剪羊毛或雕刻" ], [ "shotgun", "霰弹枪", "强力的霰弹枪" ], [ "stone_hoe", "石锄", "用于开垦土地" ], [ "green_wire", "绿色红石线缆", "放置以连接红石电路" ], [ "blue_wire", "蓝色红石线缆", "放置以连接红石电路" ], [ "yellow_wire", "黄色红石线缆", "放置以连接红石电路" ], [ "wire_cutter", "红石线钳", "用于移除红石线缆" ], [ "lever", "拉杆", "控制红石电路的激活状态" ], [ "redstone_torch", "红石火把", "右键以激活或取消激活" ], [ "bomb", "炸弹", "可以破坏图格的炸弹" ], [ "grenade", "手榴弹", "对敌人造成伤害,不会破坏图格" ], [ "handgun", "手枪", "一把手枪" ], [ "rifle", "步枪", "一把步枪" ], [ "fire_gun", "喷火枪", "一把喷火枪" ], [ "super_iron_sword", "锻铁剑", "铁器打造成的剑" ], [ "super_golden_sword", "宽金剑", "黄金炼成的剑" ], [ "super_diamond_sword", "加强钻石剑", "锋利的钻石剑" ], [ "copper_sword", "铜剑", "铜器打造成的剑" ], [ "super_copper_sword", "宽铜剑", "铜器打造成的剑" ], [ "tin_sword", "锡剑", "用锡打造成的剑" ], [ "super_tin_sword", "宽锡剑", "用锡打造成的剑" ], [ "lead_sword", "铅剑", "用铅打造成的剑" ], [ "super_lead_sword", "大铅剑", "用铅打造成的剑" ], [ "silver_sword", "银剑", "用银打造成的剑" ], [ "super_silver_sword", "长银剑", "用银打造成的剑" ], [ "bronze_sword", "青铜剑", "用青铜打造成的剑" ], [ "super_bronze_sword", "宽青铜剑", "用青铜打造成的剑" ], [ "steel_sword", "钢剑", "用钢打造成的剑" ], [ "super_steel_sword", "长钢剑", "用钢打造成的剑" ], [ "ghost_sword", "日光刀", "注入阳光能量的刀(鬼灭之刃?)" ], [ "glow_ball", "烈焰光球", "提供较长时间的照明" ], [ "glow_bomb", "强光炸弹", "对敌人造成伤害,不会破坏图格,提供短暂强光照明" ], [ "lighting_bow", "光灵弓", "射出光灵箭,命中时提供照明加成" ], [ "fire_bullet", "土子弹", "最普通的子弹" ], [ "iron_bullet", "铁子弹", "铁质的子弹" ], [ "silver_bullet", "银子弹", "银制的子弹" ], [ "lighting_arrow", "光灵箭", "发光的箭" ], [ "cross_bow", "连弩", "快速发射弓箭" ], [ "shot_bow", "散射弩", "快速发射多个弓箭" ], [ "super_cross_bow", "强化连弩", "快速发射弓箭" ], [ "boomerang", "回旋镖", "扔出去然后飞回来!" ], [ "wooden_boomerang", "木制回旋镖", "扔出去然后飞回来!" ], [ "star_arrow", "坠星箭", "发射的时候再次坠落一支箭" ], [ "fire_boomerang", "烈焰回旋镖", "着火的回旋镖!" ], [ "blood_arrow", "血腥箭", "持续吸血" ], [ "blood_bow", "血腥弓", "射出血腥箭" ], [ "blue_stone_bow", "蓝石弓", "具有更快的攻速和攻击频率" ], [ "ice_arrow", "冰雪箭", "散发着寒冷气息的箭" ], [ "ice_bow", "冰雪弓", "射出冰雪箭" ], [ "chast_bow", "跟踪剑弓", "射出跟踪剑箭" ], [ "sword_arrow", "跟踪箭", "半辅助瞄准目标" ], [ "air_sword", "空气剑", "斩破空气,发射空气弹" ], [ "super_air_sword", "破隙剑", "斩破空气,发射空气弹" ], [ "amethyst_staff", "紫水晶法杖", "一个充满魔力的法杖" ], [ "lighting_staff", "光之法杖", "一个散发光辉的法杖" ], [ "water_staff", "水之法杖", "一个魔法法杖" ], [ "ice_staff", "冰霜法杖", "一个散发寒气的法杖" ], [ "shadow_staff", "影流法杖", "一个受到黑暗魔法控制的法杖" ], [ "red_torch", "红光火把", "散发着红色光的火把" ], [ "yellow_torch", "黄光火把", "散发着黄色光的火把" ], [ "blue_torch", "蓝光火把", "散发着蓝色光的火把" ], [ "green_torch", "绿光火把", "散发着绿色光的火把" ], [ "white_torch", "白光火把", "散发着白色光的火把" ], [ "flesh_stone", "血石块", "由不可名状物凝固而成的方块" ], [ "flesh_dirt", "肉块", "不知名的肉类方块" ], [ "flesh_gut", "肠块", "不可名状的方块" ], [ "mycelium", "菌丝", "由真菌组成的方块" ], [ "tainted_stone", "腐化石", "受到腐化的石头" ], [ "tainted_dirt", "腐化土", "受到腐化的泥土" ], [ "volcano_stone", "熔岩石", "长时间熔岩接触凝结的石头" ], [ "volcano_dirt", "熔岩泥", "松散的熔岩泥土" ], [ "ore_tin", "锡矿石", "矿物原矿,需要进一步加工" ], [ "ore_copper", "铜矿石", "矿物原矿,需要进一步加工" ], [ "ore_lead", "铅矿石", "矿物原矿,需要进一步加工" ], [ "ore_silver", "银矿石", "矿物原矿,需要进一步加工" ], [ "bronze_helmet", "青铜头盔", "青铜制成的头盔" ], [ "bronze_chestplate", "青铜胸甲", "青铜制成的胸甲" ], [ "bronze_leggings", "青铜护胫", "青铜制成的护胫" ], [ "copper_helmet", "铜头盔", "铜制成的头盔" ], [ "copper_chestplate", "铜胸甲", "铜制成的胸甲" ], [ "copper_leggings", "铜护胫", "铜制成的护胫" ], [ "lead_helmet", "铅头盔", "铅制成的头盔" ], [ "lead_chestplate", "铅胸甲", "铅制成的胸甲" ], [ "lead_leggings", "铅护胫", "铅制成的护胫" ], [ "nether_helmet", "下界合金头盔", "下界合金锭加固制成的头盔" ], [ "nether_chestplate", "下界合金胸甲", "下界合金锭加固制成的胸甲" ], [ "nether_leggings", "下界合金护胫", "下界合金锭加固制成的护胫" ], [ "silver_helmet", "银头盔", "银器制成的头盔" ], [ "silver_chestplate", "银胸甲", "银器制成的胸甲" ], [ "silver_leggings", "银护胫", "银器制成的护胫" ], [ "steel_helmet", "钢头盔", "钢制成的头盔" ], [ "steel_chestplate", "钢胸甲", "钢制成的胸甲" ], [ "steel_leggings", "钢护胫", "钢制成的护胫" ], [ "tin_helmet", "锡头盔", "锡制成的头盔" ], [ "tin_chestplate", "锡胸甲", "锡制成的胸甲" ], [ "tin_leggings", "锡护胫", "锡制成的护胫" ], [ "palm_plank", "棕榈木板", "常用的木制建筑材料" ], [ "volcano_plank", "熔岩木板", "常用的木制建筑材料" ], [ "tainted_plank", "腐化木板", "被腐化的木制建筑材料" ], [ "wood_palm", "棕榈木头", "刚砍下来的新鲜原木" ], [ "wood_volcano", "熔岩木头", "长期处在熔岩环境的木头" ], [ "wood_tainted", "腐化木头", "刚砍下来的新鲜原木" ], [ "wood_stripped_palm", "棕榈去皮木头", "剥掉了树皮的原木" ], [ "wood_stripped_volcano", "熔岩去皮木头", "剥掉了树皮的原木" ], [ "wood_stripped_tainted", "腐化去皮木头", "剥掉了树皮的原木" ], [ "sapling_tainted", "腐化树苗", "一种树苗,种植后会成长为腐化树" ], [ "sapling_palm", "棕榈树苗", "一种树苗,种植后会成长为棕榈树" ], [ "sapling_cactus", "仙人掌", "一个小仙人掌,种植后会成长为大仙人掌" ], [ "sapling_volcano", "熔岩树苗", "一种树苗,种植后会成长为熔岩树" ], [ "sapling_bare_oak", "秃橡木树苗", "一种树苗,种植后会成长为秃橡木树" ], [ "platform_palm", "棕榈平台", "一种木制的平台" ], [ "platform_volcano", "熔岩木平台", "一种木制的平台" ], [ "platform_tainted", "腐化木平台", "一种木制的平台" ], [ "wooden_door_palm", "棕榈门", "房子必不可少的部分" ], [ "wooden_door_volcano", "熔岩木门", "房子必不可少的部分" ], [ "wooden_door_tainted", "腐化木门", "房子必不可少的部分" ], [ "fence_palm", "棕榈栅栏", "木制的栅栏" ], [ "fence_volcano", "熔岩木栅栏", "木制的栅栏" ], [ "fence_tainted", "腐化木栅栏", "木制的栅栏" ], [ "ore_ancient_debris", "远古残骸", "矿物原矿,需要进一步加工" ], [ "block_netherite", "下界合金块", "下界合金而成的方块" ], [ "netherite_ingot", "下界合金锭", "" ], [ "netherite_scrap", "下界合金碎片", "用于合成下界合金锭" ], [ "dried_kelp_block", "干海带块", "一捆干海带" ], [ "blue_ice", "蓝冰", "比浮冰更光滑,内部独特的结构使得它能发出微弱的光芒" ], [ "ore_nether_quartz", "下界石英矿", "矿物原矿,需要进一步加工" ], [ "block_quartz", "石英块", "石英压缩而成的方块,常用的建筑材料" ], [ "platform_end_stone", "末地石平台", "由末地石制作而成的平台" ], [ "platform_nether_brick", "地狱平台", "由地狱砖制作而成的平台" ], [ "platform_prismarine", "海晶石平台", "由海晶石制作而成的平台" ], [ "platform_prismarine_dark", "暗海晶石平台", "由暗海晶石制作而成的平台" ], [ "platform_purpur", "紫珀平台", "由紫珀砖制作而成的平台" ], [ "platform_quartz", "石英平台", "由石英制作而成的平台" ], [ "platform_red_sand_stone", "红沙石平台", "由红沙石制作而成的平台" ], [ "platform_sandstone", "沙石平台", "由沙石制作而成的平台" ], [ "platform_stone_brick", "石砖平台", "由石砖制作而成的平台" ], [ "stained_glass_white", "白色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_orange", "橙色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_magenta", "品红色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_light_blue", "淡蓝色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_yellow", "黄色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_lime", "浅绿色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_pink", "粉红色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_gray", "灰色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_light_gray", "浅灰色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_cyan", "青色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_purple", "紫色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_blue", "蓝色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_brown", "棕色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_green", "绿色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_red", "红色染色玻璃", "这是一块染色玻璃" ], [ "stained_glass_black", "黑色染色玻璃", "这是一块染色玻璃" ], [ "wooden_bed_white", "白色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_orange", "橙色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_magenta", "品红色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_light_blue", "淡蓝色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_yellow", "黄色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_lime", "浅绿色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_pink", "粉红色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_gray", "灰色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_light_gray", "浅灰色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_cyan", "青色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_purple", "紫色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_blue", "蓝色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_brown", "棕色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_green", "绿色床", "这是一张床,用于重置重生点" ], [ "wooden_bed_black", "黑色床", "这是一张床,用于重置重生点" ], [ "jack_o_lantern", "南瓜灯", "雕刻有万圣节图案的南瓜灯" ], [ "pumpkin_helmet", "雕刻南瓜头套", "一个南瓜头套" ], [ "shulker_box", "潜影盒", "以物品的形式继续存放物品" ], [ "end_rod", "末地烛", "末地的照明工具" ], [ "lantern", "灯笼", "这是一个可以悬挂的灯笼" ], [ "barrel", "木桶", "存储物品" ], [ "campfire", "营火", "提供照明" ], [ "painting_4x2", "画 4x2", "目前收录MC原版画作,欢迎各位大大投稿 0w0" ], [ "painting_2x4", "画 2x4", "目前收录MC原版画作,欢迎各位大大投稿 0w0" ], [ "painting_4x4", "画 4x4", "目前收录MC原版画作,欢迎各位大大投稿 0w0" ], [ "painting_8x4", "画 2x2", "目前收录MC原版画作,欢迎各位大大投稿 0w0" ], [ "painting_8x6", "画 8x6", "目前收录MC原版画作,欢迎各位大大投稿 0w0" ], [ "painting_8x8", "画 8x8", "目前收录MC原版画作,欢迎各位大大投稿 0w0" ], [ "flower_pot", "花盆", "可以放置小型花的花盆" ], [ "flower_pot_large", "大型花盆", "可以放置大型花的花盆" ], [ "trapped_chest", "陷阱箱", "存储物品,打开时发出红石信号" ], [ "cocoa_bean", "可可豆", "生长在丛林木上的食物材料" ], [ "table_spruce", "云杉木桌", "一张木桌" ], [ "table_birch", "桦树木桌", "一张木桌" ], [ "table_jungle", "丛林木桌", "一张木桌" ], [ "table_acacia", "金合欢木桌", "一张木桌" ], [ "table_dark_oak", "深色橡木木桌", "一张木桌" ], [ "table_palm", "棕榈木桌", "一张木桌" ], [ "table_volcano", "熔岩木木桌", "一张木桌" ], [ "table_tainted", "腐化木木桌", "一张木桌" ], [ "cabinet_spruce", "云杉桌柜", "一张桌柜,可存储物品" ], [ "cabinet_birch", "桦树桌柜", "一张桌柜,可存储物品" ], [ "cabinet_jungle", "丛林桌柜", "一张桌柜,可存储物品" ], [ "cabinet_acacia", "金合欢桌柜", "一张桌柜,可存储物品" ], [ "cabinet_dark_oak", "深色橡木桌柜", "一张桌柜,可存储物品" ], [ "cabinet_palm", "棕榈桌柜", "一张桌柜,可存储物品" ], [ "cabinet_volcano", "熔岩木桌柜", "一张桌柜,可存储物品" ], [ "cabinet_tainted", "腐化木桌柜", "一张桌柜,可存储物品" ], [ "chair_spruce", "云杉椅子", "一张木制的椅子" ], [ "chair_birch", "桦树椅子", "一张木制的椅子" ], [ "chair_jungle", "丛林椅子", "一张木制的椅子" ], [ "chair_acacia", "金合欢椅子", "一张木制的椅子" ], [ "chair_dark_oak", "深色橡木椅子", "一张木制的椅子" ], [ "chair_palm", "棕榈椅子", "一张木制的椅子" ], [ "chair_volcano", "熔岩木椅子", "一张木制的椅子" ], [ "chair_tainted", "腐化木椅子", "一张木制的椅子" ], [ "bookcase_spruce", "云杉书架", "摆放着很多书籍的书架,可存储物品" ], [ "bookcase_birch", "桦树书架", "摆放着很多书籍的书架,可存储物品" ], [ "bookcase_jungle", "丛林书架", "摆放着很多书籍的书架,可存储物品" ], [ "bookcase_acacia", "金合欢书架", "摆放着很多书籍的书架,可存储物品" ], [ "bookcase_dark_oak", "深色橡木书架", "摆放着很多书籍的书架,可存储物品" ], [ "bookcase_palm", "棕榈书架", "摆放着很多书籍的书架,可存储物品" ], [ "bookcase_volcano", "熔岩木书架", "摆放着很多书籍的书架,可存储物品" ], [ "bookcase_tainted", "腐化木书架", "摆放着很多书籍的书架,可存储物品" ], [ "bench_oak", "橡木长椅", "一张长椅" ], [ "bench_spruce", "云杉长椅", "一张长椅" ], [ "bench_birch", "桦树长椅", "一张长椅" ], [ "bench_jungle", "丛林长椅", "一张长椅" ], [ "bench_acacia", "金合欢长椅", "一张长椅" ], [ "bench_dark_oak", "深色橡木长椅", "一张长椅" ], [ "bench_palm", "棕榈长椅", "一张长椅" ], [ "bench_volcano", "熔岩木长椅", "一张长椅" ], [ "bench_tainted", "腐化木长椅", "一张长椅" ], [ "prismarine_mud", "海晶泥", "大量存在于海底的方块" ], [ "snow_queen_loot", "冰雪女王战利品", "纪念击败冰雪女王" ], [ "nether_destroyer_loot", "地狱毁灭者战利品", "纪念击败地狱毁灭者" ], [ "table_nether", "地狱桌", "一张地狱要塞的桌子" ], [ "cabinet_nether", "地狱桌柜", "一张地狱要塞的桌柜,可储存物品" ], [ "bench_nether", "地狱长椅", "一张长椅" ], [ "chair_nether", "地狱椅子", "一张地狱要塞的椅子" ], [ "bookcase_nether", "地狱书架", "摆放着很多书籍的书架,可存储物品" ], [ "door_nether", "地狱门", "房子必不可少的部分" ], [ "nether_chest", "地狱箱子", "存放物品" ], [ "nether_lamp", "地狱吊灯", "提供明亮的照明" ], [ "mana_piece", "魔法碎片", "食用后提高10魔法上限" ], [ "wooden_hoe", "木锄", "用于开垦土地" ], [ "steel_axe", "钢斧", "钢制成的斧头" ], [ "bronze_axe", "青铜斧", "青铜制成的斧头" ], [ "silver_axe", "银斧", "银制成的斧头" ], [ "lead_axe", "铅斧", "铅制成的斧头" ], [ "tin_axe", "锡斧", "锡制成的斧头" ], [ "copper_axe", "铜斧", "铜制成的斧头" ], [ "steel_pickaxe", "钢镐", "钢制成的镐子" ], [ "bronze_pickaxe", "青铜镐", "青铜制成的镐子" ], [ "silver_pickaxe", "银镐", "银制成的镐子" ], [ "lead_pickaxe", "铅镐", "铅制成的镐子" ], [ "tin_pickaxe", "锡镐", "锡制成的镐子" ], [ "copper_pickaxe", "铜镐", "铜制成的镐子" ], [ "potion_glowing", "发光药水", "一瓶饮用后全身发光的药水" ], [ "potion_glowing_long", "长效发光药水", "一瓶饮用后全身发光的药水" ], [ "glowing_mushroom", "发光蘑菇", "一个散发着光芒的蘑菇" ], [ "poison_mushroom", "毒蘑菇", "禁止食用!" ], [ "large_brown_mushroom", "大型棕色蘑菇", "一个巨大的棕色蘑菇" ], [ "large_red_mushroom", "大型红蘑菇", "一个巨大的红色蘑菇" ], [ "large_poison_mushroom", "大型毒蘑菇", "一个巨大的毒蘑菇" ], [ "gray_feather", "灰羽毛", "这是一根灰色的羽毛" ], [ "nether_axe", "下界合金斧", "下界合金加固制成的斧头" ], [ "nether_pickaxe", "下界合金镐", "下界合金加固制成的镐子" ], [ "nether_sword", "下界合金剑", "下界合金加固制成的剑" ], [ "super_nether_sword", "加强下界合金剑", "下界合金加固制成的加强剑" ], [ "rocket", "火箭", "需要火箭筒来发射" ], [ "nether_altar", "地狱祭坛", "内部似乎封印着可怕的敌人" ], [ "snow_glass_ball", "冰雪女王玻璃球", "冰雪女王沉睡在这个玻璃球中" ], [ "blue_shot_bow", "魔蓝速射驽", "" ], [ "bone_gun", "魔法骨枪", "" ], [ "curse_bow", "魔法诅咒弓", "" ], [ "dark_staff", "暗黑法杖", "" ], [ "fire_book", "火焰之书", "" ], [ "fire_shooter", "喷火器", "" ], [ "fire_staff", "火之法杖", "" ], [ "frosen_staff", "强力冰冻法杖", "" ], [ "lava_sword", "熔岩剑", "" ], [ "mini_laser_gun", "迷你激光枪", "" ], [ "mini_rocket_launcher", "魔法三分火箭发射器", "" ], [ "sniper", "狙击枪", "" ], [ "soul_laserer", "灵魂迷你炮", "" ], [ "soul_staff", "灵魂法杖", "" ], [ "super_fire_shot_bow", "强力连弩", "" ], [ "super_shark", "鲨鱼枪", "" ], [ "super_shark_ghost", "鲨鱼枪", "" ], [ "super_spike_shot_bow", "钉刺枪", "" ], [ "sword_fish", "鱼枪", "" ], [ "sword_fish_gun", "剑鱼枪", "" ], [ "water_book", "水之书", "" ], [ "blue_arrow", "蓝魔箭", "可以产生穿透伤害" ], [ "rocket_boost", "火箭靴", "允许持续飞行一段时间" ], [ "blue_talisman", "魔力护符", "加速回复魔力" ], [ "heart_talisman", "生命护符", "加速回复生命" ], [ "gold_talisman", "黄金护符", "减少死亡经验损失" ], [ "lava_necklace", "熔岩护符", "免疫火焰伤害" ], [ "lighting_talisman", "星星护符", "持续提供照明" ], [ "ancient_ingot", "远古合金", "古老的合金" ], [ "ancient_sample", "远古鳞片样本", "远古生物身上的鳞片" ], [ "blood", "凝固血滴", "硬邦邦的血滴" ], [ "blue_crystal", "魔力蓝水晶", "充满魔力的蓝水晶" ], [ "dark_shadow_ingot", "魔影锭", "融入魔法力量的金属" ], [ "dark_shadow_part", "暗影碎片", "来自另一个世界的碎片" ], [ "diamond_ingot", "魔力钻石锭", "充满魔法的钻石锭" ], [ "ender_mirror", "末影魔镜", "快速传送至重生点" ], [ "evil_part", "恶魔鳞片", "来自恶魔身上的鳞片" ], [ "flesh_ingot", "血腥锭", "一块极具攻击性的未知金属" ], [ "flesh_machine_part", "生物机械零件", "拥有生物能力的机械零件" ], [ "flesh_part", "血腥碎片", "血肉模糊的碎片" ], [ "ghost", "幽魂", "为魔法系/塔防系设施提供幽魂驱动力" ], [ "ghost_crystal", "幽魂碎片", "魔法系/塔防系的基本元素" ], [ "ghost_element", "幽魂元素", "魔法系/塔防系的基本元素" ], [ "ice_element", "冰霜元素", "摸起来冷冷的" ], [ "ice_element_ball", "冰霜元素球", "摸起来冷冷的" ], [ "knight_ingot", "骑士锭", "从骑士身上掉落的未知金属" ], [ "machine_part", "机械零件", "一块机械零件" ], [ "magic_cell", "魔影细胞", "一个不断蠕动的魔法细胞" ], [ "magic_cell_group", "魔影细胞群", "一团不断蠕动的魔法细胞" ], [ "magic_crystal", "魔力水晶", "" ], [ "magic_silver_ingot", "魔银锭", "充满魔法的银锭" ], [ "magma_gold_ingot", "熔岩金锭", "熔岩包裹的金锭" ], [ "dungeon_eater", "地牢吞噬者召唤物", "可在暗黑地牢召唤地牢吞噬者" ], [ "pure_red_stone", "纯净红石", "" ], [ "red_crystal", "魔力红水晶", "充满魔力的红水晶" ], [ "red_gold_ingot", "魔金锭", "充满魔法的红色金锭" ], [ "soul_element", "灵魂元素", "" ], [ "star_ingot", "星空锭", "似乎是来自太空的未知金属" ], [ "strange_eye", "克苏鲁之眼召唤物", "可在夜晚召唤克苏鲁之眼" ], [ "strange_len", "可疑晶状体", "来自于另一个时空的晶状体" ], [ "tower_core", "防御塔核心", "放置于防御能量塔中,为所有防御塔提供能量" ], [ "white_crystal", "魔力白水晶", "充满魔力的白水晶" ], [ "yellow_crystal", "魔力黄水晶", "充满魔力的黄水晶" ], [ "ancient_helmet", "远古头盔", "全套奖励:抗火+照明 +12防御 +7攻击力 +30%移速" ], [ "ancient_chestplate", "远古胸甲", "全套奖励:抗火+照明 +12防御 +7攻击力 +30%移速" ], [ "ancient_leggings", "远古护胫", "全套奖励:抗火+照明 +12防御 +7攻击力 +30%移速" ], [ "fine_tin_helmet", "精锡头盔", "全套奖励:+3攻击力 +20%移速" ], [ "fine_tin_chestplate", "精锡胸甲", "全套奖励:+3攻击力 +20%移速" ], [ "fine_tin_leggings", "精锡护胫", "全套奖励:+3攻击力 +20%移速" ], [ "flesh_helmet", "猩红头盔", "全套奖励:+7攻击力" ], [ "flesh_chestplate", "猩红胸甲", "全套奖励:+7攻击力" ], [ "flesh_leggings", "猩红护胫", "全套奖励:+7攻击力" ], [ "knight_helmet", "骑士头盔", "全套奖励:+6防御 +5攻击力" ], [ "knight_chestplate", "骑士胸甲", "全套奖励:+6防御 +5攻击力" ], [ "knight_leggings", "骑士护胫", "全套奖励:+6防御 +5攻击力" ], [ "lava_helmet", "熔岩头盔", "全套奖励:抗火+照明" ], [ "lava_chestplate", "熔岩胸甲", "全套奖励:抗火+照明" ], [ "lava_leggings", "熔岩护胫", "全套奖励:抗火+照明" ], [ "magic_gold_helmet", "魔金头盔", "全套奖励:+2防御 +40%魔力恢复速度" ], [ "magic_gold_chestplate", "魔金胸甲", "全套奖励:+2防御 +40%魔力恢复速度" ], [ "magic_gold_leggings", "魔金护胫", "全套奖励:+2防御 +40%魔力恢复速度" ], [ "magic_shadow_helmet", "魔影头盔", "全套奖励:+3防御 +30%移速 +60%魔力恢复速度" ], [ "magic_shadow_chestplate", "魔影胸甲", "全套奖励:+3防御 +30%移速 +60%魔力恢复速度" ], [ "magic_shadow_leggings", "魔影护胫", "全套奖励:+3防御 +30%移速 +60%魔力恢复速度" ], [ "magic_silver_helmet", "魔银头盔", "全套奖励:+2防御 +40%魔力恢复速度" ], [ "magic_silver_chestplate", "魔银胸甲", "全套奖励:+2防御 +40%魔力恢复速度" ], [ "magic_silver_leggings", "魔银护胫", "全套奖励:+2防御 +40%魔力恢复速度" ], [ "shadow_helmet", "暗影头盔", "全套奖励:+100%魔力恢复速度" ], [ "shadow_chestplate", "暗影胸甲", "全套奖励:+100%魔力恢复速度" ], [ "shadow_leggings", "暗影护胫", "全套奖励:+100%魔力恢复速度" ], [ "star_helmet", "星空头盔", "全套奖励:照明 +4防御 +5攻击力 +20%魔力恢复速度" ], [ "star_chestplate", "星空胸甲", "全套奖励:照明 +4防御 +5攻击力 +20%魔力恢复速度" ], [ "star_leggings", "星空护胫", "全套奖励:照明 +4防御 +5攻击力 +20%魔力恢复速度" ], [ "super_diamond_helmet", "强化钻石头盔", "全套奖励:+8防御" ], [ "super_diamond_chestplate", "强化钻石胸甲", "全套奖励:+8防御" ], [ "super_diamond_leggings", "强化钻石护胫", "全套奖励:+8防御" ], [ "blue_mushroom", "蓝蘑菇", "" ], [ "large_blue_mushroom", "大型蓝蘑菇", "" ], [ "blue_mushroom_dirt", "蓝蘑菇泥", "" ], [ "blue_mushroom_stem", "蓝蘑菇梗", "" ], [ "ice_cobblestone_hard", "坚硬冰圆石", "" ], [ "lava_block_pile", "岩浆凝块墙", "" ], [ "pile_cobblestone", "圆石排墙", "" ], [ "snow_soft", "软雪泥", "" ], [ "volcano_burn_stone", "火山石", "" ], [ "volcano_cobblestone", "燃烧火山石", "" ] ], "chemicalFormulas": [ [ "coal", "C" ], [ "charcoal", "C" ], [ "diamond", "C" ], [ "emerald", "Be3Al2(SiO3)6" ], [ "lapis_lazuli", "(Al6Si6Ca8Na8)12(Al3Si3Na4Cl)2FeS2CaCO3" ], [ "quartz", "SiO2" ], [ "redstone", "Si(FeS2)5CrAl2O3Hg3" ], [ "iron_nugget", "Fe" ], [ "gold_nugget", "Au" ], [ "iron_ingot", "Fe" ], [ "gold_ingot", "Au" ], [ "redstone_ingot", "Si(FeS2)5CrAl2O3Hg3" ], [ "copper_ingot", "Cu" ], [ "tin_ingot", "Sn" ], [ "bronze_ingot", "SnCu3" ], [ "lead_ingot", "Pb" ], [ "silver_ingot", "Ag" ], [ "steel_ingot", "Fe50C" ], [ "lithium_ingot", "Li" ], [ "beryllium_ingot", "Be" ], [ "sodium_ingot", "Na" ], [ "magnesium_ingot", "Mg" ], [ "aluminum_ingot", "Al" ], [ "titanium_ingot", "Ti" ], [ "vanadium_ingot", "V" ], [ "chromium_ingot", "Cr" ], [ "manganese_ingot", "Mn" ], [ "cobalt_ingot", "Co" ], [ "nickel_ingot", "Ni" ], [ "zinc_ingot", "Zn" ], [ "gallium_ingot", "Ga" ], [ "yttrium_ingot", "Y" ], [ "niobium_ingot", "Nb" ], [ "molybdenum_ingot", "Mo" ], [ "palladium_ingot", "Pd" ], [ "indium_ingot", "In" ], [ "antimony_ingot", "Sb" ], [ "tantalum_ingot", "Ta" ], [ "wolfram_ingot", "W" ], [ "rhenium_ingot", "Re" ], [ "osmium_ingot", "Os" ], [ "iridium_ingot", "Ir" ], [ "platinum_ingot", "Pt" ], [ "bismuth_ingot", "Bi" ], [ "vibranium_ingot", "Vb" ] ] } ================================================ FILE: languages/english.json ================================================ { "modTexts": [ [ "BACK", "Back" ], [ "DESC", "Description" ], [ "WEB", "Website" ], [ "OK", "OK" ], [ "SINGLE_PLAYER", "Singleplayer" ], [ "MULTI_PLAYER", "Multiplayer" ], [ "MOD_LIST", "Mod List"], [ "COMMUNITY", "Community" ], [ "SETTING", "Option" ], [ "EXIT_GAME", "Exit Game" ], [ "COPYRIGHT", "BlueYoshi.cn/TerraCraft 进击的蓝耀西(Bilibili)" ], [ "MOD_LOADER_INFO", "[Mod Loader] Total %d mods loaded" ], [ "ENGINE_VERSION", "Engine Version %s" ], [ "OPEN_MOD_FOLDER", "Open Mods Folder" ], [ "MANAGER_SOURCES", "Manager Sources.." ], [ "ALL_MOD_LOADED", "All mods (%d loaded)" ], [ "MOD_VERSION", "Mod Version" ], [ "MOD_AUTHORS", "Mod Authors" ], [ "MOD_FOLDER_UNSUPPORTED", "Mobile version does not support opening mods folder function." ], [ "WEB_SOURCE_GITHUB", "Sources (Github)" ], [ "WEB_HOME", "Homepage" ], [ "help:kill", "Kill yourself." ], [ "help:killp", "Kill the targeted player." ], [ "help:buff", "Add BUFF and set the duration." ], [ "help:buffp", "Add BUFF to the targeted player and set the duration." ], [ "help:spawn", "Teleport to spawn point." ], [ "help:home", "Teleport to respawn point." ], [ "help:ex", "Increase experience points." ], [ "help:exp", "Increase experience points to the targeted player." ], [ "help:give", "Give items and set the count." ], [ "help:givep", "Give items to the targeted player and set the count." ], [ "help:gamemode", "Set the game mode of yourself." ], [ "help:gamemodep", "Set the game mode of the targeted player." ], [ "help:gamemodew", "Set the game mode of world." ], [ "help:npc", "Create an NPC at the specified location." ], [ "help:effect", "Create an Effect at the specified location." ], [ "help:tp", "Teleport to a specified location." ], [ "help:tpp", "Teleport the targeted player to a specified location." ], [ "help:me", "Display a message about yourself." ], [ "help:msg", "Send a private message to the targeted player." ], [ "help:say", "Broadcast a message." ], [ "help:clear", "Clear your backpack." ], [ "help:clearp", "Clear backpack of the targeted player." ], [ "help:day", "Set the time of day." ], [ "help:dayf", "Set the hour, minute, second of the time of day." ], [ "help:dayspeed", "Set the elapsed speed of time." ], [ "help:daylock", "Lock the time of day." ], [ "help:dayunlock", "Unlock the time of day." ], [ "help:wea", "Set the weather time." ], [ "help:stopwea", "Cancel the weather event." ], [ "help:admin", "Give the targeted player administrator authority." ], [ "help:noadmin", "Deprive the targeted player administrator authority." ], [ "help:master", "Give the targeted player server owner authority." ], [ "help:nomaster", "Deprive the targeted player server owner authority." ], [ "help:save", "Save the world immediately." ], [ "help:autosave-on", "Open autosave mode." ], [ "help:autosave-off", "Close autosave mode." ], [ "help:port", "Display the server port." ], [ "help:state", "Display server running status." ], [ "help:pvp-on", "Open PVP mode." ], [ "help:pvp-off", "Close PVP mode." ], [ "help:safeblow-on", "All explosions will destroy tiles." ], [ "help:safeblow-off", "All explosions will not destroy tiles." ], [ "help:players", "Display all online players." ], [ "help:kick", "Kick a player with a certain name." ], [ "help:kickall", "Kick all players." ], [ "help:banip", "Do not allow an ip to access the server." ], [ "help:nobanip", "Allow an ip to access the server." ], [ "help:blacklist", "Show all banned IPs." ], [ "help:enchant", "Enchant the hand-held item and set the level." ], [ "help:blueyoshiiscool", "An easter egg." ], [ "ex_ok", "Give %s experience levels %d." ], [ "buff_ok", "Give %s buff %s duration %d seconds." ], [ "em_ok", "Give %s's item %s enchantment %s level %d." ], [ "em_fail", "Enchanting failed." ], [ "spawn_ok", "Teleport %s to spawn point." ], [ "home_ok", "Teleport %s to home." ], [ "home_fail", "Cannot find the home of %s." ], [ "give_ok", "Give %s item %s * %d" ], [ "clear_ok", "The backpack of %s has been cleared." ], [ "day_ok", "The current day time is set to %02d:%02d:%02d" ], [ "dayspeed_ok", "The time lapse speed has been set to %.2f times." ], [ "wea_ok", "The current weather progress is %d%%." ], [ "admin_ok", "The player %s has been set as an administrator." ], [ "noadmin_ok", "The admin rights of player %s have been cancelled." ], [ "master_ok", "The player %s has been set as an server owner." ], [ "nomaster_ok", "The owner rights of player %s have been cancelled." ], [ "save_ok", "[Saving] has been added to the server processing queue." ], [ "player_info", "(%d) %s (%s:%d)" ], [ "players_ok", "%d players online." ], [ "autosave_on_ok", "The [Auto Save] mode is turned on." ], [ "autosave_off_ok", "The [Auto Save] mode is turned off." ], [ "pvp_on_ok", "The [PVP] mode is turned on." ], [ "pvp_off_ok", "The [PVP] mode is turned oFF." ], [ "safeblow_on_ok", "The [Explosion Protection] mode is turned on." ], [ "safeblow_off_ok", "The [Explosion Protection] mode is turned off." ], [ "port_ok", "The server port number is %d" ], [ "kick_ok", "Kicked %s" ], [ "blacklist_info", "(%d) %s" ], [ "blacklist_ok", "There are %d entries in blacklist." ], [ "banip_ok", "IP %s has been banned and added to the server blacklist." ], [ "nobanip_ok", "IP %s has been removed from the server blacklist." ], [ "nobanip_fail", "IP %s does not exist in the server blacklist." ], [ "gamemodep_s_ok", "The game mode of player %s has been changed to survival mode." ], [ "gamemodep_c_ok", "The game mode of player %s has been changed to creative mode." ], [ "gamemodep_a_ok", "The game mode of player %s has been changed to adventure mode." ], [ "gamemodew_s_ok", "The game mode of world has been changed to survival mode." ], [ "gamemodew_c_ok", "The game mode of world has been changed to creative mode." ], [ "gamemodew_a_ok", "The game mode of world has been changed to adventure mode." ], [ "msg_content", "[PM from %s] %s" ], [ "msg_server_content", "[PM from server] %s" ], [ "msg_to_content", "[PM to %s] %s" ], [ "msg_server_to_content", "[PM to %s] %s" ], [ "say", "[Server] %s" ], [ "npc_ok", "Created npc %s at (%d, %d)" ], [ "tp_ok", "Teleported player %s to (%d, %d)" ], [ "blueyoshiiscool_ok", "Blueyoshi is cool!!!" ] ], "enchantments": [ [ "silk_touch", "Silk Youch" ], [ "fortune", "Fortune" ], [ "phyton", "Phyton" ], [ "unbreaking", "Unbreaking" ], [ "efficiency", "Efficiency" ], [ "aqua_affinity", "Aqua Affinity" ], [ "bane_of_arthropods", "Bane of Arthropods" ], [ "blast_protection", "Blast Protection" ], [ "curse_of_binding", "Curse of Binding" ], [ "curse_of_vanishing", "Curse of Vanishing" ], [ "depth_strider", "Depth Strider" ], [ "feather_falling", "Feather Falling" ], [ "fire_aspect", "Fire Aspect" ], [ "fire_protection", "Fire Protection" ], [ "flame", "Flame" ], [ "frost_walker", "Frost Walker" ], [ "infinity", "Infinity" ], [ "knockback", "Knockback" ], [ "looting", "Looting" ], [ "luck_of_the_sea", "Luck of the Sea" ], [ "lure", "Lure" ], [ "multishot", "Multishot" ], [ "piercing", "Piercing" ], [ "power", "Power" ], [ "projectile_protection", "Projectile Protection" ], [ "protection", "Protection" ], [ "punch", "Punch" ], [ "quick_charge", "Quick Charge" ], [ "respiration", "Respiration" ], [ "sharpness", "Sharpness" ], [ "smite", "Smite" ], [ "thorns", "Thorns" ] ], "buffs": [ [ "absorption", "Absorption" ], [ "blindness", "Blindness" ], [ "fire", "Fire" ], [ "fire_defense", "Fire Defense" ], [ "glowing", "Glowing" ], [ "happiness", "Happiness" ], [ "health_boost", "Health Boost" ], [ "hunger", "Hunger" ], [ "hurt", "Hurt" ], [ "invisibility", "Invisibility" ], [ "jump_boost", "Jump Boost" ], [ "levitation", "Levitation" ], [ "luck", "Luck" ], [ "mining_fatique", "Mining Fatique" ], [ "nausea", "Nausea" ], [ "poison", "Poison" ], [ "regeneration", "Regeneration" ], [ "resistance", "Resistance" ], [ "sadness", "Sadness" ], [ "slow_falling", "Slow Falling" ], [ "slow_mining", "Slow Mining" ], [ "slowness", "Slowness" ], [ "speed", "Speed" ], [ "strength", "Strength" ], [ "vision", "Night Vision" ], [ "water_breathing", "Water Breathing" ], [ "weak", "Weak" ], [ "wither", "Wither" ], [ "health_cold", "Health Cold" ] ], "advancements": [ [ "inventory", "Start Terracraft!", "WASD: Move\nSPACE: Jump\nSHIFT+Left Click: Place/Dig Wall\nLeft Click: Place/Use\nRight Click: Interact\nCTRL: Auto Mode\nQ: Drop\nE: Inventory\nR: Recipes\nF: Advancements\nT: Chat\nTAB: Ping List\nF1: Hide UI\nF3: Debug" ], [ "wood", "Getting Wood", "Punch a tree until a block of wood pops out." ], [ "crafting_table", "Benchmaking", "Craft a workbench with four blocks of wooden wood planks." ], [ "farm", "Time to Farm!", "Make a Hoe." ], [ "bread", "Bake Bread", "Turn wheat into bread." ], [ "cake", "The Lie", "Bake a cake using: wheat, sugar, milk, and eggs." ], [ "bow", "Archer!", "Use strings and wooden sticks to make a bow." ], [ "crossbow", "Crossbow archer!", "Make a crossbow." ], [ "mine", "Time to Mine!", "Use planks and sticks to make a pickaxe." ], [ "stone", "Stone Age", "Mine stone with your new pickaxe." ], [ "mine_up", "Getting an Upgrade", "Construct a better pickaxe." ], [ "furnace", "Hot Topic", "Construct a furnace out of eight cobblestone blocks." ], [ "iron", "Acquire Hardware", "Smelt metal ore in the furnace." ], [ "sword", "Time to Strike!", "Use planks and sticks to make a sword." ], [ "leather", "Cow Tipper", "Harvest some leather." ], [ "hunter", "Monster Hunter", "Attack and destroy a monster." ], [ "staff", "Magic Staff", "Make a magic staff." ], [ "magic_limit", "Magician", "Eat a magic fragment that increases the upper limit of magic." ], [ "ender_pearl", "Enderman Killer", "Obtain an ender pearl." ], [ "steel", "Refined Iron!", "Smelt an iron ingot to get a steel ingot." ], [ "bronze", "Bronze Age", "Obtain a bronze ingot" ], [ "diamond", "DIAMONDS!", "Acquire diamonds with your metal tools." ], [ "enchant", "Enchanter", "Construct an Enchantment Table." ], [ "nether", "Need to go deeper", "Get into nether layer." ], [ "blaze_rod", "Into Fire", "Relieve a Blaze of its rod." ], [ "brew", "Local Brewery", "Make a brewing stand." ], [ "ghast", "Go to hell!", "Defeat a Ghast." ], [ "netherite", "Hidden in the Depths", "Obtain Ancient Debris." ], [ "gun", "Arms Dealer", "Obtain a gun in the nether fortress." ], [ "redstone", "Redstone Found!", "Obtain a redstone powder." ], [ "redstone_wire", "Redstone Technology", "Make a redstone wire." ], [ "lava", "Super Fuel", "Get a bucket of lava." ], [ "pumpkin_helmet", "Halloween!", "Make a Halloween-style pumpkin helmet." ], [ "ender_chest", "Alien Space", "Make an ender box." ], [ "guardian", "Intruder!", "Defeat a guardian on the seabed." ], [ "snow_queen", "Snow Queen!", "Awaken the Snow Queen from the Snow Queen Glass Ball." ], [ "snow_queen_killed", "Liberation of the Aurora Palace", "Defeat the Snow Queen." ], [ "nether_destroyer", "Destroy the Nether!", "Destroy the nether altar to release the Nether Destroyer." ], [ "nether_destroyer_killed", "Save the Nether", "Defeat the Nether Destroyer." ], [ "diamond_wear", "Cover Me With Diamonds", "Diamond armor saves lives." ], [ "netherite_full_wear", "Cover Me in Debris", "Get a full suit of Netherite armor." ] ], "npcs": [ [ "pig", "Pig" ], [ "zombie", "Zombie" ], [ "husk", "Husk" ], [ "mummy", "Mummy" ], [ "waste_mummy", "Waste Mummy" ], [ "villager_zombie", "Villager Zombie" ], [ "arrow_zombie", "Arrow Zombie" ], [ "bald_zombie", "Bald Zombie" ], [ "doge_zombie", "Doge Zombie" ], [ "iron_zombie", "Iron Zombie" ], [ "skeleton", "Skeleton" ], [ "tainted_skeleton", "Tainted Skeleton" ], [ "blood_skeleton", "Bloody Skeleton" ], [ "angry_skeleton", "Angry Skeleton" ], [ "black_skeleton", "Black Skeleton" ], [ "boney_skeleton", "Boney Skeleton" ], [ "creeper", "Creeper" ], [ "flower_creeper", "Flower Creeper" ], [ "tainted_creeper", "Tainted Creeper" ], [ "spider", "Spider" ], [ "bat", "Bat" ], [ "jungle_bat", "Jungle Bat" ], [ "large_jungle_bat", "Large Jungle Bat" ], [ "blood_bat", "Bloody Bat" ], [ "man_eater", "Man Eater" ], [ "blood_eye", "Bloody Eye" ], [ "chicken", "Chicken" ], [ "cow", "Cow" ], [ "sheep", "Sheep" ], [ "red_mushroom_cow", "Mooshroom" ], [ "brown_mushroom_cow", "Mooshroom" ], [ "cat", "Cat" ], [ "white_rabbit", "White Rabbit" ], [ "brown_rabbit", "Brown Rabbit" ], [ "black_rabbit", "Black Rabbit" ], [ "yellow_rabbit", "Yellow Rabbit" ], [ "squid", "Squid" ], [ "turtle", "Turtle" ], [ "pufferfish", "Pufferfish" ], [ "dolphin", "Dolphin" ], [ "wolf", "Wolf" ], [ "enderman", "Enderman" ], [ "zombie_pigman", "Zombie Pigman" ], [ "blaze", "Blaze" ], [ "drowned", "Drowned" ], [ "guardian", "Guardian" ], [ "ghast", "Ghast" ], [ "ice_elf", "Ice Elf" ], [ "magma_elf", "Magma Elf" ], [ "waste_ghost", "Waste Ghost" ], [ "large_block_slime", "Large Block Slime" ], [ "block_slime", "Block Slime" ], [ "large_ice_slime", "Large Ice Slime" ], [ "ice_slime", "Ice Slime" ], [ "large_waste_block_slime", "Large Waste Block Slime" ], [ "waste_block_slime", "Waste Block Slime" ], [ "green_slime", "Green Slime" ], [ "large_green_slime", "Large Green Slime" ], [ "large_black_slime", "Large Black Slime" ], [ "large_waste_slime", "Large Waste Slime" ], [ "large_tainted_slime", "Large Tainted Slime" ], [ "blood_slime", "Bloody Slime" ], [ "yellow_slime", "Yellow Slime" ], [ "desert_slime", "Desert Slime" ], [ "large_desert_slime", "Large_desert Slime" ], [ "blue_slime", "Blue Slime" ], [ "purple_slime", "Purple Slime" ], [ "snow_slime", "Snow Slime" ], [ "tainted_slime", "Tainted Slime" ], [ "magma_slime", "Magma Slime" ], [ "phantom", "Phantom" ], [ "eagle", "Eagle" ], [ "magma_birdo", "Magma Birdo" ], [ "meteor", "Meteor" ], [ "shulker", "Shulker" ], [ "evoker", "Evoker" ], [ "wither_skeleton", "Wither Skeleton" ], [ "ender_dragon", "Ender Dragon" ], [ "light_blue_butterfly", "Light Blue Butterfly" ], [ "yellow_butterfly", "Yellow Butterfly" ], [ "red_butterfly", "Red Butterfly" ], [ "worm_head", "Nether Destroyer" ], [ "worm_body", "Nether Destroyer" ], [ "worm_tail", "Nether Destroyer" ], [ "vine_man_eater_head", "Jungle Man Eater" ], [ "vine_man_eater_body", "Jungle Man Eater" ], [ "vine_man_eater_tail", "Jungle Man Eater" ], [ "snow_queen", "Snow Queen" ], [ "small_hell_eater", "Hell Eater" ], [ "snow_guardian", "Snow Guardian" ], [ "snow_guardian_archer", "Snow Guardian Archer" ], [ "small_fire_hell_eater", "Burning Eater" ] ], "projectiles": [ [ "wooden_arrow", "Wooden Arrow" ], [ "lighting_arrow", "Lighting Arrow" ], [ "star_arrow", "Star Arrow" ], [ "blood_arrow", "Bloody Arrow" ], [ "ice_arrow", "Ice Arrow" ], [ "sword_arrow", "Sword Arrow" ], [ "air_bullet", "Air Bullet" ], [ "small_air_bullet", "Air Bullet" ], [ "amethyst_magic", "Amethyst Magic" ], [ "star", "Star Magic" ], [ "ice_magic", "Ice Magic" ], [ "shadow_magic", "Shadow Magic" ], [ "water_magic", "Water Magic" ], [ "fire_magic", "Fire Magic" ], [ "crystal_magic", "Crystal Magic" ], [ "ice_bullet", "Ice Bullet" ], [ "boomerang", "Boomerang" ], [ "wooden_boomerang", "Wooden Boomerang" ], [ "fire_boomerang", "Fire Boomerang" ], [ "rocket", "Rocket" ], [ "blaze_rod", "Blaze Rod" ], [ "fire_charge", "Fireball" ], [ "shulker_bullet", "Shulker bullet" ], [ "bullet", "Bullet" ], [ "gun_fire", "Fire" ], [ "bullet_laser", "Laser" ], [ "bullet_super", "Buper" ], [ "tnt", "TNT" ], [ "bomb", "Bomb" ], [ "grenade", "Grenade" ], [ "glow_bomb", "Glowing Bomb" ], [ "glow_ball", "Glowing Ball" ], [ "snow_flake", "Snow Flake" ] ], "items": [ [ "stone_axe", "Stone Axe", "More efficient than the wooden one." ], [ "dirt", "Dirt", "A dirt block covering the ground." ], [ "stone", "Stone", "A smoother stone." ], [ "cobblestone", "Cobblestone", "A Basic stone material." ], [ "stick", "Stick", "A wooden stick." ], [ "gravel", "Gravel", "A block mixed with various impurities." ], [ "sand", "Sand", "The source of glass." ], [ "ore_coal", "Coal Ore", "A mineral ore, require further processing." ], [ "ore_iron", "Iron Ore", "A mineral ore, require further processing." ], [ "ore_gold", "Gold Ore", "A mineral ore, require further processing." ], [ "ore_lapis", "Lapis Ore", "A mineral ore, require further processing." ], [ "ore_redstone", "Redstone Ore", "A mineral ore, require further processing." ], [ "ore_diamond", "Diamond Ore", "A mineral ore, require further processing." ], [ "ore_emerald", "Emerald Ore", "A mineral ore, require further processing." ], [ "stone_pickaxe", "Stone Pickaxe", "Better than the wooden one." ], [ "stone_sword", "Stone Sword", "A sword made of stone." ], [ "furnace", "Furnace", "Smelt or cook items." ], [ "chest", "Chest", "Store items." ], [ "oak_plank", "Oak Plank", "A wooden building material." ], [ "grass_axe", "Grass Axe", "Endless regeneration ability." ], [ "grass_pickaxe", "Grass Pickaxe", "Endless regeneration ability." ], [ "grass_sword", "Grass Sword", "A weak grass sword." ], [ "iron_ingot", "Iron Ingot", "" ], [ "gold_ingot", "Gold Ingot", "" ], [ "redstone_ingot", "Redstone Ingot", "" ], [ "copper_ingot", "Copper Ingot", "" ], [ "tin_ingot", "Tin Ingot", "" ], [ "bronze_ingot", "Bronze Ingot", "" ], [ "lead_ingot", "Lead Ingot", "" ], [ "silver_ingot", "Silver Ingot", "" ], [ "steel_ingot", "Steel Ingot", "" ], [ "lithium_ingot", "Lithium Ingot", "" ], [ "beryllium_ingot", "Beryllium Ingot", "" ], [ "sodium_ingot", "Sodium Ingot", "" ], [ "magnesium_ingot", "Magnesium Ingot", "" ], [ "aluminum_ingot", "Aluminum Ingot", "" ], [ "titanium_ingot", "Titanium Ingot", "" ], [ "vanadium_ingot", "Vanadium Ingot", "" ], [ "chromium_ingot", "Chromium Ingot", "" ], [ "manganese_ingot", "Manganese Ingot", "" ], [ "cobalt_ingot", "Cobalt Ingot", "" ], [ "nickel_ingot", "Nickel Ingot", "" ], [ "zinc_ingot", "Zinc Ingot", "" ], [ "gallium_ingot", "Gallium Ingot", "" ], [ "yttrium_ingot", "Yttrium Ingot", "" ], [ "niobium_ingot", "Niobium Ingot", "" ], [ "molybdenum_ingot", "Molybdenum Ingot", "" ], [ "palladium_ingot", "Palladium Ingot", "" ], [ "indium_ingot", "Indium Ingot", "" ], [ "antimony_ingot", "Antimony Ingot", "" ], [ "tantalum_ingot", "Tantalum Ingot", "" ], [ "wolfram_ingot", "Wolfram Ingot", "" ], [ "rhenium_ingot", "Rhenium Ingot", "" ], [ "osmium_ingot", "Osmium Ingot", "" ], [ "iridium_ingot", "Iridium Ingot", "" ], [ "platinum_ingot", "Platinum Ingot", "" ], [ "bismuth_ingot", "Bismuth Ingot", "" ], [ "vibranium_ingot", "Vibranium Ingot", "" ], [ "andesite", "Andesite", "Rich in calcium and alkaline." ], [ "andesite_polished", "Polished Andesite", "Andesite material after polishing." ], [ "clay", "Clay", "This is a clay ball." ], [ "cobblestone_mossy", "Mossy Cobblestone", "Cobblestone covered with moss." ], [ "diorite", "Diorite", "A variant of stone." ], [ "diorite_polished", "Polished Diorite", "Andesite material after polishing." ], [ "glass", "Glass", "Light-transmissive glass." ], [ "granite", "Granite", "A variant of stone." ], [ "granite_polished", "Polished Granite", "Andesite material after polishing." ], [ "ice", "Ice", "Cold and fragile ice." ], [ "ice_cobblestone", "Ice Cobblestone", "Frozen stone" ], [ "ice_packed", "Packed Ice", "The unique internal structure make it never melt." ], [ "obsidian", "Obsidian", "Forms when Magma meets water, and has a high hardness." ], [ "prismarine", "Prismarine", "Building materials for underwater ruins." ], [ "prismarine_brick", "Prismarine Brick", "Prismarine brick with jagged stripes." ], [ "prismarine_dark", "Dark Prismarine", "Has a grid-like pattern." ], [ "red_sand", "Red Sand", "Rich in iron oxide red sand." ], [ "red_sand_carved", "Carved Red Sand", "Carved red sand bricks." ], [ "red_sand_smooth", "Smooth Red Sand", "Red sand brick with smooth surface." ], [ "sandstone", "Sandstone", "Hard sand." ], [ "sandstone_carved", "Carved Sandstone", "Carved sandstone bricks." ], [ "sandstone_smooth", "Smooth Sandstone", "Sandstone bricks with smooth surfaces." ], [ "snow", "Snow", "Soft snow block." ], [ "stone_brick", "Stone Brick", "A stone material for construction." ], [ "stone_brick_carved", "Carved Stone Brick", "Carved stone building materials." ], [ "stone_brick_cracked", "Cracked Stone Brick", "Cracked stone building material." ], [ "stone_brick_mossy", "Mossy Stone Brick", "Stone brick covered with moss." ], [ "bucket_empty", "Bucket Empty", "An empty bucket, can hold liquid." ], [ "bucket_water", "Bucket Water", "A bucket full of water, left-click to pour out water." ], [ "bucket_lava", "Bucket Lava", "A bucket full of lava, left click to pour out the lava." ], [ "bucket_milk", "Bucket Milk", "A bucket full of milk, can remove all buffs." ], [ "snowball", "Snowball", "Round snowball." ], [ "vine", "Vine", "This is a vine." ], [ "sugar_cane", "Sugar Cane", "For making sugars or books." ], [ "suger", "Suger", "It tastes sweet." ], [ "paper", "Paper", "A piece of paper." ], [ "leather", "Leather", "Animal fur." ], [ "book", "Book", "this is a book." ], [ "wheat", "Wheat", "Can be processed into many foods." ], [ "bread", "Bread", "Sweet bread." ], [ "bone", "Bone", "A bone." ], [ "bone_meal", "Bone Meal", "Can be used to ripen crops." ], [ "crafting_table", "Crafting Table", "Use a 3x3 square matrix to craft more items." ], [ "torch", "Torch", "Basic and cheap lighting tools." ], [ "coal", "Coal", "" ], [ "charcoal", "Charcoal", "" ], [ "string", "String", "A long thin thread." ], [ "wooden_bow", "Wooden Bow", "Suitable for long-range attacks." ], [ "flint", "Flint", "Sharp flint." ], [ "feather", "Feather", "This is a feather." ], [ "wooden_arrow", "Wooden Arrow", "A shootable arrow." ], [ "rocket_launcher", "Rocket Launcher", "Destroy everything!!!!" ], [ "redstone_lamp", "Redstone Lamp", "Light up after charging." ], [ "red_wire", "Red Wire", "Can transmit redstone power." ], [ "clay_block", "Clay Block", "Source of construction materials." ], [ "brick", "Brick", "A Construction material." ], [ "spruce_plank", "Spruce Plank", "Wooden building materials." ], [ "birch_plank", "Birch Plank", "Wooden building materials." ], [ "jungle_plank", "Jungle Plank", "Wooden building materials." ], [ "acacia_plank", "Acacia Plank", "Wooden building materials." ], [ "dark_oak_plank", "Dark Oak Plank", "Dark wooden building materials." ], [ "block_iron", "Iron Block", "Made of pressed iron ingots." ], [ "block_gold", "Gold Block", "Made of pressed gold ingots" ], [ "block_coal", "Coal Block", "Has a great burning value." ], [ "block_diamond", "Diamond Block", "Made of diamonds." ], [ "block_emerald", "Emerald Block", "Made of emeralds." ], [ "block_lapis", "Lapis Block", "Made of lapis lazuli." ], [ "block_redstone", "RedstoneBlock", "Made of redstones." ], [ "bone_block", "Bone Block", "Calcium-rich." ], [ "red_brick", "Red Brick", "Red brick fired from clay." ], [ "brown_mushroom_block", "Brown Mushroom Block", "From giant brown mushrooms." ], [ "coarse_dirt", "Coarse Dirt", "Mud variants, has a strong acidity." ], [ "cobblestone_fence", "Cobblestone Fence", "Made of stone." ], [ "end_stone", "End Stone", "The main blocks of the end." ], [ "end_stone_brick", "End Stone Brick", "Brick made of end stone." ], [ "farmland", "Farmland", "You can sow and harvest crops on this." ], [ "fence_oak", "Oak Fence", "Wooden fence." ], [ "fence_birch", "Birch Fence", "Wooden fence." ], [ "fence_spruce", "Spruce Fence", "Wooden fence." ], [ "fence_jungle", "Jungle Fence", "Wooden fence." ], [ "fence_acacia", "Acacia Fence", "Wooden fence." ], [ "fence_dark_oak", "Dark Oak Fence", "Wooden fence." ], [ "fence_nether", "Nether Fence", "Dark black fence of nether." ], [ "glowstone", "Glowstone", "A shining stone." ], [ "hay_bale", "Hay Bale", "A sheaf of wheat." ], [ "ice_brick", "Ice Brick", "A Brick made of ice." ], [ "iron_bar", "Iron Bar", "Window with iron grating." ], [ "magma_block", "Magma Block", "Solid magma." ], [ "mossy_cobblestone_fence", "Mossy Cobblestone Fence", "Stone fence covered with moss." ], [ "mushroom_stem", "Mushroom Stem", "The stem of giant mushroom." ], [ "netherrack", "Netherrack", "The main block of nether." ], [ "nether_brick_block", "Nether Brick Block", "Dark black nether brick." ], [ "purpur_block", "Purpur Block", "A Block made of purpur." ], [ "red_mushroom_block", "Red Mushroom Block", "From giant red mushrooms." ], [ "red_nether_brick", "Red Nether Brick", "Red dark nether brick." ], [ "red_sand_stone", "Red Sand Stone", "Hard red sand." ], [ "sea_lantern", "Sea Lantern", "Glowing block in the sea." ], [ "slime_block", "Slime Block", "Sticky gelatin block." ], [ "snow_brick", "Snow Brick", "Hardened snow brick." ], [ "soul_sand", "Soul Sand", "The fragile sand block seems to seal the soul inside." ], [ "sponge", "Sponge", "The fluffy sponge block can absorb a lot of water." ], [ "wet_sponge", "Wet Sponge", "Saturated sponge absorbed in water, can be recycled after drying." ], [ "terracotta_white", "White Terracotta", "Hard terracotta." ], [ "terracotta_orange", "Orange Terracotta", "Hard terracotta." ], [ "terracotta_magenta", "Magenta Terracotta", "Hard terracotta." ], [ "terracotta_light_blue", "Light Blue Terracotta", "Hard terracotta." ], [ "terracotta_yellow", "Yellow Terracotta", "Hard terracotta." ], [ "terracotta_lime", "Lime Terracotta", "Hard terracotta." ], [ "terracotta_pink", "Pink Terracotta", "Hard terracotta." ], [ "terracotta_gray", "Gray Terracotta", "Hard terracotta." ], [ "terracotta_light_gray", "Light Gray Terracotta", "Hard terracotta." ], [ "terracotta_cyan", "Cyan Terracotta", "Hard terracotta." ], [ "terracotta_purple", "Purple Terracotta", "Hard terracotta." ], [ "terracotta_blue", "Blue Terracotta", "Hard terracotta." ], [ "terracotta_brown", "Brown Terracotta", "Hard terracotta." ], [ "terracotta_green", "Green Terracotta", "Hard terracotta." ], [ "terracotta_red", "Red Terracotta", "Hard terracotta." ], [ "terracotta_black", "Black Terracotta", "Hard terracotta." ], [ "tnt", "Tnt", "It will explode after being activated." ], [ "wood_oak", "Oak Wood", "Fresh log just cut down." ], [ "wood_birch", "Birch Wood", "Fresh log just cut down." ], [ "wood_spruce", "Spruce Wood", "Fresh log just cut down." ], [ "wood_jungle", "Jungle Wood", "Fresh log just cut down." ], [ "wood_acacia", "Acacia Wood", "Fresh log just cut down." ], [ "wood_dark_oak", "Dark Oak Wood", "Fresh log just cut down." ], [ "fishing_rod", "Fishing Rod", "Can be used for fishing." ], [ "wood_stripped_oak", "Oak Stripped Wood", "A Log peeled off the bark." ], [ "wood_stripped_birch", "Birch Stripped Wood", "A Log peeled off the bark." ], [ "wood_stripped_spruce", "Spruce Stripped Wood", "A Log peeled off the bark." ], [ "wood_stripped_jungle", "Jungle Stripped Wood", "A Log peeled off the bark." ], [ "wood_stripped_acacia", "Acacia Stripped Wood", "A Log peeled off the bark." ], [ "wood_stripped_dark_oak", "Dark Oak Stripped Wood", "A Log peeled off the bark." ], [ "allium", "Allium", "A small flower." ], [ "anvil", "Anvil", "Used to repair broken tools." ], [ "azure_bluet", "Azure Bluet", "A small flower." ], [ "wooden_bed_red", "Wooden Bed Red", "This is a bed, used to reset the respawn point." ], [ "blue_orchid", "Blue Orchid", "A small flower." ], [ "book_block", "Book Block", "The ocean of knowledge." ], [ "bookcase_oak", "Bookcase Oak", "A shelf with many books, can store items." ], [ "brewing_stand", "Brewing Stand", "Brew potion with various effects." ], [ "brown_mushroom", "Brown Mushroom", "A brown mushroom." ], [ "cake", "Cake", "A Creamy cake, can be cut into slices." ], [ "candle", "Candle", "This is a candle." ], [ "candle_holder", "Candle Holder", "Candlestick with western characteristics." ], [ "cauldron", "Cauldron", "This is a cauldron." ], [ "chair_oak", "Wooden Chair Oak", "A wooden chair." ], [ "chandeliers", "Chandeliers", "Bright and luxurious crystal chandelier." ], [ "stone_chest", "Stone Chest", "Store items." ], [ "cobweb", "Cobweb", "A spider web, can trap various creatures." ], [ "dandelion", "Dandelion", "A small flower." ], [ "daylight_sensor", "Daylight Sensor", "Continuously output the redstone signal under the sunlight." ], [ "daylight_sensor_inverted", "Moonlight Sensor", "Continuously output the redstone signal under the moonlight." ], [ "dispenser", "Dispenser", "Launches an item when the redstone signal is activated." ], [ "ender_chest", "Ender Chest", "The quantum effect makes all ender chests share a space." ], [ "fern", "Fern", "A spore plant." ], [ "fire_lamp", "Fire Lamp", "Provides bright lighting." ], [ "wooden_pressure_plate", "Wooden Pressure Plate", "Activate the redstone signal after stepping." ], [ "stone_pressure_plate", "Stone Pressure Plate", "Activate the redstone signal after stepping." ], [ "iron_pressure_plate", "Iron Pressure Plate", "Activate the redstone signal after stepping." ], [ "golden_pressure_plate", "Golden Pressure Plate", "Activate the redstone signal after stepping." ], [ "jukebox", "Jukebox", "Put in a record and enjoy the music." ], [ "grass", "Grass", "This is a grass." ], [ "iron_door", "Iron Door", "The essential part of the house." ], [ "lilac", "Lilac", "A large plant." ], [ "orange_tulip", "Orange Tulip", "A small flower." ], [ "red_tulip", "Red Tulip", "A small flower." ], [ "white_tulip", "White Tulip", "A small flower." ], [ "pink_tulip", "Pink Tulip", "A small flower." ], [ "painting_2x2", "Painting 2X2", "Welcome to contribute. 0w0" ], [ "peony", "Peony", "A large plant." ], [ "poppy", "Poppy", "A small flower." ], [ "pumpkin", "Pumpkin", "A whole pumpkin." ], [ "pumpkin_carved", "Carved Pumpkin", "Carved pumpkin with Halloween pattern." ], [ "red_mushroom", "Red Mushroom", "A red mushroom." ], [ "rose_bush", "Rose Bush", "A large plant." ], [ "sapling_oak", "Oak Sapling", "A sapling, grows into an oak tree after planting." ], [ "sapling_birch", "Birch Sapling", "A sapling, grows into a birch tree after planting." ], [ "sapling_jungle", "Jungle Sapling", "A sapling, grows into a jungle tree after planting." ], [ "sapling_spruce", "Spruce Sapling", "A sapling, grows into a spruce tree after planting." ], [ "sapling_acacia", "Acacia Sapling", "A sapling, grows into an acacia tree after planting." ], [ "sapling_dark_oak", "Dark Oak Sapling", "A sapling, grows into a dark oak tree after planting." ], [ "sign", "Sign", "Not available for now." ], [ "stone_button", "Stone Button", "Controls the activation state of the redstone circuit." ], [ "wooden_button", "Wooden Button", "Controls the activation state of the redstone circuit." ], [ "sunflower", "Sunflower", "A large plant." ], [ "watermelon", "Watermelon", "A whole watermelon, looks very full and sweet." ], [ "wooden_door_oak", "Wooden Oak Door", "The essential part of the house." ], [ "wooden_door_birch", "Wooden Birch Door", "The essential part of the house." ], [ "wooden_door_spruce", "Wooden Spruce Door", "The essential part of the house." ], [ "wooden_door_jungle", "Wooden Jungle Door", "The essential part of the house." ], [ "wooden_door_acacia", "Wooden Acacia Door", "The essential part of the house." ], [ "wooden_door_dark_oak", "Wooden Dark Oak Door", "The essential part of the house." ], [ "table_oak", "Wooden Oak Table", "A wooden table." ], [ "cabinet_oak", "Wooden Oak Cabinet", "A table cabinet, can store items." ], [ "apple", "Apple", "A ripe red apple." ], [ "baked_potato", "Baked Potato", "Roasted potatoes." ], [ "blaze_powder", "Blaze Powder", "The energy source of brewing." ], [ "blaze_rod", "Blaze Rod", "This is a hot rod." ], [ "bowl", "Bowl", "A big and round bowl." ], [ "cake_piece", "Cake Piece", "A piece of cake." ], [ "carrot", "Carrot", "A vitamin-rich carrots." ], [ "chorus_fruit", "Chorus Fruit", "A fruit of chorus trees." ], [ "cooked_chicken", "Cooked Chicken", "A roasted turkey, has a crispy chicken flavor." ], [ "cookie", "Cookie", "A sweet cookie." ], [ "diamond", "Diamond", "" ], [ "dried_kelp", "Dried Kelp", "A dry kelp." ], [ "egg", "Egg", "This is an egg." ], [ "emerald", "Emerald", "" ], [ "ender_eye", "Ender Eye", "You feel something is watching you." ], [ "ender_pearl", "Ender Pearl", "This is a pearl that releases unknown magical energy." ], [ "fermented_spider_eye", "Fermented Spider Eye", "A fermented spider eye." ], [ "ghast_tear", "Ghast Tear", "This is a tear crystal of ghast." ], [ "glass_bottle", "Glass Bottle", "A transparent glass bottle." ], [ "glistering_melon_slice", "Glistering Melon Slice", "Can be used for brewing." ], [ "glowstone_dust", "Glowstone Dust", "Glowing glowstone powder." ], [ "golden_apple", "Golden Apple", "There are special effects bonus after eating." ], [ "golden_carrot", "Golden Carrot", "There are special effects bonus after eating." ], [ "gunpowder", "Gunpowder", "A flammable sulfurized mixture." ], [ "heart_of_sea", "Heart Of Sea", "The essence of the ocean." ], [ "ink_sac", "Ink Sac", "This is a cuttlefish tentacle." ], [ "lapis_lazuli", "Lapis Lazuli", "" ], [ "magma_cream", "Magma Cream", "A magma jelly." ], [ "melon_seed", "Melon Seed", "Watermelon seeds, can be grown into watermelon." ], [ "melon_slice", "Melon Slice", "A slice of watermelon, a must for summer." ], [ "mushroom_stew", "Mushroom Stew", "A bowl of mushroom soup." ], [ "nether_brick", "Nether Brick", "A nether brick, can be stacked into nether brick blocks." ], [ "nether_star", "Nether Star", "A wither's drop." ], [ "nether_wart", "Nether Wart", "Special crops of hell." ], [ "phantom_membrane", "Phantom Membrane", "A transparent phantom wing." ], [ "popped_chorus_fruits", "Popped Chorus Fruits", "Rich juice!" ], [ "potato", "Potato", "A Raw potato." ], [ "prismarine_crystals", "Prismarine Crystals", "A piece of prismarine crystals." ], [ "prismarine_shard", "Prismarine Shard", "A prismarine shard." ], [ "quartz", "Quartz", "" ], [ "pufferfish", "Pufferfish", "A very sweet puffer fish." ], [ "pumpkin_pie", "Pumpkin Pie", "A big pumpkin pie." ], [ "pumpkin_seed", "Pumpkin Seed", "Pumpkin seeds, can grow into pumpkins." ], [ "raw_beef", "Raw Beef", "A piece of raw beef." ], [ "raw_chicken", "Raw Chicken", "Would you like to eat raw chicken if it is not cooked?" ], [ "scute", "Scute", "A scale of the turtle." ], [ "seed", "Seed", "Seeds of wheat, can grow into wheat." ], [ "shulker_shell", "Shulker Shell", "A hard shell of a shulker." ], [ "slimeball", "Slimeball", "Looks very tasty." ], [ "steak", "Steak", "Looks very tasty." ], [ "beetroot", "Beetroot", "This is a beetroot." ], [ "raw_cod", "Raw Cod", "A lively cod." ], [ "cooked_cod", "Cooked Cod", "A delicious cod." ], [ "raw_mutton", "Raw Mutton", "Raw lamb." ], [ "cooked_mutton", "Cooked Mutton", "Cooked lamb." ], [ "raw_porkchop", "Raw Porkchop", "This is a piece of raw pork." ], [ "cooked_porkchop", "Cooked Porkchop", "A delicious pork chop." ], [ "raw_rabbit", "Raw Rabbit", "Raw rabbit meat." ], [ "cooked_rabbit", "Cooked Rabbit", "Cooked rabbit meat." ], [ "raw_salmon", "Raw Salmon", "A lively salmon." ], [ "cooked_salmon", "Cooked Salmon", "A delicious salmon." ], [ "dye_white", "White Dye", "A dye that can be used for dyeing." ], [ "dye_orange", "Orange Dye", "A dye that can be used for dyeing." ], [ "dye_magenta", "Magenta Dye", "A dye that can be used for dyeing." ], [ "dye_light_blue", "Light Blue Dye", "A dye that can be used for dyeing." ], [ "dye_yellow", "Yellow Dye", "A dye that can be used for dyeing." ], [ "dye_lime", "Lime Dye", "A dye that can be used for dyeing." ], [ "dye_pink", "Pink Dye", "A dye that can be used for dyeing." ], [ "dye_gray", "Gray Dye", "A dye that can be used for dyeing." ], [ "dye_light_gray", "Light Gray Dye", "A dye that can be used for dyeing." ], [ "dye_cyan", "Cyan Dye", "A dye that can be used for dyeing." ], [ "dye_purple", "Purple Dye", "A dye that can be used for dyeing." ], [ "dye_blue", "Blue Dye", "A dye that can be used for dyeing." ], [ "dye_brown", "Brown Dye", "A dye that can be used for dyeing." ], [ "dye_green", "Green Dye", "A dye that can be used for dyeing." ], [ "dye_red", "Red Dye", "A dye that can be used for dyeing." ], [ "dye_black", "Black Dye", "A dye that can be used for dyeing." ], [ "fire_charge", "Fire Charge", "A burning flame bomb." ], [ "firework_rocket", "Firework Rocket", "This is a firework rocket." ], [ "iron_nugget", "Iron Nugget", "" ], [ "gold_nugget", "Gold Nugget", "" ], [ "kelp", "Kelp", "A long kelp." ], [ "lighter", "Lighter", "Let the flame burn more violently!" ], [ "map_paper", "Map Paper", "Record a map of each chunk." ], [ "nautilus_shell", "Nautilus Shell", "Why not ask the magical parrot conch?" ], [ "rabbit_foot", "Rabbit Foot", "Rabbit's sturdy foot." ], [ "rabbit_hide", "Rabbit Hide", "Rabbit furry fur." ], [ "redstone", "Redstone", "" ], [ "rotten_flesh", "Rotten Flesh", "A piece of meat that have been rotting for a long time." ], [ "spider_eye", "Spider Eye", "A spider eye." ], [ "totem_of_undying", "Totem Of Undying", "Use it to escape a death." ], [ "wool_white", "White Wool", "Soft and elastic wool." ], [ "wool_orange", "Orange Wool", "Soft and elastic wool." ], [ "wool_magenta", "Magenta Wool", "Soft and elastic wool." ], [ "wool_light_blue", "Light Blue Wool", "Soft and elastic wool." ], [ "wool_yellow", "Yellow Wool", "Soft and elastic wool." ], [ "wool_lime", "Lime Wool", "Soft and elastic wool." ], [ "wool_pink", "Pink Wool", "Soft and elastic wool." ], [ "wool_gray", "Gray Wool", "Soft and elastic wool." ], [ "wool_light_gray", "Light Gray Wool", "Soft and elastic wool." ], [ "wool_cyan", "Cyan Wool", "Soft and elastic wool." ], [ "wool_purple", "Purple Wool", "Soft and elastic wool." ], [ "wool_blue", "Blue Wool", "Soft and elastic wool." ], [ "wool_brown", "Brown Wool", "Soft and elastic wool." ], [ "wool_green", "Green Wool", "Soft and elastic wool." ], [ "wool_red", "Red Wool", "Soft and elastic wool." ], [ "wool_black", "Black Wool", "Soft and elastic wool." ], [ "wooden_axe", "Wooden Axe", "A wooden Axe, better than the grass one." ], [ "wooden_pickaxe", "Wooden Pickaxe", "A wooden pickaxe, better than the grass one." ], [ "wooden_sword", "Wooden Sword", "A sword made of wood." ], [ "platform_oak", "Oak Platform", "A wooden platform." ], [ "platform_birch", "Birch Platform", "A wooden platform." ], [ "platform_spruce", "Spruce Platform", "A wooden platform." ], [ "platform_jungle", "Jungle Platform", "A wooden platform." ], [ "platform_acacia", "Acacia Platform", "A wooden platform." ], [ "platform_dark_oak", "Dark Oak Platform", "A wooden platform." ], [ "iron_axe", "Iron Axe", "An axe made of iron." ], [ "iron_pickaxe", "Iron Pickaxe", "A pickaxe made of iron." ], [ "iron_sword", "Iron Sword", "A sword made of iron." ], [ "golden_axe", "Golden Axe", "An axe made of gold." ], [ "golden_pickaxe", "Golden Pickaxe", "A pickaxe made of gold." ], [ "golden_sword", "Golden Sword", "A sword made of gold." ], [ "diamond_axe", "Diamond Axe", "An axe made of diamond." ], [ "diamond_pickaxe", "Diamond Pickaxe", "A pickaxe made of diamond." ], [ "diamond_sword", "Diamond Sword", "A sword made of diamond." ], [ "leather_helmet", "Leather Helmet", "A hat made of leather." ], [ "leather_chestplate", "Leather Chestplate", "A cloth made of leather." ], [ "leather_leggings", "Leather Leggings", "A pant made of leather." ], [ "iron_helmet", "Iron Helmet", "A helmet made of iron." ], [ "iron_chestplate", "Iron Chestplate", "A chestplate made of iron." ], [ "iron_leggings", "Iron Leggings", "leggings made of iron." ], [ "golden_helmet", "Golden Helmet", "A helmet made of gold." ], [ "golden_chestplate", "Golden Chestplate", "A chestplate made of gold." ], [ "golden_leggings", "Golden Leggings", "leggings made of gold." ], [ "diamond_helmet", "Diamond Helmet", "A helmet made of diamond." ], [ "diamond_chestplate", "Diamond Chestplate", "A chestplate made of diamond." ], [ "diamond_leggings", "Diamond Leggings", "leggings made of diamond." ], [ "potion_water", "Water Potion", "A bottle of water, can be brewed into potions with various effects." ], [ "potion_awkward", "Awkward Potion", "A bottle of crude potion, can be obtained by refining different materials." ], [ "potion_strength", "Strength Potion", "A potion full of power." ], [ "potion_strength_long", "Super Strength Potion", "A potion full of power." ], [ "potion_swiftness", "Swiftness Potion", "Move faster after drinking." ], [ "potion_swiftness_long", "Super Swiftness Potion", "Move faster after drinking." ], [ "potion_slowness", "Slowness Potion", "A slow-paced potion." ], [ "potion_slowness_long", "Super Slowness Potion", "A slow-paced potion." ], [ "potion_leaping", "Leaping Potion", "Improve jumping power." ], [ "potion_leaping_long", "Super Leaping Potion", "Improve jumping power." ], [ "potion_healing", "Healing Potion", "Instantly restores health." ], [ "potion_healing_super", "Super Healing Potion", "Instantly restores health." ], [ "potion_harming", "Harming Potion", "Contains various harmful substances." ], [ "potion_harming_super", "SuperHarming Potion", "Contains various harmful substances." ], [ "potion_poison", "Poison Potion", "A poisonous potion." ], [ "potion_poison_long", "Super Poison Potion", "A poisonous potion." ], [ "potion_regeneration", "Regeneration Potion", "Continuously improves health." ], [ "potion_regeneration_long", "Super Regeneration Potion", "Continuously improves health." ], [ "potion_fire_resistance", "Fire Resistance Potion", "Immune to flame and lava." ], [ "potion_fire_resistance_long", "Super Fire Resistance Potion", "Immune to flame and lava." ], [ "potion_water_breathing", "Water-Breathing Potion", "You can breathe in water after drinking." ], [ "potion_water_breathing_long", "Super Water-Breathing Potion", "You can breathe in water after drinking." ], [ "potion_night_vision", "Night Vision Potion", "See in dark." ], [ "potion_night_vision_long", "Super Night Vision Potion", "See in dark." ], [ "potion_invisibility", "Invisibility Potion", "A unscientific potion." ], [ "potion_invisibility_long", "Super Invisibility Potion", "A unscientific potion." ], [ "potion_slow_falling", "Slow Falling Potion", "Fall very slowly." ], [ "potion_slow_falling_long", "Super Slow Falling Potion", "Fall very slowly." ], [ "potion_weakness", "Weakness Potion", "Collapse after drinking." ], [ "potion_weakness_long", "Super Weakness Potion", "Collapse after drinking." ], [ "enchantment_table", "Enchantment Table", "Enchant every tools!" ], [ "enchanted_book", "Enchanted Book", "A book full of spells." ], [ "shears", "Shears", "Used for shearing or carving." ], [ "shotgun", "Shotgun", "A powerful shotgun." ], [ "stone_hoe", "Stone Hoe", "Used to reclaim land." ], [ "green_wire", "Green Wire", "Place to connect the redstone circuit." ], [ "blue_wire", "Blue Wire", "Place to connect the redstone circuit." ], [ "yellow_wire", "Yellow Wire", "Place to connect the redstone circuit." ], [ "wire_cutter", "Wire Cutter", "Place to connect the redstone circuit." ], [ "lever", "Lever", "Controls the activation state of the redstone circuit." ], [ "redstone_torch", "Redstone Torch", "Right click to activate or deactivate." ], [ "bomb", "Bomb", "A bomb that can destroy the tiles." ], [ "grenade", "Grenade", "Do damage to enemies without destroying the tiles." ], [ "handgun", "Handgun", "A handgun." ], [ "rifle", "Rifle", "A rifle." ], [ "fire_gun", "Fire Gun", "A fire gun." ], [ "super_iron_sword", "Wrought Iron Sword", "A sword made of iron." ], [ "super_golden_sword", "Wide Golden Sword", "A sword made of gold." ], [ "super_diamond_sword", "Super Diamond Sword", "A sharp diamond sword." ], [ "copper_sword", "Copper Sword", "A sword made of copper." ], [ "super_copper_sword", "Wide Copper Sword", "A sword made of copper." ], [ "tin_sword", "Tin Sword", "A sword made of tin." ], [ "super_tin_sword", "Wide Tin Sword", "A sword made of tin." ], [ "lead_sword", "Lead Sword", "A sword made of lead." ], [ "super_lead_sword", "Heavy Lead Sword", "A sword made of lead." ], [ "silver_sword", "Silver Sword", "A sword made of silver." ], [ "super_silver_sword", "Long Silver Sword", "A sword made of silver." ], [ "bronze_sword", "Bronze Sword", "A sword made of bronze." ], [ "super_bronze_sword", "Wide Bronze Sword", "A sword made of bronze." ], [ "steel_sword", "Steel Sword", "A sword made of steel." ], [ "super_steel_sword", "Long Steel Sword", "A sword made of steel." ], [ "ghost_sword", "Sun Light Sword", "A sword that injects sunlight energy." ], [ "glow_ball", "Glow Ball", "Provide lighting." ], [ "glow_bomb", "Glow Bomb", "Makes damage to enemies, does not destroy the tile, provides short-term bright lighting." ], [ "lighting_bow", "Lighting Bow", "Shoots light arrows and provides lighting effects." ], [ "fire_bullet", "Soil Bullet", "A common bullet." ], [ "iron_bullet", "Iron Bullet", "An iron bullet." ], [ "silver_bullet", "Silver Bullet", "A silver bullet." ], [ "lighting_arrow", "Lighting Arrow", "A glowing arrow." ], [ "cross_bow", "Cross Bow", "Shoot arrows quickly." ], [ "shot_bow", "Shot Bow", "Shoot multiple arrows quickly." ], [ "super_cross_bow", "Super Cross Bow", "Shoot arrows very quick." ], [ "boomerang", "Boomerang", "Throw out and fly back!" ], [ "wooden_boomerang", "Wooden Boomerang", "Throw out and fly back!" ], [ "star_arrow", "Star Arrow", "A dropped arrow." ], [ "fire_boomerang", "Fire Boomerang", "A burning boomerang!" ], [ "blood_arrow", "Bloody Arrow", "Keep sucking blood." ], [ "blood_bow", "Bloody Bow", "Shoots bloody arrows." ], [ "blue_stone_bow", "Blue Stone Bow", "Has a faster attack speed and attack frequency." ], [ "ice_arrow", "Ice Arrow", "A cold arrow." ], [ "ice_bow", "Ice Bow", "Shoots ice arrows." ], [ "chast_bow", "Sword Bow", "Shoots swrod arrows." ], [ "sword_arrow", "Sword Arrow", "A sword shape arrow, auto aiminig at the target." ], [ "air_sword", "Air Sword", "Cut through the air." ], [ "super_air_sword", "Super Air Sword", "Cut through the air." ], [ "amethyst_staff", "Amethyst Staff", "A magical staff." ], [ "lighting_staff", "Lighting Staff", "A radiant staff." ], [ "water_staff", "Water Staff", "A water magic staff." ], [ "ice_staff", "Ice Staff", "A cold staff." ], [ "shadow_staff", "Shadow Staff", "A staff controlled by dark magic." ], [ "red_torch", "Red Torch", "A torch glowing red." ], [ "yellow_torch", "Yellow Torch", "A torch glowing yellow." ], [ "blue_torch", "Blue Torch", "A torch glowing blue." ], [ "green_torch", "Green Torch", "A torch glowing green." ], [ "white_torch", "White Torch", "A torch glowing white." ], [ "flesh_stone", "Flesh Stone", "A block made of unnamed objects." ], [ "flesh_dirt", "Flesh Dirt", "A block made of unknown meat." ], [ "flesh_gut", "Flesh Gut", "An Inexplicable block." ], [ "mycelium", "Mycelium", "A Block made of fungi." ], [ "tainted_stone", "Tainted Stone", "A corroded stone." ], [ "tainted_dirt", "Tainted Dirt", "A corroded dirt." ], [ "volcano_stone", "Volcano Stone", "A stone has been contact with lava for a long time." ], [ "volcano_dirt", "Volcano Dirt", "A loose lava soil." ], [ "ore_tin", "Tin Ore", "A mineral ore, require further processing." ], [ "ore_copper", "Copper Ore", "A mineral ore, require further processing." ], [ "ore_lead", "Lead Ore", "A mineral ore, require further processing." ], [ "ore_silver", "Silver Ore", "A mineral ore, require further processing." ], [ "bronze_helmet", "Bronze Helmet", "A helmet made of bronze." ], [ "bronze_chestplate", "Bronze Chestplate", "A chestplate made of bronze." ], [ "bronze_leggings", "Bronze Leggings", "Leggings made of bronze." ], [ "copper_helmet", "Copper Helmet", "A helmet made of copper." ], [ "copper_chestplate", "Copper Chestplate", "A chestplate made of copper." ], [ "copper_leggings", "Copper Leggings", "Leggings made of copper." ], [ "lead_helmet", "Lead Helmet", "A helmet made of lead." ], [ "lead_chestplate", "Lead Chestplate", "A chestplate made of lead." ], [ "lead_leggings", "Lead Leggings", "Leggings made of lead." ], [ "nether_helmet", "Netherite Helmet", "An equipment reinforced by netherite." ], [ "nether_chestplate", "Netherite Chestplate", "An equipment reinforced by netherite." ], [ "nether_leggings", "Netherite Leggings", "An equipment reinforced by netherite." ], [ "silver_helmet", "Silver Helmet", "A helmet made of silver." ], [ "silver_chestplate", "Silver Chestplate", "A chestplate made of silver." ], [ "silver_leggings", "Silver Leggings", "Leggings made of silver." ], [ "steel_helmet", "Steel Helmet", "A helmet made of steel." ], [ "steel_chestplate", "Steel Chestplate", "A chestplate made of steel." ], [ "steel_leggings", "Steel Leggings", "Leggings made of steel." ], [ "tin_helmet", "Tin Helmet", "A helmet made of tin." ], [ "tin_chestplate", "Tin Chestplate", "A chestplate made of tin." ], [ "tin_leggings", "Tin Leggings", "Leggings made of tin." ], [ "palm_plank", "Palm Plank", "A wooden building material." ], [ "volcano_plank", "Volcano Plank", "A red wooden building material." ], [ "tainted_plank", "Tainted Plank", "A tainted wooden building material." ], [ "wood_palm", "Palm Wood", "A fresh log just cut down." ], [ "wood_volcano", "Volcano Wood", "A wood that lives in a lava environment." ], [ "wood_tainted", "Tainted Wood", "A fresh log just cut down." ], [ "wood_stripped_palm", "Palm Stripped Wood", "A log stripped of bark." ], [ "wood_stripped_volcano", "Volcano Stripped Wood", "A log stripped of bark." ], [ "wood_stripped_tainted", "Tainted Stripped Wood", "A log stripped of bark." ], [ "sapling_tainted", "Tainted Sapling", "A sapling, grows into a tainted tree after planting." ], [ "sapling_palm", "Palm Sapling", "A sapling, grows into a palm tree after planting." ], [ "sapling_cactus", "Cactus", "A small cactus, will grow into a large cactus after planting." ], [ "sapling_volcano", "Volcano Sapling", "A sapling, grows into a volcano tree after planting." ], [ "sapling_bare_oak", "Bare Oak Sapling", "A sapling, grows into a bark oak tree after planting." ], [ "platform_palm", "Palm Platform", "A wooden platform." ], [ "platform_volcano", "Volcano Platform", "A wooden platform." ], [ "platform_tainted", "Tainted Platform", "A wooden platform." ], [ "wooden_door_palm", "Wooden Palm Door", "The essential part of the house." ], [ "wooden_door_volcano", "Wooden Volcano Door", "The essential part of the house." ], [ "wooden_door_tainted", "Wooden Tainted Door", "The essential part of the house." ], [ "fence_palm", "Palm Fence", "A wooden fence." ], [ "fence_volcano", "Volcano Fence", "A wooden fence." ], [ "fence_tainted", "Tainted Fence", "A wooden fence." ], [ "ore_ancient_debris", "Ancient Debris", "A mineral ore, require further processing." ], [ "block_netherite", "Netherite Block", "A block made of netherite." ], [ "netherite_ingot", "Netherite Ingot", "" ], [ "netherite_scrap", "Netherite Scrap", "Used to craft netherite ingot." ], [ "dried_kelp_block", "Dried Kelp Block", "A bundle of dried kelp." ], [ "blue_ice", "Blue Ice", "Smoother than packed ice, the unique structure inside makes it emit a faint light." ], [ "ore_nether_quartz", "Nether Quartz Ore", "A mineral ore, require further processing." ], [ "block_quartz", "Quartz Block", "A Quartz compressed block, building material." ], [ "platform_end_stone", "End Stone Platform", "A platform made of end stone." ], [ "platform_nether_brick", "Nether Brick Platform", "A platform made of nether bricks." ], [ "platform_prismarine", "Prismarine Platform", "A platform made of prismarine." ], [ "platform_prismarine_dark", "Prismarine Dark Platform", "A platform made of dark prismarine." ], [ "platform_purpur", "Purpur Platform", "A platform made of purpur." ], [ "platform_quartz", "Quartz Platform", "A platform made of quartz." ], [ "platform_red_sand_stone", "Red Sand Stone Platform ", "A platform made of red sandstone." ], [ "platform_sandstone", "Sandstone Platform", "A platform made of sand stone." ], [ "platform_stone_brick", "Stone Brick Platform", "A platform made of stone bricks." ], [ "stained_glass_white", "White Stained Glass", "This is a stained glass." ], [ "stained_glass_orange", "Orange Stained Glass", "This is a stained glass." ], [ "stained_glass_magenta", "Magenta Stained Glass", "This is a stained glass." ], [ "stained_glass_light_blue", "Light Blue Stained Glass", "This is a stained glass." ], [ "stained_glass_yellow", "Yellow Stained Glass", "This is a stained glass." ], [ "stained_glass_lime", "Lime Stained Glass", "This is a stained glass." ], [ "stained_glass_pink", "Pink Stained Glass", "This is a stained glass." ], [ "stained_glass_gray", "Gray Stained Glass", "This is a stained glass." ], [ "stained_glass_light_gray", "Light Gray Stained Glass", "This is a stained glass." ], [ "stained_glass_cyan", "Cyan Stained Glass", "This is a stained glass." ], [ "stained_glass_purple", "Purple Stained Glass", "This is a stained glass." ], [ "stained_glass_blue", "Blue Stained Glass", "This is a stained glass." ], [ "stained_glass_brown", "Brown Stained Glass", "This is a stained glass." ], [ "stained_glass_green", "Green Stained Glass", "This is a stained glass." ], [ "stained_glass_red", "Red Stained Glass", "This is a stained glass." ], [ "stained_glass_black", "Black Stained Glass", "This is a stained glass." ], [ "wooden_bed_white", "White Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_orange", "Orange Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_magenta", "Magenta Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_light_blue", "Light Blue Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_yellow", "Yellow Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_lime", "Lime Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_pink", "Pink Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_gray", "Gray Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_light_gray", "Light Gray Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_cyan", "Cyan Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_purple", "Purple Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_blue", "Blue Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_brown", "Brown Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_green", "Green Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "wooden_bed_black", "Black Wooden Bed", "This is a bed, used to reset the respawn point." ], [ "jack_o_lantern", "Jack-o-Lantern", "A carved jack-o-lantern with halloween motifs." ], [ "pumpkin_helmet", "Pumpkin Helmet", "A pumpkin balaclava." ], [ "shulker_box", "Shulker Box", "Store items in this item." ], [ "end_rod", "End Rod", "An end lighting tool." ], [ "lantern", "Lantern", "This is a lantern that can be hung." ], [ "barrel", "Barrel", "Store items." ], [ "campfire", "Campfire", "Provide lighting." ], [ "painting_4x2", "Painting 4X2", "Welcome to contribute. 0w0" ], [ "painting_2x4", "Painting 2X4", "Welcome to contribute. 0w0" ], [ "painting_4x4", "Painting 4X4", "Welcome to contribute. 0w0" ], [ "painting_8x4", "Painting 8X4", "Welcome to contribute. 0w0" ], [ "painting_8x6", "Painting 8X6", "Welcome to contribute. 0w0" ], [ "painting_8x8", "Painting 8X8", "Welcome to contribute. 0w0" ], [ "flower_pot", "Flower Pot", "A flower pot where small flowers can be placed." ], [ "flower_pot_large", "Large Flower Pot", "A flower pot where large flowers can be placed." ], [ "trapped_chest", "Trapped Chest", "Store items and send a redstone signal when opened." ], [ "cocoa_bean", "Cocoa Bean", "A food material growing on jungle wood." ], [ "table_spruce", "Spruce Table", "A wooden table." ], [ "table_birch", "Birch Table", "A wooden table." ], [ "table_jungle", "Jungle Table", "A wooden table." ], [ "table_acacia", "Acacia Table", "A wooden table." ], [ "table_dark_oak", "Dark Oak Table", "A wooden table." ], [ "table_palm", "Palm Table", "A wooden table." ], [ "table_volcano", "Wooden Volcano Table", "A wooden table." ], [ "table_tainted", "Wooden Tainted Table", "A wooden table." ], [ "cabinet_spruce", "Spruce Cabinet", "A table cabinet, can store items." ], [ "cabinet_birch", "Birch Cabinet", "A table cabinet, can store items." ], [ "cabinet_jungle", "Jungle Cabinet", "A table cabinet, can store items." ], [ "cabinet_acacia", "Acacia Cabinet", "A table cabinet, can store items." ], [ "cabinet_dark_oak", "Dark Oak Cabinet", "A table cabinet, can store items." ], [ "cabinet_palm", "Palm Cabinet", "A table cabinet, can store items." ], [ "cabinet_volcano", "Wooden Volcano Cabinet", "A table cabinet, can store items." ], [ "cabinet_tainted", "Wooden Tainted Cabinet", "A table cabinet, can store items." ], [ "chair_spruce", "Spruce Chair", "A wooden chair." ], [ "chair_birch", "Birch Chair", "A wooden chair." ], [ "chair_jungle", "Jungle Chair", "A wooden chair." ], [ "chair_acacia", "Acacia Chair", "A wooden chair." ], [ "chair_dark_oak", "Dark Oak Chair", "A wooden chair." ], [ "chair_palm", "Palm Chair", "A wooden chair." ], [ "chair_volcano", "Wooden Volcano Chair", "A wooden chair." ], [ "chair_tainted", "Wooden Tainted Chair", "A wooden chair." ], [ "bookcase_spruce", "Spruce Bookcase", "A shelf with many books, can store items." ], [ "bookcase_birch", "Birch Bookcase", "A shelf with many books, can store items." ], [ "bookcase_jungle", "Jungle Bookcase", "A shelf with many books, can store items." ], [ "bookcase_acacia", "Acacia Bookcase", "A shelf with many books, can store items." ], [ "bookcase_dark_oak", "Dark Oak Bookcase", "A shelf with many books, can store items." ], [ "bookcase_palm", "Palm Bookcase", "A shelf with many books, can store items." ], [ "bookcase_volcano", "Wooden Volcano Bookcase", "A shelf with many books, can store items." ], [ "bookcase_tainted", "Wooden Tainted Bookcase", "A shelf with many books, can store items." ], [ "bench_oak", "Oak Bench", "A bench." ], [ "bench_spruce", "Spruce Bench", "A bench." ], [ "bench_birch", "Birch Bench", "A bench." ], [ "bench_jungle", "Jungle Bench", "A bench." ], [ "bench_acacia", "Acacia Bench", "A bench." ], [ "bench_dark_oak", "Dark Oak Bench", "A bench." ], [ "bench_palm", "Palm Bench", "A bench." ], [ "bench_volcano", "Volcano Bench", "A bench." ], [ "bench_tainted", "Tainted Bench", "A bench." ], [ "prismarine_mud", "Prismarine Mud", "A block covering the sea floor." ], [ "snow_queen_loot", "Loot of Snow Queen", "To celebrate the defeat of the Snow Queen." ], [ "nether_destroyer_loot", "Loot of Nether Destroyer", "To celebrate the defeat of the Nether Destroyer." ], [ "table_nether", "Nether Table", "A table in nether." ], [ "cabinet_nether", "Nether Cabinet", "A table cabinet, can store items." ], [ "bench_nether", "Nether Bench", "A bench." ], [ "chair_nether", "Nether Chair", "A chair in nether." ], [ "bookcase_nether", "Nether Bookcase", "A shelf with many books, can store items." ], [ "door_nether", "Nether Door", "The essential part of the house." ], [ "nether_chest", "Nether Chest", "Store items." ], [ "nether_lamp", "Nether Lamp", "Provides bright lighting." ], [ "mana_piece", "Magic Fragment", "Increase the limit of magic by 10 when eating." ], [ "wooden_hoe", "Wooden Hoe", "Used to reclaim land." ], [ "steel_axe", "Steel Axe", "An axe made of steel." ], [ "bronze_axe", "Bronze Axe", "An axe made of bronze." ], [ "silver_axe", "Silver Axe", "An axe made of silver." ], [ "lead_axe", "Lead Axe", "An axe made of lead." ], [ "tin_axe", "Tin Axe", "An axe made of tin." ], [ "copper_axe", "Copper Axe", "An axe made of copper." ], [ "steel_pickaxe", "Steel Pickaxe", "A pickaxe made of steel." ], [ "bronze_pickaxe", "Bronze Pickaxe", "A pickaxe made of bronze." ], [ "silver_pickaxe", "Silver Pickaxe", "A pickaxe made of silver." ], [ "lead_pickaxe", "Lead Pickaxe", "A pickaxe made of lead." ], [ "tin_pickaxe", "Tin Pickaxe", "A pickaxe made of tin." ], [ "copper_pickaxe", "Copper Pickaxe", "A pickaxe made of copper." ], [ "potion_glowing", "Glowing Potion", "You will glow all over after drinking." ], [ "potion_glowing_long", "Super Glowing Potion", "You will glow all over after drinking." ], [ "glowing_mushroom", "Glowing Mushroom", "A mushroom with slight light." ], [ "poison_mushroom", "Poison Mushroom", "Do not eat!" ], [ "large_brown_mushroom", "Large Brown Mushroom", "A bigger brown mushroom." ], [ "large_red_mushroom", "Large Red Mushroom", "A bigger red mushroom." ], [ "large_poison_mushroom", "Large Poison Mushroom", "A bigger poison mushroom." ], [ "gray_feather", "Gray Feather", "This is a gray feather." ], [ "nether_axe", "Netherite Axe", "An axe reinforced by netherite." ], [ "nether_pickaxe", "Netherite Pickaxe", "A pickaxe reinforced by netherite." ], [ "nether_sword", "Netherite Sword", "A sword reinforced by netherite." ], [ "super_nether_sword", "Super Netherite Sword", "A super sword reinforced by netherite." ], [ "rocket", "Rocket", "You need a rocket launcher to launch this." ], [ "nether_altar", "Nether Altar", "There seems to be a terrible enemy sealed inside." ], [ "snow_glass_ball", "Snow Queue Glass Ball", "The snow queen is sleeping in this glass ball." ], [ "guardian", "Guardian", "To commemorate defeating a guardian." ] ], "chemicalFormulas": [ [ "coal", "C" ], [ "charcoal", "C" ], [ "diamond", "C" ], [ "emerald", "Be3Al2(SiO3)6" ], [ "lapis_lazuli", "(Al6Si6Ca8Na8)12(Al3Si3Na4Cl)2FeS2CaCO3" ], [ "quartz", "SiO2" ], [ "redstone", "Si(FeS2)5CrAl2O3Hg3" ], [ "iron_nugget", "Fe" ], [ "gold_nugget", "Au" ], [ "iron_ingot", "Fe" ], [ "gold_ingot", "Au" ], [ "redstone_ingot", "Si(FeS2)5CrAl2O3Hg3" ], [ "copper_ingot", "Cu" ], [ "tin_ingot", "Sn" ], [ "bronze_ingot", "SnCu3" ], [ "lead_ingot", "Pb" ], [ "silver_ingot", "Ag" ], [ "steel_ingot", "Fe50C" ], [ "lithium_ingot", "Li" ], [ "beryllium_ingot", "Be" ], [ "sodium_ingot", "Na" ], [ "magnesium_ingot", "Mg" ], [ "aluminum_ingot", "Al" ], [ "titanium_ingot", "Ti" ], [ "vanadium_ingot", "V" ], [ "chromium_ingot", "Cr" ], [ "manganese_ingot", "Mn" ], [ "cobalt_ingot", "Co" ], [ "nickel_ingot", "Ni" ], [ "zinc_ingot", "Zn" ], [ "gallium_ingot", "Ga" ], [ "yttrium_ingot", "Y" ], [ "niobium_ingot", "Nb" ], [ "molybdenum_ingot", "Mo" ], [ "palladium_ingot", "Pd" ], [ "indium_ingot", "In" ], [ "antimony_ingot", "Sb" ], [ "tantalum_ingot", "Ta" ], [ "wolfram_ingot", "W" ], [ "rhenium_ingot", "Re" ], [ "osmium_ingot", "Os" ], [ "iridium_ingot", "Ir" ], [ "platinum_ingot", "Pt" ], [ "bismuth_ingot", "Bi" ], [ "vibranium_ingot", "Vb" ] ] } ================================================ FILE: liquids/lava.json ================================================ { "lava": { "textureData": "lava.png", "borderTextureData": "lava_border.png", "texWidth": 1024, "texHeight": 1024, "color": [ 244, 255, 255, 255 ], "paticularColor": [ 255, 200, 100, 0 ], "isLighting": true, "lightColor": [ 32, 20, 10, 0 ], "offsetSpeedX": 0.5, "offsetSpeedY": 0.5, "delay": 8, "stickyRate": 0.4, "damage": 8, "buffs": [ { "id": "fire", "time": 300 } ], "noBuffs": [] } } ================================================ FILE: liquids/water.json ================================================ { "water": { "textureData": "water.png", "borderTextureData": "water_border.png", "texWidth": 256, "texHeight": 16, "color": [ 96, 122, 122, 255 ], "paticularColor": [ 255, 32, 160, 200 ], "offsetSpeedX": 0, "offsetSpeedY": 0, "delay": 4, "stickyRate": 0.5, "damage": 0, "buffs": [], "noBuffs": [ "fire" ] } } ================================================ FILE: mod_textures/ModTextures.lua ================================================ ---@class TC.ModTextures local ModTextures = class("ModTextures") local s_instance ---@return TC.ModTextures function ModTextures.getInstance() if s_instance == nil then s_instance = ModTextures.new() end return s_instance end function ModTextures:__init() self.textureNameDict = {} self:loadAll() end function ModTextures:loadAll() local allPngNames = AssetManager.getAllFiles(Path.join(Mod.current.assetRootPath, "mod_textures"), ".png", true, false, false) for _, pngName in ipairs(allPngNames) do local realPath = Path.join(Mod.current.assetRootPath, "mod_textures", pngName .. ".png") self.textureNameDict[pngName] = TextureManager.load(realPath) end end function ModTextures:getTexture(pngName) return self.textureNameDict[pngName] end return ModTextures ================================================ FILE: mod_textures/blade.json ================================================ { "blade": { "textureData": "blade.png", "width": 64, "height": 64, "frameXs": 1, "bringToFront": true } } ================================================ FILE: mod_textures/candle_fire.json ================================================ { "candle_fire": { "textureData": "candle_fire.png", "width": 16, "height": 16, "frameXs": 4, "frameSpeed": 8, "loopPlay": true } } ================================================ FILE: mod_textures/candle_fire_blue.json ================================================ { "candle_fire_blue": { "textureData": "candle_fire_blue.png", "width": 16, "height": 16, "frameXs": 4, "frameSpeed": 8, "loopPlay": true } } ================================================ FILE: mod_textures/crack.json ================================================ { "crack": { "textureData": "crack.png", "width": 16, "height": 16, "frameXs": 5, "userDisabled": true } } ================================================ FILE: mod_textures/electric_direction.json ================================================ { "electric_direction": { "textureData": "electric_direction.png", "width": 16, "height": 16, "frameXs": 4 } } ================================================ FILE: mod_textures/fire.json ================================================ { "fire": { "textureData": "fire.png", "width": 24, "height": 24, "frameXs": 4, "frameSpeed": 8, "loopPlay": true } } ================================================ FILE: mod_textures/flesh_grass.json ================================================ { "flesh_grass": { "textureData": "flesh_grass.png", "width": 32, "height": 32, "frameXs": 5, "frameYs": 2, "userDisabled": true } } ================================================ FILE: mod_textures/fly_book.json ================================================ { "fly_book": { "textureData": "fly_book.png", "width": 32, "height": 32, "userDisabled": true } } ================================================ FILE: mod_textures/grass.json ================================================ { "grass": { "textureData": "grass.png", "width": 32, "height": 32, "frameXs": 5, "frameYs": 2, "userDisabled": true } } ================================================ FILE: mod_textures/mycelium_grass.json ================================================ { "mycelium_grass": { "textureData": "mycelium_grass.png", "width": 32, "height": 32, "frameXs": 5, "frameYs": 2, "userDisabled": true } } ================================================ FILE: mod_textures/tainted_grass.json ================================================ { "tainted_grass": { "textureData": "tainted_grass.png", "width": 32, "height": 32, "frameXs": 5, "frameYs": 2, "userDisabled": true } } ================================================ FILE: mod_textures/torch_fire.json ================================================ { "torch_fire": { "textureData": "torch_fire.png", "width": 16, "height": 16, "frameXs": 4, "frameSpeed": 8, "loopPlay": true } } ================================================ FILE: mod_textures/torch_fire_blue.json ================================================ { "torch_fire_blue": { "textureData": "torch_fire_blue.png", "width": 16, "height": 16, "frameXs": 4, "frameSpeed": 8, "loopPlay": true } } ================================================ FILE: mod_textures/torch_fire_green.json ================================================ { "torch_fire_green": { "textureData": "torch_fire_green.png", "width": 16, "height": 16, "frameXs": 4, "frameSpeed": 8, "loopPlay": true } } ================================================ FILE: mod_textures/torch_fire_red.json ================================================ { "torch_fire_red": { "textureData": "torch_fire_red.png", "width": 16, "height": 16, "frameXs": 4, "frameSpeed": 8, "loopPlay": true } } ================================================ FILE: mod_textures/torch_fire_white.json ================================================ { "torch_fire_white": { "textureData": "torch_fire_white.png", "width": 16, "height": 16, "frameXs": 4, "frameSpeed": 8, "loopPlay": true } } ================================================ FILE: mod_textures/torch_fire_yellow.json ================================================ { "torch_fire_yellow": { "textureData": "torch_fire_yellow.png", "width": 16, "height": 16, "frameXs": 4, "frameSpeed": 8, "loopPlay": true } } ================================================ FILE: mod_textures/torch_redstone.json ================================================ { "torch_redstone": { "textureData": "torch_redstone.png", "width": 16, "height": 16, "frameXs": 4, "frameSpeed": 8, "loopPlay": true, "tagUsage": "TAG_ADD_FRAME_INDEX_Y" } } ================================================ FILE: network/ClientBoundResponse.lua ================================================ ---@class Portal.ClientBoundResponse local ClientBoundResponse = class("ClientBoundResponse") local s_instance ---@return Portal.ClientBoundResponse function ClientBoundResponse.getInstance() if s_instance == nil then s_instance = ClientBoundResponse.new() end return s_instance end function ClientBoundResponse:__init() self.modResponseCallbacks = {} end ---addResponseCallback ---@param mod Mod ---@param rpcID int ---@param func function ---@param caller any function ClientBoundResponse:addResponseCallback(mod, rpcID, func, caller) local found = false if self.modResponseCallbacks[mod.modId] == nil then self.modResponseCallbacks[mod.modId] = {} end if self.modResponseCallbacks[mod.modId][rpcID] == nil then self.modResponseCallbacks[mod.modId][rpcID] = {} end for _, cb in ipairs(self.modResponseCallbacks[mod.modId][rpcID]) do if cb[1] == func and cb[2] == caller then found = true break end end if found then return end table.insert(self.modResponseCallbacks[mod.modId][rpcID], { func, caller }) end function ClientBoundResponse:removeResponse(caller) for _, responseCallbacks in pairs(self.modResponseCallbacks) do for _, cbs in pairs(responseCallbacks) do for i = #cbs, 1, -1 do if cbs[i][2] == caller then table.remove(cbs, i) end end end end end function ClientBoundResponse:doResponse(mod, rpcID, ...) local responseCallbacks = self.modResponseCallbacks[mod.modId] if responseCallbacks == nil then return end local cbs = responseCallbacks[rpcID] if cbs == nil then return end for _, cb in ipairs(cbs) do cb[1](cb[2], ...) end end return ClientBoundResponse ================================================ FILE: network/ModNetworkProxyHandler.lua ================================================ ---@class TC.ModNetworkProxyHandler local ModNetworkProxyHandler = class("ModNetworkProxyHandler") ---__init ---@param mod Mod function ModNetworkProxyHandler:__init(mod) self.mod = mod self.isServer = NetMode.current == NetMode.Server if self.isServer then self.mod:RegisterServerBoundReaderCallback({ ModNetworkProxyHandler.HandleProxyServerBound, self }) else self.mod:RegisterClientBoundReaderCallback({ ModNetworkProxyHandler.HandleProxyClientBound, self }) end self.rpcHandlerFuncSB = {} self.rpcHandlerFuncCB = {} end function ModNetworkProxyHandler:RegisterRPCHandlerServerBoundMappings(mappings) for k, v in ipairs(mappings) do self:RegisterRPCHandlerServerBound(k, v) end end function ModNetworkProxyHandler:RegisterRPCHandlerClientBoundMappings(mappings) for k, v in ipairs(mappings) do self:RegisterRPCHandlerClientBound(k, v) end end function ModNetworkProxyHandler:RegisterRPCHandlerServerBound(rpcID, rpcFunc) self.rpcHandlerFuncSB[rpcID] = rpcFunc end function ModNetworkProxyHandler:RegisterRPCHandlerClientBound(rpcID, rpcFunc) self.rpcHandlerFuncCB[rpcID] = rpcFunc end ---RPCWriteVar ---@param buffer ByteStream local function RPCReadVar(buffer) local flag = buffer:readIntVarLen() local v if flag == 1 then local isDouble = buffer:readBoolean() if isDouble then v = buffer:readDouble() else v = buffer:readIntVarLen() end elseif flag == 2 then v = buffer:readBoolean() elseif flag == 3 then v = buffer:readString() elseif flag == 4 then v = {} local tableCount = buffer:readIntVarLen() for i = 1, tableCount do local tk, tv local isKeyNum = buffer:readBoolean() if isKeyNum then tk = buffer:readIntVarLen() else tk = buffer:readString() end tv = RPCReadVar(buffer) v[tk] = tv end elseif flag == 5 then v = nil else assert(false, "RPC failed") end return v end ---RPCRead ---@param buffer ByteStream function ModNetworkProxyHandler:_RPCRead(buffer, player, sb) local values = {} local rpcID = buffer:readIntVarLen() local argCount = buffer:readIntVarLen() while argCount > 0 do local v = RPCReadVar(buffer) table.insert(values, v) argCount = argCount - 1 end local rpcFunc if sb then rpcFunc = self.rpcHandlerFuncSB[rpcID] if rpcFunc ~= nil then rpcFunc(self, player, unpack(values)) end else rpcFunc = self.rpcHandlerFuncCB[rpcID] if rpcFunc ~= nil then rpcFunc(self, unpack(values)) end end end function ModNetworkProxyHandler:HandleProxyServerBound(player) assert(self.isServer) local serverBoundPacket = self.mod.serverBoundPacket local buffer = serverBoundPacket.readerBuffer self:_RPCRead(buffer, player, true) end function ModNetworkProxyHandler:HandleProxyClientBound() assert(not self.isServer) local clientBoundPacket = self.mod.clientBoundPacket local buffer = clientBoundPacket.readerBuffer self:_RPCRead(buffer, nil, false) end return ModNetworkProxyHandler ================================================ FILE: network/NetworkProxy.lua ================================================ ---@class TC.NetworkProxy local NetworkProxy = class("NetworkProxy") ---RPCWriteVar ---@param buffer ByteStream ---@param v any local function RPCWriteVar(buffer, v) local typeName = type(v) if typeName == "number" then buffer:writeIntVarLen(1) if math.floor(v) == v then buffer:writeBoolean(false) buffer:writeIntVarLen(v) else buffer:writeBoolean(true) buffer:writeDouble(v) end elseif typeName == "boolean" then buffer:writeIntVarLen(2) buffer:writeBoolean(v) elseif typeName == "string" then buffer:writeIntVarLen(3) buffer:writeString(v) elseif typeName == "table" then buffer:writeIntVarLen(4) local tableCount = 0 for _ in pairs(v) do tableCount = tableCount + 1 end buffer:writeIntVarLen(tableCount) for tk, kv in pairs(v) do local tkTypeName = type(tk) if tkTypeName == "string" then buffer:writeBoolean(false) buffer:writeString(tk) else buffer:writeBoolean(true) buffer:writeIntVarLen(tk) end RPCWriteVar(buffer, kv) end elseif typeName == "nil" then buffer:writeIntVarLen(5) else assert(false, "RPC failed") end end ---RPCWrite ---@param buffer ByteStream ---@param rpcID int function NetworkProxy._RPCWrite(buffer, rpcID, ...) local argCount = select('#', ...) buffer:writeIntVarLen(rpcID) buffer:writeIntVarLen(argCount) for _, v in ipairs { ... } do RPCWriteVar(buffer, v) end end ---RPCSendServerBound ---@param mod Mod ---@param rpcID int function NetworkProxy.RPCSendServerBound(mod, rpcID, ...) if NetMode.current ~= NetMode.Client then return end local serverBoundPacket = mod.serverBoundPacket local buffer = serverBoundPacket.writerBuffer NetworkProxy._RPCWrite(buffer, rpcID, ...) serverBoundPacket:Send() end ---RPCSendClientBound ---@param mod Mod ---@param rpcID int ---@param player Player function NetworkProxy.RPCSendClientBound(mod, rpcID, player, ...) if NetMode.current ~= NetMode.Server then return end local clientBoundPacket = mod.clientBoundPacket local buffer = clientBoundPacket.writerBuffer NetworkProxy._RPCWrite(buffer, rpcID, ...) clientBoundPacket:Send(player) end return NetworkProxy ================================================ FILE: network/RPC_ID.lua ================================================ local RPC_ID = { SB_PLAYER_MAP_OPERATION = 1, SB_PLAYER_THROWING = 2, SB_REMOVE_WIRE = 3, SB_DROP_ITEM_HELD = 4, SB_DROP_ITEM_MOUSE = 5, } return RPC_ID ================================================ FILE: network/TCNetworkProxyHandler.lua ================================================ ---@class TC.TCNetworkProxyHandler:TC.ModNetworkProxyHandler local TCNetworkProxyHandler = class("TCNetworkProxyHandler", require("ModNetworkProxyHandler")) local RPC_ID = require("RPC_ID") local GPlayer = require("player.GPlayer") function TCNetworkProxyHandler:__init() TCNetworkProxyHandler.super.__init(self, Mod.current) local SERVER_BOUND_MAPPINGS = { [RPC_ID.SB_PLAYER_MAP_OPERATION] = TCNetworkProxyHandler.PlayerMapOperation, [RPC_ID.SB_PLAYER_THROWING] = TCNetworkProxyHandler.PlayerThrowing, [RPC_ID.SB_REMOVE_WIRE] = TCNetworkProxyHandler.RemoveWire, [RPC_ID.SB_DROP_ITEM_HELD] = TCNetworkProxyHandler.DropItemHeld, [RPC_ID.SB_DROP_ITEM_MOUSE] = TCNetworkProxyHandler.DropItemMouse, } self:RegisterRPCHandlerServerBoundMappings(SERVER_BOUND_MAPPINGS) end function TCNetworkProxyHandler:PlayerMapOperation(player, opType, xi, yi) GPlayer.GetInstance(player):OnMapOpServerBound(opType, xi, yi) end function TCNetworkProxyHandler:PlayerThrowing(player, angle) GPlayer.GetInstance(player):OnThrowingServerBound(angle) end function TCNetworkProxyHandler:RemoveWire(player, xi, yi) GPlayer.GetInstance(player):OnRemovingWireBound(xi, yi) end ---DropItemHeld ---@param player Player function TCNetworkProxyHandler:DropItemHeld(player, onlyOne) local heldSlot = player.backpackInventory:GetSlot(player.heldSlotIndex) if heldSlot.hasStack then player:DropItem(heldSlot:GetStack(), onlyOne) if onlyOne then heldSlot:DecrStackSize(1) else heldSlot:ClearStack() end end end ---DropItemHeld ---@param player Player function TCNetworkProxyHandler:DropItemMouse(player) local mouseSlot = player.mouseInventory:GetSlot(0) if mouseSlot.hasStack then player:DropItem(mouseSlot:GetStack()) mouseSlot:ClearStack() end end return TCNetworkProxyHandler ================================================ FILE: npc_ai/AngrySkeleton.json ================================================ { "AngrySkeleton": { "script": { "path": "AngrySkeleton.lua" } } } ================================================ FILE: npc_ai/AngrySkeleton.lua ================================================ ---@class TC.AngrySkeleton:TC.SwordHumanFighter local AngrySkeleton = class("AngrySkeleton", require("SwordHumanFighter")) function AngrySkeleton:Init() AngrySkeleton.super.Init(self) self:SetHeldItemByIDName("lead_sword") end function AngrySkeleton:Update() AngrySkeleton.super.Update(self) end return AngrySkeleton ================================================ FILE: npc_ai/Animal.json ================================================ { "Animal": { "script": { "path": "Animal.lua" } } } ================================================ FILE: npc_ai/Animal.lua ================================================ ---@class TC.Animal:ModNpc local Animal = class("Animal", ModNpc) function Animal:Init() -- all animal can save to file self.npc.isAutoSave = true end function Animal:Update() local npc = self.npc if npc.hurry then if Utils.RandTry(256) then npc.hurry = false end end if npc.hurry then npc.maxSpeed = npc.maxSpeed * 2 end npc:TryMakeSound() npc:RandomWalk() end function Animal:PostUpdate() if self.npc.speedX == 0 then self.npc.frameTickTime = 0 end end function Animal:OnHit() self.npc.hurry = true end --function Animal:Save() -- return { -- say = "I'm an animal!", -- value = 123 -- } --end -- --function Animal:Load(tagTable) -- print(tagTable) --end -- --function Animal:OnLoot() -- ItemUtils.CreateDrop(ItemStack.new(ItemRegistry.GetItemByIDName("diamond"), 2), -- self.npc.centerX, self.npc.centerY, 0, -3) --end return Animal ================================================ FILE: npc_ai/Archer.json ================================================ { "Archer": { "script": { "path": "Archer.lua" } } } ================================================ FILE: npc_ai/Archer.lua ================================================ ---@class TC.Archer:TC.HumanFighter local Archer = class("Archer", require("HumanFighter")) local State = { NORMAL = 0, NO_MOVE = 1 } function Archer:Init() Archer.super.Init(self) self.inventory = Inventory.new(1) self.npc.dataWatcher:AddInventory(self.inventory) self.itemSlotHeld = self.inventory:GetSlot(0) self.shootTimes = 0 self.shootOffsetAngle = 0 self.SHOOT_TIMES = self.npc.dataWatcher:AddInteger(0) end function Archer:Update() self:RecvSync() local npc = self.npc npc.noMove = true local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) npc.state = State.NORMAL if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end local watchAngle = Utils.FixAngle(npc.watchAngle) local offsetDir = 1 if watchAngle >= -math.pi / 2 and watchAngle < math.pi / 2 then offsetDir = -1 end watchAngle = watchAngle + self.shootOffsetAngle * offsetDir self.isHeadLook = true self.headLookAngle = watchAngle self.headLookDenominator = 2.0 self.isBackHandLook = true self.isFrontHandLook = true self.backHandLookAngle = watchAngle self.frontHandLookAngle = watchAngle npc.state = State.NORMAL if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 540 and self.shootTimes ~= 0 then npc.state = State.NO_MOVE end if distance < 1200 then if npc.stand or npc.gravity == 0 then if (npc.tickTime % 200 == 0) then self.isUsingItemForAnimation = true self.shootTimes = self.shootTimes + 1 end end end if self.shootTimes > 1 and Utils.RandTry(128) then self.shootTimes = 0 end end if npc.state == State.NORMAL then npc.noMove = false elseif npc.state == State.NO_MOVE then npc.noMove = true end if npc.gravity ~= 0 then npc:Walk() elseif npc.noMove then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.1) else npc:Fly() end if npc.inLiquid then npc.speedY = - 8 end self:SendSync() end function Archer:SendSync() if NetMode.current == NetMode.Server then self.npc.dataWatcher:UpdateInteger(self.SHOOT_TIMES, self.shootTimes) end end function Archer:RecvSync() if NetMode.current == NetMode.Client then self.shootTimes = self.npc.dataWatcher:GetInteger(self.SHOOT_TIMES) end end return Archer ================================================ FILE: npc_ai/BallMagic.json ================================================ { "BallMagic": { "script": { "path": "BallMagic.lua" } } } ================================================ FILE: npc_ai/BallMagic.lua ================================================ ---@class TC.BallMagic:ModNpc local BallMagic = class("BallMagic", ModNpc) function BallMagic:Init() self.npc.noHurt = true self.npc.noCollisionByWeapon = true end function BallMagic:Update() local npc = self.npc ---@type Player local target = PlayerUtils.SearchNearestPlayer(npc.centerX, npc.centerY, 1000) if target ~= nil then if npc:GetDistance(target.centerX, target.centerY) < 128 then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.2) npc.speedY = npc.speedY + math.sin(npc.tickTime / 8) / 4 npc.speedX = npc.speedX + math.cos(npc.tickTime / 18) / 6 else local targetAngle = npc:GetAngleTo(target.centerX, target.centerY) npc.speedX, npc.speedY = Utils.ForceSpeed2D(npc.speedX, npc.speedY, 0.2, targetAngle, npc.maxSpeed) end npc.direction = npc.centerX < target.centerX else npc.direction = npc.speedX > 0 end if npc.tickTime % 2 == 0 then local effectAngle = Utils.RandSym(math.pi) local d = 128 local effectX = npc.centerX + math.cos(effectAngle) * d local effectY = npc.centerY + math.sin(effectAngle) * d local effectSpeed = 6 local effectSpeedAngle = Utils.FixAngle(effectAngle + math.pi) local spx = npc.speedX + math.cos(effectSpeedAngle) * effectSpeed local spy = npc.speedY + math.sin(effectSpeedAngle) * effectSpeed local colorChannel = Utils.RandIntArea(200, 50) EffectUtils.Create( Reg.EffectID("flash2"), effectX, effectY, spx, spy, Utils.RandSym(0.5), Utils.RandDoubleArea(1.25, 0.5), 0.9, Color.new(colorChannel, colorChannel, colorChannel) ) end local npcTarget = NpcUtils.SearchNearestEnemy(npc.centerX, npc.centerY, 300, true) if npcTarget ~= nil then local targetAngle = npc:GetAngleTo(npcTarget.centerX, npcTarget.centerY) if npc.tickTime % 16 == 0 then local rotCenterX = npc.centerX local rotCenterY = npc.centerY - 8 local angle = targetAngle local shootX = rotCenterX + 24 * math.cos(angle) + Utils.RandSym(20) local shootY = rotCenterY + 24 * math.sin(angle) + Utils.RandSym(20) local speed = 12 local attack = Attack.new(11, 1, 1) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("air_wave"), shootX, shootY, speed * math.cos(angle), speed * math.sin(angle), attack) proj.isCheckNpc = true SoundUtils.PlaySound(Reg.SoundID("bow"), npc.centerXi, npc.centerYi) end end LightingUtils.Add(npc.centerXi, npc.centerYi, 32) end function BallMagic:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.spriteEx.angle + 0.1 end end return BallMagic ================================================ FILE: npc_ai/BaseSnake.lua ================================================ ---@class TC.BaseSnake:ModNpc local BaseSnake = class("BaseSnake", ModNpc) local SnakeModel = require("util.SnakeModel") -- TODO: 网络同步优化!不能每帧都同步坐标!! function BaseSnake:Init() local npc = self.npc self.npc.netUpdate = false self._snakeModel = SnakeModel.new() self._npcIndices = {} npc.isWatchAngleForTarget = false npc.rotateAngle = 0 end function BaseSnake:SetSnakeData(totalJointCount, bodyID, tailID, headDistance, bodyDistance, tailDistance, bodySize, tailSize) if NetMode.current ~= NetMode.Server then return end if totalJointCount < 2 then return end local npc = self.npc local cx, cy = npc.centerX, npc.centerY local lastDistance = headDistance local headRotateAngle = npc.rotateAngle local backAngle = Utils.FixAngle(headRotateAngle + math.pi) self._snakeModel:addHead(cx, cy, headRotateAngle, headDistance) for i = 2, totalJointCount do local id = bodyID local distance = bodyDistance local size = bodySize if i == totalJointCount then id = tailID distance = tailDistance size = tailSize end local d = (lastDistance + distance) * 0.5 cx = cx + math.cos(backAngle) * d cy = cy + math.sin(backAngle) * d local nextNpc = NpcUtils.Create(id, cx - size.width / 2, cy - size.height / 2) nextNpc.rotateAngle = headRotateAngle lastDistance = distance local entityIndex = EntityIndex.new(nextNpc.entityIndex.entityID, nextNpc.entityIndex.uniqueID) table.insert(self._npcIndices, entityIndex) self._snakeModel:addBody(Utils.FixAngle(nextNpc.rotateAngle + math.pi), distance) local modNpc = nextNpc:GetModNpc() if modNpc ~= nil and modNpc.SetHeadOwner ~= nil then modNpc:SetHeadOwner(self.npc.entityIndex) end end end function BaseSnake:PostUpdate() if NetMode.current == NetMode.Server then local npc = self.npc --npc.gravity = 0.1 --npc.speedY = npc.speedY + 0.05 --npc.speedX = 1 self._snakeModel:update(npc.centerX, npc.centerY, npc.speedX, npc.speedY, npc.rotateAngle) local cx, cy, angle = self._snakeModel:getRes(1) npc:SetCenterX(cx) npc:SetCenterY(cy) npc.rotateAngle = angle npc.watchAngle = npc.rotateAngle for i = 1, #self._npcIndices do local entityIndex = self._npcIndices[i] if NpcUtils.IsAlive(entityIndex) then local npcPart = NpcUtils.Get(entityIndex) cx, cy, angle = self._snakeModel:getRes(i + 1) npcPart:SetCenterX(cx) npcPart:SetCenterY(cy) npcPart.rotateAngle = angle npcPart.watchAngle = npcPart.rotateAngle end end npc.x = npc.x - npc.speedX npc.y = npc.y - npc.speedY end end function BaseSnake:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.watchAngle + math.pi end function BaseSnake:OnKilled() for i = 1, #self._npcIndices do local entityIndex = self._npcIndices[i] if NpcUtils.IsAlive(entityIndex) then local npcPart = NpcUtils.Get(entityIndex) npcPart.noLooting = true npcPart:KillByStrike() end end end return BaseSnake ================================================ FILE: npc_ai/BaseSnakeBody.lua ================================================ ---@class TC.BaseSnakeBody:ModNpc local BaseSnakeBody = class("BaseSnakeBody", ModNpc) function BaseSnakeBody:Init() self.npc.netUpdate = false self.headOwnerNpcIndex = nil self.npc.isAntiLava = true end function BaseSnakeBody:Update() if self.npc.tickTime % 64 == 0 then if self.headOwnerNpcIndex ~= nil then if not NpcUtils.IsAlive(self.headOwnerNpcIndex) then self.npc:Kill() end end end end function BaseSnakeBody:SetHeadOwner(npcIndex) self.headOwnerNpcIndex = npcIndex end function BaseSnakeBody:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.watchAngle + math.pi end function BaseSnakeBody:ModifyHit(attack) local headNpc = NpcUtils.Get(self.headOwnerNpcIndex) if headNpc ~= nil then attack.attack = attack.attack * 0.7 headNpc:Strike(attack) return false end return true end return BaseSnakeBody ================================================ FILE: npc_ai/Bat.json ================================================ { "Bat": { "script": { "path": "Bat.lua" } } } ================================================ FILE: npc_ai/Bat.lua ================================================ ---@type ModNpc local Bat = class("Bat", ModNpc) function Bat:Update() self.npc:Fly() end function Bat:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 end end return Bat ================================================ FILE: npc_ai/BlackSkeleton.json ================================================ { "BlackSkeleton": { "script": { "path": "BlackSkeleton.lua" } } } ================================================ FILE: npc_ai/BlackSkeleton.lua ================================================ ---@class TC.BlackSkeleton:TC.SwordHumanFighter local BlackSkeleton = class("BlackSkeleton", require("SwordHumanFighter")) function BlackSkeleton:Init() BlackSkeleton.super.Init(self) self:SetHeldItemByIDName("golden_pickaxe") end function BlackSkeleton:Update() BlackSkeleton.super.Update(self) self:DoExternArmsAnimation(1, 16) end return BlackSkeleton ================================================ FILE: npc_ai/Blaze.json ================================================ { "Blaze": { "script": { "path": "Blaze.lua" } } } ================================================ FILE: npc_ai/Blaze.lua ================================================ ---@class TC.Blaze:ModNpc local Blaze = class("Blaze", ModNpc) function Blaze:Init() local npc = self.npc -- 有BUG,砍了算了 --for i = 1, 4 do -- local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("blaze_rod"), npc.centerX, npc.centerY, 0, 0, npc.baseAttack) -- proj.isCheckPlayer = true -- if proj.modData:DataOf("Blaze_Rod") then -- proj.modData.beginDir = i - 1 -- end --end end function Blaze:Update() local npc = self.npc local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 360 then npc:Fly(false) -- random fly else npc:Fly() end if distance < 640 then if npc.tickTime > 0 and npc.tickTime % 128 == 0 then if MiscUtils.RayReach(npc.centerX, npc.centerY, playerTarget.centerX, playerTarget.centerY) then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("fire_charge"), npc.centerX, npc.centerY, 5 * math.cos(angle), 5 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end end else npc:Fly(false) end if npc.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("flame_star"), npc.randX, npc.randY, -npc.speedX, -npc.speedY, Utils.RandSym(1.0), Utils.RandDoubleArea(1, 2)) end LightingUtils.Add(npc.centerXi, npc.centerYi, 24, 12, 0, 0) end function Blaze:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 4 else npc.spriteEx.angle = 0 end end return Blaze ================================================ FILE: npc_ai/BlockSlime.json ================================================ { "BlockSlime": { "script": { "path": "BlockSlime.lua" } } } ================================================ FILE: npc_ai/BlockSlime.lua ================================================ ---@class TC.BlockSlime:ModNpc local BlockSlime = class("BlockSlime", ModNpc) local State = { NORMAL = 0, READY_TO_JUMP = 1, FALLEN = 2, } function BlockSlime:Update() local npc = self.npc if not npc.stand then npc.state = State.FALLEN if npc.direction then npc.speedX = npc.speedX + 0.1 else npc.speedX = npc.speedX - 0.1 end npc.speedX = math.max(npc.speedX, -npc.maxSpeed) npc.speedX = math.min(npc.speedX, npc.maxSpeed) else local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.1) if npc.state == State.NORMAL then npc.stateTimer = npc.stateTimer + 1 -- if Utils.RandTry(32) then if npc.stateTimer > 32 then npc.stateTimer = 0 npc.state = State.READY_TO_JUMP end elseif npc.state == State.READY_TO_JUMP then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = State.FALLEN if npc.direction then npc.speedX = Utils.RandDoubleArea(npc.maxSpeed / 2, npc.maxSpeed / 2) else npc.speedX = -Utils.RandDoubleArea(npc.maxSpeed / 2, npc.maxSpeed / 2) end npc.speedY = -Utils.RandDoubleArea(8, 4) end elseif npc.state == State.FALLEN then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = State.NORMAL end end else npc.stateTimer = 0 npc.state = State.NORMAL end end end function BlockSlime:OnDraw() local npc = self.npc npc.frameTickTime = 0 if not npc.stand then npc.spriteRect.x = npc.spriteDefaultWidth * 2 else if npc.state == State.NORMAL then npc.spriteRect.x = 0 else npc.spriteRect.x = npc.spriteDefaultWidth end end end return BlockSlime ================================================ FILE: npc_ai/BloodSkeleton.json ================================================ { "BloodSkeleton": { "script": { "path": "BloodSkeleton.lua" } } } ================================================ FILE: npc_ai/BloodSkeleton.lua ================================================ ---@type ModNpc local BloodSkeleton = class("BloodSkeleton", require("Archer")) function BloodSkeleton:Init() BloodSkeleton.super.Init(self) self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("blood_bow"))) self.shootOffsetAngle = 0.2 end return BloodSkeleton ================================================ FILE: npc_ai/BloodyEye.json ================================================ { "BloodyEye": { "script": { "path": "BloodyEye.lua" } } } ================================================ FILE: npc_ai/BloodyEye.lua ================================================ ---@type ModNpc local BloodyEye = class("BloodyEye", ModNpc) function BloodyEye:Update() local npc = self.npc npc:Fly() local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) local useShootTimer = false if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 560 then local angle = npc.speedAngle useShootTimer = true npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer >= 128 then npc.stateTimer = 0 if MiscUtils.RayReach(npc.centerX, npc.centerY, playerTarget.centerX, playerTarget.centerY) then local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("bullet_super"), npc.centerX + math.cos(angle) * 20, npc.centerY + math.sin(angle) * 20, 16 * math.cos(angle), 16 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("gore1"), npc.centerXi, npc.centerYi) end end if npc.tickTime % 32 == 0 then angle = angle + Utils.RandSym(0.5) EffectUtils.Create(Reg.EffectID("fire_flame"), npc.centerX + math.cos(angle) * 20, npc.centerY + math.sin(angle) * 20, 3 * math.cos(angle), 3 * math.sin(angle), 1, Utils.RandDoubleArea(0.5, 0.5), Utils.RandDoubleArea(0.75, 0.25)) end end end if not useShootTimer then npc.stateTimer = 0 end end function BloodyEye:OnDraw() self.npc.spriteEx.angle = self.npc.speedAngle end return BloodyEye ================================================ FILE: npc_ai/BoneArcher.json ================================================ { "BoneArcher": { "script": { "path": "BoneArcher.lua" } } } ================================================ FILE: npc_ai/BoneArcher.lua ================================================ ---@class TC.BoneArcher:TC.Archer local BoneArcher = class("BoneArcher", require("Archer")) function BoneArcher:Init() BoneArcher.super.Init(self) self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("wooden_bow"))) self.shootOffsetAngle = 0.2 end return BoneArcher ================================================ FILE: npc_ai/BoneLee.json ================================================ { "BoneLee": { "script": { "path": "BoneLee.lua" } } } ================================================ FILE: npc_ai/BoneLee.lua ================================================ ---@class TC.BoneLee:TC.HumanFighter local BoneLee = class("BoneLee", require("HumanFighter")) function BoneLee:Update() BoneLee.super.Update(self) local npc = self.npc if npc.inLiquid then npc.speedY = - 8 end end return BoneLee ================================================ FILE: npc_ai/BoneOfficer.json ================================================ { "BoneOfficer": { "script": { "path": "BoneOfficer.lua" } } } ================================================ FILE: npc_ai/BoneOfficer.lua ================================================ ---@class TC.BoneOfficer:TC.Archer local BoneOfficer = class("BoneOfficer", require("Archer")) function BoneOfficer:Init() BoneOfficer.super.Init(self) self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("soul_laserer"))) end return BoneOfficer ================================================ FILE: npc_ai/BoneSniper.json ================================================ { "BoneSniper": { "script": { "path": "BoneSniper.lua" } } } ================================================ FILE: npc_ai/BoneSniper.lua ================================================ ---@class TC.BoneSniper:TC.Archer local BoneSniper = class("BoneSniper", require("Archer")) function BoneSniper:Init() BoneSniper.super.Init(self) self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("sword_fish_gun"))) end return BoneSniper ================================================ FILE: npc_ai/BoneySkeleton.json ================================================ { "BoneySkeleton": { "script": { "path": "BoneySkeleton.lua" } } } ================================================ FILE: npc_ai/BoneySkeleton.lua ================================================ ---@class TC.BoneySkeleton:TC.SwordHumanFighter local BoneySkeleton = class("BoneySkeleton", require("SwordHumanFighter")) function BoneySkeleton:Init() BoneySkeleton.super.Init(self) self:SetHeldItemByIDName("iron_axe") end function BoneySkeleton:Update() BoneySkeleton.super.Update(self) self:DoExternArmsAnimation(1, 32) end return BoneySkeleton ================================================ FILE: npc_ai/BouncySlime.json ================================================ { "BouncySlime": { "script": { "path": "BouncySlime.lua" } } } ================================================ FILE: npc_ai/BouncySlime.lua ================================================ ---@class TC.BouncySlime:TC.BlockSlime local BouncySlime = class("BouncySlime", require("BlockSlime")) return BouncySlime ================================================ FILE: npc_ai/Butterfly.json ================================================ { "Butterfly": { "script": { "path": "Butterfly.lua" } } } ================================================ FILE: npc_ai/Butterfly.lua ================================================ ---@type ModNpc local Butterfly = class("Butterfly", ModNpc) function Butterfly:Update() self.npc:Fly() end function Butterfly:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 end npc.spriteEx.scaleRateX = 0.55 + Utils.SinValue(npc.frameTickTime, 16) * 0.45 npc.spriteOffsetX = -(npc.spriteEx.scaleRateX - 1) * npc.spriteDefaultWidth / 2 end return Butterfly ================================================ FILE: npc_ai/Cat.json ================================================ { "Cat": { "script": { "path": "Cat.lua" } } } ================================================ FILE: npc_ai/Cat.lua ================================================ ---@type ModNpc local Cat = class("Cat", require("Animal")) function Cat:OnDraw() local npc = self.npc if npc.frameTickTime > 0 then npc.spriteRect.x = npc.spriteRect.x + npc.spriteDefaultWidth end end return Cat ================================================ FILE: npc_ai/Chicken.json ================================================ { "Chicken": { "script": { "path": "Chicken.lua" } } } ================================================ FILE: npc_ai/Chicken.lua ================================================ ---@type ModNpc local Chicken = class("Chicken", require("Animal")) function Chicken:PostUpdate() local npc = self.npc if not npc.hurry then if npc.stand and npc.speedX == 0 and Utils.RandTry(2048) then -- lay eggs ItemUtils.CreateDrop(Reg.ItemID("egg"), 1, npc.centerX, npc.centerY) SoundUtils.PlaySound(Reg.SoundID("pop"), npc.centerXi, npc.centerYi) end end if npc.speedY > 3 then -- fall slowly npc.speedY = 3 end if npc.stand and npc.speedX == 0 then npc.frameTickTime = 0 end end function Chicken:OnDraw() local npc = self.npc if not npc.stand then npc.spriteRect.y = npc.spriteDefaultHeight end end return Chicken ================================================ FILE: npc_ai/Creeper.json ================================================ { "Creeper": { "script": { "path": "Creeper.lua" } } } ================================================ FILE: npc_ai/Creeper.lua ================================================ ---@class TC.Creeper:ModNpc local Creeper = class("Creeper", ModNpc) local ST_NORMAL = 0 local ST_EXPANDING_EXPLOSION = 1 local ST_CANCELING_EXPLOSION = 2 function Creeper:Init() self.boomPower = 8 self.boomHurtNpc = true self.boomHurtPlayer = true self.boomKillTile = true self.boomKillWall = true self.boomWaitTime = 128 self.boomCancelTime = 240 self.triggerExpandingDistance = 64 end function Creeper:Update() local npc = self.npc local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) npc.noMove = false if npc.state == ST_NORMAL then if npc.stand then if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < self.triggerExpandingDistance then npc.state = ST_EXPANDING_EXPLOSION SoundUtils.PlaySound(Reg.SoundID("fuse"), npc.centerXi, npc.centerYi) end end end elseif npc.state == ST_EXPANDING_EXPLOSION then npc.noMove = true npc.stateTimer = npc.stateTimer + 1 local canceling = false if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance > self.boomCancelTime then npc.state = ST_CANCELING_EXPLOSION canceling = true end end if not canceling then if npc.stateTimer > self.boomWaitTime then npc:Kill() MiscUtils.CreateExplosion(npc.centerXi, npc.centerYi, self.boomPower, self.boomHurtNpc, self.boomHurtPlayer, self.boomKillTile, self.boomKillWall) self:OnCreateBoomEffect(npc.centerX, npc.centerY) end end elseif npc.state == ST_CANCELING_EXPLOSION then npc.noMove = true npc.stateTimer = npc.stateTimer - 8 if npc.stateTimer <= 0 then npc.stateTimer = 0 npc.state = ST_NORMAL end end npc:Walk() end function Creeper:OnCreateBoomEffect(centerX, centerY) EffectUtils.CreateExplosion(centerX, centerY) end function Creeper:OnDraw() local npc = self.npc if npc.state == ST_EXPANDING_EXPLOSION or npc.state == ST_CANCELING_EXPLOSION then local scale = 1 + npc.stateTimer / 200 npc.spriteEx.scaleRateX = scale npc.spriteEx.scaleRateY = scale npc.spriteRect.x = npc.spriteDefaultWidth * npc.frames npc.spriteOffsetX = math.floor(-(scale - 1) * npc.spriteDefaultWidth / 2) npc.spriteOffsetY = math.floor(-(scale - 1) * npc.spriteDefaultHeight) else npc.spriteEx.scaleRateX = 1 npc.spriteEx.scaleRateY = 1 npc.spriteOffsetX = 0 npc.spriteOffsetY = 0 if npc.speedX == 0 and npc.stand then npc.frameTickTime = 0 end end end return Creeper ================================================ FILE: npc_ai/CrisonEye.json ================================================ { "CrisonEye": { "script": { "path": "CrisonEye.lua" } } } ================================================ FILE: npc_ai/CrisonEye.lua ================================================ ---@class TC.CrisonEye:ModNpc local CrisonEye = class("ManEater", ModNpc) local ST_READY = 0 local ST_DASH = 1 local ST_TRANSFORM = 2 local ST_LEAVE = 3 local IDLE_TIME = 128 local MAD_IDLE_TIME = 64 local TRANSFORM_TIME = 100 local TRANSFORM_TIME_HALF = TRANSFORM_TIME / 2 local DISTANCE = 360 local MAD_DISTANCE = 500 local DASH_TIME = 48 local DASH_TIMES = 1 local DASH_SPEED_SCALE = 2.5 local MAD_DASH_TIME = 80 local MAD_DASH_TIMES = 2 local MAD_DASH_SPEED_SCALE = 2.7 function CrisonEye:Init() self.facingAngle = 0 self:NotifyAllPlayer("crison_eye") self.isMad = false self.dashRemainTimes = 0 self.IS_MAD = self.npc.dataWatcher:AddBool(self.isMad) self.DASH_REMAIN_TIMES = self.npc.dataWatcher:AddInteger(self.dashRemainTimes) end function CrisonEye:Update() self:RecvSync() local npc = self.npc if not MiscUtils.isNight then npc.state = ST_LEAVE npc.stateTimer = 0 npc.speedX = 1 npc.speedY = -7 self.facingAngle = npc.speedAngle end if npc.state ~= ST_LEAVE then if not self.isMad and npc.health < npc.maxHealth * 0.4 then self.isMad = true npc.state = ST_TRANSFORM npc.stateTimer = 0 self:MakeMonsterSound() end if npc.state == ST_TRANSFORM then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.1) npc.stateTimer = npc.stateTimer + 1 if npc.tickTime % 32 == 0 then local rid = Reg.NpcID("fly_mouth") NpcUtils.Create(rid, npc.centerX + 60, npc.centerY + 60) end self.facingAngle = self.facingAngle + 0.4 * (1.0 - math.abs(npc.stateTimer - TRANSFORM_TIME_HALF) / TRANSFORM_TIME_HALF) if npc.stateTimer >= TRANSFORM_TIME then npc.state = ST_READY npc.stateTimer = 0 end else local flyFollowOnly = true local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) local checkDistance = self.isMad and 320 or DISTANCE if distance < checkDistance then flyFollowOnly = false npc.maxSpeed = 3.2 if npc.state == ST_READY then local force = 0.1 if self.isMad then force = 0.2 end npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, force) npc.stateTimer = npc.stateTimer + 1 local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) if not self.isMad and npc.stateTimer == 16 and Utils.RandTry(7) then local rid = Reg.NpcID("fly_mouth") NpcUtils.Create(rid, npc.centerX + 60 * math.cos(angle), npc.centerY + 60 * math.sin(angle), 2 * math.cos(angle), 2 * math.sin(angle) ) end local idleTime = self.isMad and 128 or IDLE_TIME if npc.stateTimer >= idleTime then local speedScale = self.isMad and MAD_DASH_SPEED_SCALE or DASH_SPEED_SCALE npc.speedX = npc.maxSpeed * math.cos(angle) * speedScale npc.speedY = npc.maxSpeed * math.sin(angle) * speedScale self.facingAngle = angle npc.state = ST_DASH npc.stateTimer = 0 if self.isMad then self:MakeMonsterSound() end self.dashRemainTimes = self.isMad and MAD_DASH_TIMES or DASH_TIMES npc:SyncAll() else self.facingAngle = self.facingAngle + Utils.FixAngle(angle - self.facingAngle) * 0.1 end elseif npc.state == ST_DASH then npc.stateTimer = npc.stateTimer + 1 local dashTime = self.isMad and MAD_DASH_TIME or DASH_TIME if npc.stateTimer >= dashTime then self.dashRemainTimes = self.dashRemainTimes - 1 if self.dashRemainTimes <= 0 then npc.state = ST_READY npc.stateTimer = 0 else local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local speedScale = self.isMad and MAD_DASH_SPEED_SCALE or DASH_SPEED_SCALE npc.speedX = npc.maxSpeed * math.cos(angle) * speedScale npc.speedY = npc.maxSpeed * math.sin(angle) * speedScale npc.state = ST_DASH npc.stateTimer = 0 if self.isMad then self:MakeMonsterSound() end end npc:SyncAll() end if self.isMad then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) self.facingAngle = angle end end end end if flyFollowOnly then if playerTarget ~= nil then self.facingAngle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) else self.facingAngle = npc.speedAngle end self.dashRemainTimes = 0 npc.state = ST_READY npc.stateTimer = npc.stateTimer + 1 npc.maxSpeed = 4 local force = 0.1 if self.isMad then npc.maxSpeed = 8 force = 0.4 end npc:Fly(true, force, true) end end end self:SendSync() npc:SyncAll() end function CrisonEye:MakeMonsterSound() SoundUtils.PlaySound(Reg.SoundID("monster"), self.npc.centerXi, self.npc.centerYi) end function CrisonEye:OnDraw() local npc = self.npc npc.spriteEx.angle = self.facingAngle end function CrisonEye:OnRender() local npc = self.npc local GW, GH = 184, 112 local rect = Rect.new(0, 0, GW, GH) if self.isMad then rect.y = rect.y + GH end local pos = Vector2.new(npc.centerX - MiscUtils.screenX, npc.centerY - MiscUtils.screenY) local spriteEx = SpriteExData.new() spriteEx.originX = GW / 2 spriteEx.originY = GH / 2 spriteEx.angle = self.facingAngle Sprite.draw(npc.texture, pos, rect, Color.White, spriteEx, 0.0) end function CrisonEye:OnKilled() self:NotifyAllPlayer("crison_eye_killed") end function CrisonEye:NotifyAllPlayer(advancementIDName) local advancementID = Reg.AdvancementID(advancementIDName) local players = PlayerUtils.SearchByCircle(self.npc.centerX, self.npc.centerY, 300 * 16) ---@param player Player for _, player in each(players) do player:FinishAdvancement(advancementID) end end function CrisonEye:SendSync() if NetMode.current == NetMode.Server then self.npc.dataWatcher:UpdateBool(self.IS_MAD, self.isMad) self.npc.dataWatcher:UpdateInteger(self.DASH_REMAIN_TIMES, self.dashRemainTimes) end end function CrisonEye:RecvSync() if NetMode.current == NetMode.Client then self.isMad = self.npc.dataWatcher:GetBool(self.IS_MAD) self.dashRemainTimes = self.npc.dataWatcher:GetInteger(self.DASH_REMAIN_TIMES) end end return CrisonEye ================================================ FILE: npc_ai/CrystalMonster.json ================================================ { "CrystalMonster": { "script": { "path": "CrystalMonster.lua" } } } ================================================ FILE: npc_ai/CrystalMonster.lua ================================================ ---@class TC.CrystalMonster:ModNpc local CrystalMonster = class("CrystalMonster", ModNpc) function CrystalMonster:Update() local npc = self.npc if npc.state == 0 then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 128 then npc.stateTimer = 0 npc.state = 1 end npc:Fly() elseif npc.state == 1 then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.55) if npc.tickTime % 2 == 0 then local effectAngle = Utils.RandSym(math.pi) local d = 128 local effectX = npc.centerX + math.cos(effectAngle) * d local effectY = npc.centerY + math.sin(effectAngle) * d local effectSpeed = 6 local effectSpeedAngle = Utils.FixAngle(effectAngle + math.pi) local spx = npc.speedX + math.cos(effectSpeedAngle) * effectSpeed local spy = npc.speedY + math.sin(effectSpeedAngle) * effectSpeed local colorChannel = Utils.RandIntArea(200, 50) EffectUtils.Create( Reg.EffectID("circle"), effectX, effectY, spx, spy, Utils.RandSym(0.5), Utils.RandDoubleArea(0.25, 0.5), 0.7, Color.new(colorChannel, colorChannel, colorChannel) ) EffectUtils.Create( Reg.EffectID("flash2"), effectX, effectY, spx * 0.5, spy * 0.5, Utils.RandSym(0.5), Utils.RandDoubleArea(0.25, 0.5), 0.9, Color.new(colorChannel, colorChannel, colorChannel) ) end npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 128 then npc.stateTimer = 0 npc.state = 0 for i = 0, 8 do local angle = math.pi * 2 / 8 * i local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("magic_wave"), npc.centerX, npc.centerY, 3 * math.cos(angle), 3 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true end SoundUtils.PlaySound(Reg.SoundID("wand1"), npc.centerXi, npc.centerYi) end end local effect = EffectUtils.Create(Reg.EffectID("chip"), self.npc.randX, self.npc.bottomY + Utils.RandSym(12), Utils.RandSym(0.1), Utils.RandDoubleArea(1, 1), Utils.RandSym(1), 1.0, 0.8, Color.new(200, 200, 200)) effect:SetDisappearTime(30) LightingUtils.Add(npc.centerXi, npc.centerYi, 32) end function CrystalMonster:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 else npc.spriteEx.angle = 0 end end return CrystalMonster ================================================ FILE: npc_ai/CursedSkull.json ================================================ { "CursedSkull": { "script": { "path": "CursedSkull.lua" } } } ================================================ FILE: npc_ai/CursedSkull.lua ================================================ ---@class TC.CursedSkull:ModNpc local CursedSkull = class("CursedSkull", ModNpc) local ST_READY = 0 local ST_DASH = 1 function CursedSkull:Init() self.facingAngle = 0 end function CursedSkull:Update() local npc = self.npc local flyOnly = true local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 340 then flyOnly = false if npc.state == ST_READY then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.1) npc.stateTimer = npc.stateTimer + 1 local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) if npc.stateTimer >= 32 then npc.speedX = npc.maxSpeed * math.cos(angle) * 2 npc.speedY = npc.maxSpeed * math.sin(angle) * 2 self.facingAngle = angle npc.state = ST_DASH npc.stateTimer = 0 else self.facingAngle = self.facingAngle + Utils.FixAngle(angle - self.facingAngle) * 0.1 end elseif npc.state == ST_DASH then npc.maxSpeed = 3 npc:Fly(true, 0.1, true) npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer >= 128 then npc.state = ST_READY npc.stateTimer = 0 end end end end if flyOnly then npc.maxSpeed = 1.25 if playerTarget ~= nil then self.facingAngle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) else self.facingAngle = npc.speedAngle end npc.state = ST_READY npc.stateTimer = 0 npc:Fly(true, 0.1, true) end if npc.speedX > 0 then npc.direction = true elseif npc.speedX < 0 then npc.direction = false end if npc.tickTime % 8 == 0 then EffectUtils.Create(Reg.EffectID("flame_star"), npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1)) EffectUtils.Create(Reg.EffectID("flame_star"), npc.randX, npc.randY, Utils.RandSym(1), -Utils.RandDouble(2), 0, Utils.RandDoubleArea(0.5, 0.5)) end end function CursedSkull:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 3 end return CursedSkull ================================================ FILE: npc_ai/DarkMage.json ================================================ { "DarkMage": { "script": { "path": "DarkMage.lua" } } } ================================================ FILE: npc_ai/DarkMage.lua ================================================ ---@class TC.DarkMage:ModNpc local DarkMage = class("DarkMage", ModNpc) local ST_NORMAL = 0 local ST_FIRING = 1 local SHOOT_TIMES = 3 function DarkMage:Init() self.shootTimes = 0 end function DarkMage:Update() local npc = self.npc npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.1) local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end if npc.state == ST_NORMAL then npc.stateTimer = npc.stateTimer + 1 if self.shootTimes < SHOOT_TIMES and npc.stateTimer > 64 then npc.stateTimer = 0 npc.state = ST_FIRING self.shootTimes = self.shootTimes + 1 if playerTarget ~= nil then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("shulker_bullet"), npc.centerX, npc.centerY, 2 * math.cos(angle), 2 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end if npc.speedY > 6 or (self.shootTimes >= SHOOT_TIMES and npc.stateTimer > 64) then npc.state = 0 self.shootTimes = 0 npc.stateTimer = 0 local currentX = npc.x local currentY = npc.y local teleportSuccess = npc:RandomTeleport(32) if teleportSuccess then local e_ender_flash = Reg.EffectID("ender_flash") for i = 1, 16 do EffectUtils.Create(e_ender_flash, currentX + Utils.RandInt(npc.width), currentY + Utils.RandInt(npc.height), Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end for i = 1, 16 do EffectUtils.Create(e_ender_flash, npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("portal"), npc.centerXi, npc.centerYi) end end elseif npc.state == ST_FIRING then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = ST_NORMAL end end end function DarkMage:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.speedX / 8 if npc.state == ST_NORMAL then npc.spriteRect.x = 0 elseif npc.state == ST_FIRING then npc.spriteRect.x = npc.spriteDefaultWidth end end return DarkMage ================================================ FILE: npc_ai/DeadMage.json ================================================ { "DeadMage": { "script": { "path": "DeadMage.lua" } } } ================================================ FILE: npc_ai/DeadMage.lua ================================================ ---@class TC.DeadMage:ModNpc local DeadMage = class("DeadMage", ModNpc) local ST_NORMAL = 0 local ST_FIRING = 1 local SHOOT_TIMES = 3 function DeadMage:Init() self.shootTimes = 0 end function DeadMage:Update() local npc = self.npc npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.1) local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end if npc.state == ST_NORMAL then npc.stateTimer = npc.stateTimer + 1 if self.shootTimes < SHOOT_TIMES and npc.stateTimer > 64 then npc.stateTimer = 0 npc.state = ST_FIRING self.shootTimes = self.shootTimes + 1 if playerTarget ~= nil then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("shulker_bullet"), npc.centerX, npc.centerY, 2 * math.cos(angle), 2 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end if npc.speedY > 6 or (self.shootTimes >= SHOOT_TIMES and npc.stateTimer > 64) then npc.state = 0 self.shootTimes = 0 npc.stateTimer = 0 local currentX = npc.x local currentY = npc.y local teleportSuccess = npc:RandomTeleport(32) if teleportSuccess then local e_ender_flash = Reg.EffectID("ender_flash") for i = 1, 16 do EffectUtils.Create(e_ender_flash, currentX + Utils.RandInt(npc.width), currentY + Utils.RandInt(npc.height), Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end for i = 1, 16 do EffectUtils.Create(e_ender_flash, npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("portal"), npc.centerXi, npc.centerYi) end end elseif npc.state == ST_FIRING then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = ST_NORMAL end end end function DeadMage:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.speedX / 8 if npc.state == ST_NORMAL then npc.spriteRect.x = 0 elseif npc.state == ST_FIRING then npc.spriteRect.x = npc.spriteDefaultWidth end end return DeadMage ================================================ FILE: npc_ai/Dolphin.json ================================================ { "Dolphin": { "script": { "path": "Dolphin.lua" } } } ================================================ FILE: npc_ai/Dolphin.lua ================================================ ---@type ModNpc local Dolphin = class("Dolphin", ModNpc) function Dolphin:Update() local npc = self.npc npc:TryMakeSound() npc:Swim() -- always want to swim up if npc.inLiquid then npc.maxSpeed = npc.maxSpeed * 2 end if npc.inLiquid and Utils.RandTry(128) then npc.speedY = npc.speedY - 0.1 end -- jump out of the liquid if not npc.inLiquid and npc.oldInLiquid and npc.speedY < 0 then if (npc.direction and npc.speedX > 0) or (not npc.direction and npc.speedX < 0) then npc.speedY = -npc.jumpForce end npc:MakeSound() end end function Dolphin:OnDraw() local npc = self.npc local angle = Utils.GetAngle(math.abs(npc.speedX), npc.speedY) * 0.5 if (npc.direction and npc.speedX > 0) or (not npc.direction and npc.speedX < 0) then angle = -angle end npc.spriteEx.angle = angle end return Dolphin ================================================ FILE: npc_ai/DungeonCreeper.json ================================================ { "DungeonCreeper": { "script": { "path": "DungeonCreeper.lua" } } } ================================================ FILE: npc_ai/DungeonCreeper.lua ================================================ ---@class TC.DungeonCreeper:TC.Creeper local DungeonCreeper = class("DungeonCreeper", require("Creeper")) function DungeonCreeper:Init() DungeonCreeper.super.Init(self) self.boomPower = 8 --self.boomHurtNpc = true --self.boomHurtPlayer = true self.boomKillTile = false self.boomKillWall = false end function DungeonCreeper:OnCreateBoomEffect(centerX, centerY) EffectUtils.CreateExplosion(centerX, centerY) local npc = self.npc local cnt = 16 for i = 0, cnt do local angle = math.pi * 2 / cnt * i local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("lighting_arrow"), npc.centerX, npc.centerY, 8 * math.cos(angle), 8 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true end end return DungeonCreeper ================================================ FILE: npc_ai/DungeonEater.lua ================================================ ---@class TC.DungeonEater:TC.BaseSnake local DungeonEater = class("DungeonEater", require("BaseSnake")) local PhysicsUtil = require("util.PhysicsUtil") function DungeonEater:Init() DungeonEater.super.Init(self) self:SetSnakeData(12, Reg.NpcID("dungeon_eater_body"), Reg.NpcID("dungeon_eater_tail"), 48, 34, 48, Size.new(44, 36), Size.new(54, 40) ) self.npc.isAntiLava = true self.hungerTick = 0 self:NotifyAllPlayer("dungeon_eater") end function DungeonEater:Update() local npc = self.npc if NetMode.current == NetMode.Server then local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) local isMad = self.hungerTick > 128 local force = 0.15 local maxSpeed = 4 if isMad then force = 0.10 maxSpeed = 5 end if self.hungerTick > 1500 then npc.speedY = math.min(4, npc.speedY + 0.3) else if playerTarget ~= nil then npc.speedX, npc.speedY = PhysicsUtil.SightChaseSpeed2D(npc.speedX, npc.speedY, force, Utils.GetAngle(playerTarget.centerX - npc.centerX, playerTarget.centerY - npc.centerY), maxSpeed) npc.speedX = npc.speedX + Utils.RandSym(0.5) npc.speedY = npc.speedY + Utils.RandSym(0.5) end end if isMad then if playerTarget ~= nil then local iv = 64 if self.hungerTick < 400 then iv = 64 elseif self.hungerTick < 700 then iv = 32 end if npc.tickTime > 0 and npc.tickTime % iv == 0 then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("ice_bullet"), npc.centerX, npc.centerY, 7 * math.cos(angle), 7 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end end if npc.tickTime % 8 == 0 then local eat = DungeonEater.DoEatDungeonBlocks(npc) if eat then self.hungerTick = 0 end end self.hungerTick = self.hungerTick + 1 end LightingUtils.Add(npc.centerXi, npc.centerYi, 26) end function DungeonEater:OnKilled() DungeonEater.super.OnKilled(self) self:NotifyAllPlayer("dungeon_eater_killed") end function DungeonEater:NotifyAllPlayer(advancementIDName) local advancementID = Reg.AdvancementID(advancementIDName) local players = PlayerUtils.SearchByCircle(self.npc.centerX, self.npc.centerY, 300 * 16) ---@param player Player for _, player in each(players) do player:FinishAdvancement(advancementID) end end local EATABLE_DUNGEON_BLOCKS = { [Reg.BlockID("more_dungeons:dungeon_brick_green")] = true, } function DungeonEater.DoEatDungeonBlocks(npc) local eat = false local cxi, cyi = npc.centerXi, npc.centerYi for i = -1, 1 do for j = -1, 1 do local xi, yi = cxi + i, cyi + j local ok = false local blockID = MapUtils.GetFrontID(xi, yi) if blockID > 0 and EATABLE_DUNGEON_BLOCKS[blockID] then local hasAttachBlock = false if (MapUtils.HasFront(xi, yi - 1) and not MapUtils.IsSolid(xi, yi - 1)) or (MapUtils.HasFront(xi, yi + 1) and not MapUtils.IsSolid(xi, yi + 1)) then hasAttachBlock = true end if not hasAttachBlock then ok = MapUtils.RemoveFront(xi, yi, false, true) if ok then eat = true if Utils.RandTry(16) then local effect = EffectUtils.SendFromServer(Reg.EffectID("flame_star"), xi * 16 + 8, yi * 16 + 8, Utils.RandSym(1.0), Utils.RandSym(1.0), Utils.RandSym(1.0), Utils.RandDoubleArea(1, 2)) effect:SetDisappearTime(120) end end end end end end return eat end return DungeonEater ================================================ FILE: npc_ai/DungeonEaterBody.lua ================================================ ---@class TC.DungeonEaterBody:TC.BaseSnakeBody local DungeonEaterBody = class("DungeonEaterBody", require("BaseSnakeBody")) local DungeonEater = require("DungeonEater") function DungeonEaterBody:Init() DungeonEaterBody.super.Init(self) end function DungeonEaterBody:Update() DungeonEaterBody.super.Update(self) local npc = self.npc DungeonEater.DoEatDungeonBlocks(npc) LightingUtils.Add(npc.centerXi, npc.centerYi, 26) end return DungeonEaterBody ================================================ FILE: npc_ai/DungeonEater_Body.json ================================================ { "DungeonEater_Body": { "script": { "path": "DungeonEaterBody.lua" } } } ================================================ FILE: npc_ai/DungeonEater_Head.json ================================================ { "DungeonEater_Head": { "script": { "path": "DungeonEater.lua" } } } ================================================ FILE: npc_ai/DungeonKnight.json ================================================ { "DungeonKnight": { "script": { "path": "DungeonKnight.lua" } } } ================================================ FILE: npc_ai/DungeonKnight.lua ================================================ ---@class TC.DungeonKnight:TC.HumanFighter local DungeonKnight = class("DungeonKnight", require("HumanFighter")) function DungeonKnight:Init() self.boneSizeIndex = 1 DungeonKnight.super.Init(self) self.inventory = Inventory.new(1) self.npc.dataWatcher:AddInventory(self.inventory) self.itemSlotHeld = self.inventory:GetSlot(0) self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("iron_sword"))) self.isBackHandLook = true self.isFrontHandLook = true self.isBackHandLookAngleSameDirection = true self.isFrontHandLookAngleSameDirection = true end function DungeonKnight:Update() DungeonKnight.super.Update(self) local npc = self.npc local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end if math.fmod(npc.tickTime, 8) == 0 then self.isUsingItemForAnimation = true end self.isHeadLook = true self.headLookAngle = npc.watchAngle self.headLookDenominator = 2.0 self.backHandLookAngle = math.pi / 3 self.frontHandLookAngle = math.pi / 3 if npc.state == 0 then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 100 then npc.stateTimer = 0 npc.state = 1 end elseif npc.state == 1 then npc.stateTimer = npc.stateTimer + 1 local TIME = 30 local angle = npc.stateTimer / TIME * math.pi * 1.0 - math.pi / 3 * 2 self.backHandLookAngle = angle self.frontHandLookAngle = angle if npc.stateTimer > TIME then npc.stateTimer = 0 npc.state = 0 local ba = npc.watchAngle local step = math.pi / 8 local cnt = 3 local speed = 3 local cx = npc.centerX + (npc.direction and 32 or -32) local cy = npc.centerY for i = 0, cnt - 1 do local angle = ba - step * cnt / 2 + step * i local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("lighting_bullet_blue"), cx, cy, speed * math.cos(angle), speed * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true end end end end return DungeonKnight ================================================ FILE: npc_ai/DungeonSkeleton.json ================================================ { "DungeonSkeleton": { "script": { "path": "DungeonSkeleton.lua" } } } ================================================ FILE: npc_ai/DungeonSkeleton.lua ================================================ ---@class TC.DungeonSkeleton:TC.SwordHumanFighter local DungeonSkeleton = class("DungeonSkeleton", require("SwordHumanFighter")) function DungeonSkeleton:Init() DungeonSkeleton.super.Init(self) if self.style == 0 then self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("stone_sword"))) elseif self.style == 1 then self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("lead_sword"))) elseif self.style == 2 then self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("super_lead_sword"))) elseif self.style == 3 then self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("super_copper_sword"))) end if self.style == 0 then self.isFrontHandLook = false self.isBackHandLook = false end end function DungeonSkeleton:Update() DungeonSkeleton.super.Update(self) local npc = self.npc if Utils.RandTry(128) and npc.stand then npc.speedY = -6 npc.speedX = npc.speedX * 1.5 end if npc.inLiquid then npc.speedY = - 8 end end function DungeonSkeleton:OnWaitSwing() local npc = self.npc if self.style == 1 then self.frontHandLookAngle = math.cos(npc.tickTime / 16) / 4 self.backHandLookAngle = math.sin(npc.tickTime / 16) / 4 elseif self.style == 2 then self.frontHandLookAngle = math.pi / 3 + math.cos(npc.tickTime / 8) / 8 self.backHandLookAngle = math.pi / 3 + math.cos(npc.tickTime / 8) / 8 elseif self.style == 3 then self.frontHandLookAngle = -math.pi / 3 + math.cos(npc.tickTime / 12) / 4 self.backHandLookAngle = -math.pi / 3 + math.cos(npc.tickTime / 12) / 4 end end return DungeonSkeleton ================================================ FILE: npc_ai/DungeonSoul.json ================================================ { "DungeonSoul": { "script": { "path": "DungeonSoul.lua" } } } ================================================ FILE: npc_ai/DungeonSoul.lua ================================================ ---@class TC.DungeonSoul:ModNpc local DungeonSoul = class("DungeonSoul", ModNpc) function DungeonSoul:Init() end function DungeonSoul:Update() local npc = self.npc local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 360 then npc:Fly(false) -- random fly else npc:Fly() end if distance < 640 then if npc.tickTime > 0 and npc.tickTime % 128 == 0 then if MiscUtils.RayReach(npc.centerX, npc.centerY, playerTarget.centerX, playerTarget.centerY) then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("fire_charge"), npc.centerX, npc.centerY, 5 * math.cos(angle), 5 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end end else npc:Fly(false) end if npc.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("flame_star"), npc.randX, npc.randY, -npc.speedX, -npc.speedY, Utils.RandSym(1.0), Utils.RandDoubleArea(1, 2)) end LightingUtils.Add(npc.centerXi, npc.centerYi, 24, 12, 0, 0) end function DungeonSoul:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 4 else npc.spriteEx.angle = 0 end end return DungeonSoul ================================================ FILE: npc_ai/Eagle.json ================================================ { "Eagle": { "script": { "path": "Eagle.lua" } } } ================================================ FILE: npc_ai/Eagle.lua ================================================ ---@type ModNpc local Eagle = class("Eagle", ModNpc) function Eagle:Update() self.npc:Fly() end function Eagle:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 end end return Eagle ================================================ FILE: npc_ai/Ender_Dragon.json ================================================ { "Ender_Dragon": { "pAI": "Ender_Dragon_AI" } } ================================================ FILE: npc_ai/Enderman.json ================================================ { "Enderman": { "script": { "path": "Enderman.lua" } } } ================================================ FILE: npc_ai/Enderman.lua ================================================ ---@type ModNpc local Enderman = class("Enderman", require("HumanFighter")) local function Teleport(npc) local currentX = npc.x local currentY = npc.y local teleportSuccess = npc:RandomTeleport(32) if teleportSuccess then local sg_portal = Reg.SoundGroupID("portal") local e_ender_flash = Reg.EffectID("ender_flash") for _ = 1, 16 do EffectUtils.Create(e_ender_flash, currentX + Utils.RandInt(npc.width), currentY + Utils.RandInt(npc.height), Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end for _ = 1, 16 do EffectUtils.Create(e_ender_flash, npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end SoundUtils.PlaySoundGroup(sg_portal, npc.centerXi, npc.centerYi) end end function Enderman:Init() self.boneSizeIndex = 1 Enderman.super.Init(self) end function Enderman:Update() local npc = self.npc if npc.angry then print("aaaa") npc.maxSpeed = npc.maxSpeed * 1.5 if npc.stand and Utils.RandTry(32) then npc.speedY = -6 end else npc:TryMakeSound() end npc:Walk() local tp = false if npc.inLiquid then tp = true elseif npc.stand and Utils.RandTry(256) then tp = true else -- check projectiles local projectiles = ProjectileUtils.SearchByCircle(npc.centerX, npc.centerY, 80) for i = 1, projectiles.length do local proj = projectiles[i] if proj.isCheckNpc then tp = true break end end end if tp then Teleport(npc) end end function Enderman:OnHit() Teleport(self.npc) end return Enderman ================================================ FILE: npc_ai/Evil.json ================================================ { "Evil": { "script": { "path": "Evil.lua" } } } ================================================ FILE: npc_ai/Evil.lua ================================================ ---@class TC.Evil:ModNpc local Evil = class("Evil", ModNpc) function Evil:Update() local npc = self.npc npc:Fly() if npc.speedY >= 0 then local b1 = Utils.RandTry(8) local b2 = Utils.RandTry(8) if b1 or b2 then local angle = npc.speedX / npc.maxSpeed / 2 local ex = 32 * math.cos(angle) local ey = 32 * math.sin(angle) if b1 then EffectUtils.Create(Reg.EffectID("ender_flash"), npc.centerX + ex, npc.centerY + ey, Utils.RandSym(0.25), Utils.RandSym(0.25), 0, Utils.RandDoubleArea(1, 1)) end if b2 then EffectUtils.Create(Reg.EffectID("ender_flash"), npc.centerX - ex, npc.centerY - ey, Utils.RandSym(0.25), Utils.RandSym(0.25), 0, Utils.RandDoubleArea(1, 1)) end end else if Utils.RandTry(4) then EffectUtils.Create(Reg.EffectID("ender_flash"), npc.centerX + Utils.RandSym(8), npc.centerY + 8, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1)) end end end function Evil:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 end local noChangeFrame = false --if npc.speedY >= 0 then -- if npc.frameTickTime <= 1 then -- noChangeFrame = true -- end --end if npc.frameTickTime > npc.frames * npc.frameSpeed then noChangeFrame = true end if noChangeFrame then npc.frameTickTime = 0 end end return Evil ================================================ FILE: npc_ai/Evoker.json ================================================ { "Evoker": { "script": { "path": "Evoker.lua" } } } ================================================ FILE: npc_ai/Evoker.lua ================================================ ---@class TC.Evoker:ModNpc local Evoker = class("Evoker", ModNpc) local ST_NORMAL = 0 local ST_FIRING = 1 local SHOOT_TIMES = 3 function Evoker:Init() self.shootTimes = 0 end function Evoker:Update() local npc = self.npc npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.1) local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end if npc.state == ST_NORMAL then npc.stateTimer = npc.stateTimer + 1 if self.shootTimes < SHOOT_TIMES and npc.stateTimer > 64 then npc.stateTimer = 0 npc.state = ST_FIRING self.shootTimes = self.shootTimes + 1 if playerTarget ~= nil then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("shulker_bullet"), npc.centerX, npc.centerY, 2 * math.cos(angle), 2 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end if npc.speedY > 6 or (self.shootTimes >= SHOOT_TIMES and npc.stateTimer > 64) then npc.state = 0 self.shootTimes = 0 npc.stateTimer = 0 local currentX = npc.x local currentY = npc.y local teleportSuccess = npc:RandomTeleport(32) if teleportSuccess then local e_ender_flash = Reg.EffectID("ender_flash") for i = 1, 16 do EffectUtils.Create(e_ender_flash, currentX + Utils.RandInt(npc.width), currentY + Utils.RandInt(npc.height), Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end for i = 1, 16 do EffectUtils.Create(e_ender_flash, npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("portal"), npc.centerXi, npc.centerYi) end end elseif npc.state == ST_FIRING then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = ST_NORMAL end end end function Evoker:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.speedX / 8 if npc.state == ST_NORMAL then npc.spriteRect.x = 0 elseif npc.state == ST_FIRING then npc.spriteRect.x = npc.spriteDefaultWidth end end return Evoker ================================================ FILE: npc_ai/EyeGuard.json ================================================ { "EyeGuard": { "script": { "path": "EyeGuard.lua" } } } ================================================ FILE: npc_ai/EyeGuard.lua ================================================ ---@class TC.EyeGuard:ModNpc local EyeGuard = class("EyeGuard", ModNpc) function EyeGuard:Init() end function EyeGuard:Update() local npc = self.npc local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 180 then npc:Fly(false) -- random fly else npc:Fly() end else npc:Fly(false, 0.5) end LightingUtils.Add(npc.centerXi, npc.centerYi, 24, 12, 0, 0) end function EyeGuard:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 4 else npc.spriteEx.angle = 0 end end return EyeGuard ================================================ FILE: npc_ai/EyeGuardLaser.json ================================================ { "EyeGuardLaser": { "script": { "path": "EyeGuardLaser.lua" } } } ================================================ FILE: npc_ai/EyeGuardLaser.lua ================================================ ---@class TC.EyeGuardLaser:ModNpc local EyeGuardLaser = class("EyeGuardLaser", ModNpc) function EyeGuardLaser:Init() end function EyeGuardLaser:Update() local npc = self.npc local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 360 then npc:Fly(false) -- random fly else npc:Fly() end npc.direction = npc.centerX < playerTarget.centerX if distance < 640 then if npc.tickTime > 0 and npc.tickTime % 128 == 0 then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) if angle > -math.pi / 2 and angle < math.pi / 2 then angle = angle - 0.5 else angle = angle + 0.5 end local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("fire_wave"), npc.centerX, npc.centerY, 6 * math.cos(angle), 6 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true end end else npc:Fly(false) end if npc.tickTime % 64 == 0 then EffectUtils.Create(Reg.EffectID("flame_star"), npc.randX, npc.randY, -npc.speedX, -npc.speedY, Utils.RandSym(1.0), Utils.RandDoubleArea(1, 2)) end LightingUtils.Add(npc.centerXi, npc.centerYi, 24, 12, 0, 0) end function EyeGuardLaser:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 4 else npc.spriteEx.angle = 0 end end return EyeGuardLaser ================================================ FILE: npc_ai/Fighter.json ================================================ { "Fighter": { "script": { "path": "Fighter.lua" } } } ================================================ FILE: npc_ai/Fighter.lua ================================================ ---@class TC.Fighter:ModNpc local Fighter = class("Fighter", ModNpc) function Fighter:Update() self.npc:TryMakeSound() self.npc:Walk() end return Fighter ================================================ FILE: npc_ai/FireHellEater.json ================================================ { "FireHellEater": { "script": { "path": "FireHellEater.lua" } } } ================================================ FILE: npc_ai/FireHellEater.lua ================================================ ---@class TC.FireHellEater:TC.HellEater local FireHellEater = class("FireHellEater", require("HellEater")) function FireHellEater:OnTileCollide(oldSpeedX, oldSpeedY) end return FireHellEater ================================================ FILE: npc_ai/FlameSoul.json ================================================ { "FlameSoul": { "script": { "path": "FlameSoul.lua" } } } ================================================ FILE: npc_ai/FlameSoul.lua ================================================ ---@class TC.FlameSoul:ModNpc local FlameSoul = class("FlameSoul", ModNpc) function FlameSoul:Init() end function FlameSoul:Update() local npc = self.npc local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 360 then npc:Fly(false) -- random fly else npc:Fly() end else npc:Fly(false) end if npc.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("flame_star"), npc.randX, npc.randY, -npc.speedX, -npc.speedY, Utils.RandSym(1.0), Utils.RandDoubleArea(1, 2)) end LightingUtils.Add(npc.centerXi, npc.centerYi, 24, 12, 0, 0) end function FlameSoul:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 4 else npc.spriteEx.angle = 0 end end return FlameSoul ================================================ FILE: npc_ai/FlyEye.json ================================================ { "FlyEye": { "script": { "path": "FlyEye.lua" } } } ================================================ FILE: npc_ai/FlyEye.lua ================================================ ---@class TC.FlyEye:ModNpc local FlyEye = class("FlyEye", ModNpc) function FlyEye:Update() self.npc:Fly() end function FlyEye:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 end end return FlyEye ================================================ FILE: npc_ai/FlySkeleton.json ================================================ { "FlySkeleton": { "script": { "path": "FlySkeleton.lua" } } } ================================================ FILE: npc_ai/FlySkeleton.lua ================================================ ---@class TC.FlySkeleton:TC.HumanFighter local FlySkeleton = class("FlySkeleton", require("HumanFighter")) function FlySkeleton:Init() FlySkeleton.super.Init(self) end function FlySkeleton:Update() local npc = self.npc npc:Fly() if npc.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("flash2"), npc.randX, npc.randY, Utils.RandSym(0.2), Utils.RandSym(0.2), 0, Utils.RandDoubleArea(0.5, 0.5)) end self.isFrontLegOverwrite = true self.isBackLegOverwrite = true self.frontLegOverwriteAngle = math.cos(npc.tickTime / 16) * 0.2 + 0.4 self.backLegOverwriteAngle = math.sin(npc.tickTime / 16) * 0.2 + 0.4 end return FlySkeleton ================================================ FILE: npc_ai/Ghast.json ================================================ { "Ghast": { "script": { "path": "Ghast.lua" } } } ================================================ FILE: npc_ai/Ghast.lua ================================================ ---@type ModNpc local Ghast = class("Ghast", ModNpc) local ST_NORMAL = 0 local ST_FIRING = 1 function Ghast:Update() local npc = self.npc npc:TryMakeSound() npc:Fly(false) local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) if npc.state == ST_NORMAL then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 256 then npc.stateTimer = 0 local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local shootX = 0 local shootY = npc.centerY if npc.direction then shootX = npc.rightX - 16 else shootX = npc.x + 16 end local shootXi = Utils.Cell(shootX) local shootYi = Utils.Cell(shootY) if not MapUtils.IsSolid(shootXi, shootYi) then local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("fire_charge"), shootX, shootY, 4 * math.cos(angle), 4 * math.sin(angle), npc.baseAttack) if proj.modData:DataOf("Fireball") then proj.isCheckPlayer = true proj.modData.boom = true -- explosion when hit end SoundUtils.PlaySound(Reg.SoundID("ghast_charge"), npc.centerXi, npc.centerYi) npc.state = ST_FIRING end end elseif npc.state == ST_FIRING then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 32 then npc.stateTimer = 0 npc.state = ST_NORMAL end end else npc.stateTimer = 0 npc.state = ST_NORMAL end end function Ghast:OnDraw() local npc = self.npc if npc.state == ST_FIRING then npc.spriteRect.x = npc.spriteDefaultWidth end if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 8 end end return Ghast ================================================ FILE: npc_ai/GhostGunner.json ================================================ { "GhostGunner": { "script": { "path": "GhostGunner.lua" } } } ================================================ FILE: npc_ai/GhostGunner.lua ================================================ ---@class TC.GhostGunner:TC.HumanFighter local GhostGunner = class("GhostGunner", require("HumanFighter")) function GhostGunner:Init() GhostGunner.super.Init(self) self.inventory = Inventory.new(1) self.npc.dataWatcher:AddInventory(self.inventory) self.itemSlotHeld = self.inventory:GetSlot(0) self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("super_shark_ghost"))) self.isFrontHandLook = true self.isBackHandLook = true self.ghostAllowToShoot = false self.isGhostGuard = true self.GHOST_ALLOW_TO_SHOOT = self.npc.dataWatcher:AddBool(self.ghostAllowToShoot) end function GhostGunner:OnHit() self.ghostAllowToShoot = true end function GhostGunner:Update() local npc = self.npc if NetMode.current == NetMode.Server then npc.dataWatcher:UpdateBool(self.GHOST_ALLOW_TO_SHOOT, self.ghostAllowToShoot) else self.ghostAllowToShoot = npc.dataWatcher:GetBool(self.GHOST_ALLOW_TO_SHOOT) end npc:Fly(self.ghostAllowToShoot) if npc.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("flash2"), npc.randX, npc.randY, Utils.RandSym(0.2), Utils.RandSym(0.2), 0, Utils.RandDoubleArea(0.5, 0.5)) end if self.ghostAllowToShoot then local watchAngle = npc.watchAngle self.backHandLookAngle = watchAngle self.frontHandLookAngle = watchAngle if npc.tickTime % 64 == 0 then self.isUsingItemForAnimation = true end else self.frontHandLookAngle = math.cos(self.npc.tickTime / 16) / 4 self.backHandLookAngle = math.sin(self.npc.tickTime / 16) / 4 end end return GhostGunner ================================================ FILE: npc_ai/GhostSoul.json ================================================ { "GhostSoul": { "script": { "path": "GhostSoul.lua" } } } ================================================ FILE: npc_ai/GhostSoul.lua ================================================ ---@class TC.GhostSoul:ModNpc local GhostSoul = class("GhostSoul", ModNpc) function GhostSoul:Update() self.npc:Fly() end function GhostSoul:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 end end return GhostSoul ================================================ FILE: npc_ai/GiantCursedSkull.json ================================================ { "GiantCursedSkull": { "script": { "path": "GiantCursedSkull.lua" } } } ================================================ FILE: npc_ai/GiantCursedSkull.lua ================================================ ---@class TC.GiantCursedSkull:ModNpc local GiantCursedSkull = class("GiantCursedSkull", ModNpc) local ST_READY = 0 local ST_DASH = 1 function GiantCursedSkull:Init() self.facingAngle = 0 end function GiantCursedSkull:Update() local npc = self.npc local flyOnly = true local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 340 then flyOnly = false if npc.state == ST_READY then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.1) npc.stateTimer = npc.stateTimer + 1 local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) if npc.stateTimer >= 32 then npc.speedX = npc.maxSpeed * math.cos(angle) * 2 npc.speedY = npc.maxSpeed * math.sin(angle) * 2 self.facingAngle = angle npc.state = ST_DASH npc.stateTimer = 0 else self.facingAngle = self.facingAngle + Utils.FixAngle(angle - self.facingAngle) * 0.1 end elseif npc.state == ST_DASH then npc.maxSpeed = 3 npc:Fly(true, 0.1, true) npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer >= 128 then npc.state = ST_READY npc.stateTimer = 0 end end end end if flyOnly then npc.maxSpeed = 1.25 if playerTarget ~= nil then self.facingAngle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) else self.facingAngle = npc.speedAngle end npc.state = ST_READY npc.stateTimer = 0 npc:Fly(true, 0.1, true) end if npc.speedX > 0 then npc.direction = true elseif npc.speedX < 0 then npc.direction = false end if npc.tickTime % 8 == 0 then EffectUtils.Create(Reg.EffectID("flame_star"), npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1)) EffectUtils.Create(Reg.EffectID("flame_star"), npc.randX, npc.randY, Utils.RandSym(1), -Utils.RandDouble(2), 0, Utils.RandDoubleArea(0.5, 0.5)) end end function GiantCursedSkull:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 3 end return GiantCursedSkull ================================================ FILE: npc_ai/GrimReaper.json ================================================ { "GrimReaper": { "script": { "path": "GrimReaper.lua" } } } ================================================ FILE: npc_ai/GrimReaper.lua ================================================ ---@class TC.GrimReaper:ModNpc local GrimReaper = class("GrimReaper", ModNpc) local ST_NORMAL = 0 local ST_FIRING = 1 local SHOOT_TIMES = 3 function GrimReaper:Init() self.shootTimes = 0 end function GrimReaper:Update() local npc = self.npc npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.1) local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end if npc.state == ST_NORMAL then npc.stateTimer = npc.stateTimer + 1 if self.shootTimes < SHOOT_TIMES and npc.stateTimer > 64 then npc.stateTimer = 0 npc.state = ST_FIRING self.shootTimes = self.shootTimes + 1 if playerTarget ~= nil then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("shulker_bullet"), npc.centerX, npc.centerY, 2 * math.cos(angle), 2 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end if npc.speedY > 6 or (self.shootTimes >= SHOOT_TIMES and npc.stateTimer > 64) then npc.state = 0 self.shootTimes = 0 npc.stateTimer = 0 local currentX = npc.x local currentY = npc.y local teleportSuccess = npc:RandomTeleport(32) if teleportSuccess then local e_ender_flash = Reg.EffectID("ender_flash") for i = 1, 16 do EffectUtils.Create(e_ender_flash, currentX + Utils.RandInt(npc.width), currentY + Utils.RandInt(npc.height), Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end for i = 1, 16 do EffectUtils.Create(e_ender_flash, npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("portal"), npc.centerXi, npc.centerYi) end end elseif npc.state == ST_FIRING then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = ST_NORMAL end end end function GrimReaper:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.speedX / 8 if npc.state == ST_NORMAL then npc.spriteRect.x = 0 elseif npc.state == ST_FIRING then npc.spriteRect.x = npc.spriteDefaultWidth end end return GrimReaper ================================================ FILE: npc_ai/Guardian.json ================================================ { "Guardian": { "script": { "path": "Guardian.lua" } } } ================================================ FILE: npc_ai/Guardian.lua ================================================ ---@type ModNpc local Guardian = class("Guardian", ModNpc) local ST_NORMAL = 0 local ST_ANGRY = 1 local ST_SHOOTING = 2 function Guardian:Update() local npc = self.npc npc:Swim() local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 360 then if npc.state == ST_NORMAL then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = ST_ANGRY end elseif npc.state == ST_ANGRY then npc.direction = (playerTarget.centerX > npc.centerX) npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 64 then npc.stateTimer = 0 npc.state = ST_SHOOTING end elseif npc.state == ST_SHOOTING then npc.direction = (playerTarget.centerX > npc.centerX) local shootAngle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) if npc.tickTime % 16 == 0 then local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("bullet_laser"), npc.centerX, npc.centerY, 9 * math.cos(shootAngle), 9 * math.sin(shootAngle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("rifle_fire"), npc.centerXi, npc.centerYi) end npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 100 then npc.stateTimer = 0 npc.state = ST_NORMAL end end else npc.stateTimer = 0 npc.state = ST_NORMAL end else npc.stateTimer = 0 npc.state = ST_NORMAL end end function Guardian:OnDraw() local npc = self.npc npc.spriteOffsetX = 0 npc.spriteOffsetY = 0 if npc.state == ST_ANGRY then local rate = Utils.SinValue(npc.tickTime, 16) local scaleRate = 1.05 + rate * 0.05 npc.spriteEx.scaleRateX = scaleRate npc.spriteEx.scaleRateY = scaleRate npc.spriteOffsetX = -(scaleRate - 1) * npc.spriteDefaultWidth / 2 npc.spriteOffsetY = -(scaleRate - 1) * npc.spriteDefaultHeight / 2 end end return Guardian ================================================ FILE: npc_ai/HellDestroyer.lua ================================================ ---@class TC.HellDestroyer:TC.BaseSnake local HellDestroyer = class("HellDestroyer", require("BaseSnake")) local PhysicsUtil = require("util.PhysicsUtil") function HellDestroyer:Init() HellDestroyer.super.Init(self) self:SetSnakeData(24, Reg.NpcID("worm_body"), Reg.NpcID("worm_tail"), 72, 34, 48, Size.new(46, 52), Size.new(60, 64) ) self.npc.isAntiLava = true self:NotifyAllPlayer("nether_destroyer") end function HellDestroyer:Update() local npc = self.npc if NetMode.current == NetMode.Server then local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.speedX, npc.speedY = PhysicsUtil.SightChaseSpeed2D(npc.speedX, npc.speedY, 0.2, Utils.GetAngle(playerTarget.centerX - npc.centerX, playerTarget.centerY - npc.centerY), 8) npc.speedX = npc.speedX + Utils.RandSym(0.5) npc.speedY = npc.speedY + Utils.RandSym(0.5) end local makeShoot = false if npc.tickTime > 0 then if npc.health > npc.maxHealth / 3 then makeShoot = npc.tickTime % 512 == 0 else makeShoot = npc.tickTime % 256 == 0 end end if makeShoot then local cxi, cyi = npc.centerXi, npc.centerYi if not MapUtils.IsSolid(cxi, cyi) then NpcUtils.Create(Reg.NpcID("small_hell_eater"), npc.centerX, npc.centerY, Utils.RandSym(2), Utils.RandSym(2)) SoundUtils.PlaySound(Reg.SoundID("fireball"), cxi, cyi) end end makeShoot = false if npc.tickTime > 0 then if npc.health > npc.maxHealth / 2 then makeShoot = (npc.tickTime + 64) % 1024 == 0 else makeShoot = (npc.tickTime + 64) % 512 == 0 end end if makeShoot then local cxi, cyi = npc.centerXi, npc.centerYi NpcUtils.Create(Reg.NpcID("small_fire_hell_eater"), npc.centerX, npc.centerY, Utils.RandSym(2), Utils.RandSym(2)) SoundUtils.PlaySound(Reg.SoundID("fireball"), cxi, cyi) end end end function HellDestroyer:OnKilled() HellDestroyer.super.OnKilled(self) self:NotifyAllPlayer("nether_destroyer_killed") end function HellDestroyer:NotifyAllPlayer(advancementIDName) local advancementID = Reg.AdvancementID(advancementIDName) local players = PlayerUtils.SearchByCircle(self.npc.centerX, self.npc.centerY, 300 * 16) ---@param player Player for _, player in each(players) do player:FinishAdvancement(advancementID) end end return HellDestroyer ================================================ FILE: npc_ai/HellDestroyer_Head.json ================================================ { "HellDestroyer_Head": { "script": { "path": "HellDestroyer.lua" } } } ================================================ FILE: npc_ai/HellEater.json ================================================ { "HellEater": { "script": { "path": "HellEater.lua" } } } ================================================ FILE: npc_ai/HellEater.lua ================================================ ---@class TC.HellEater:ModNpc local HellEater = class("HellEater", ModNpc) local ST_READY = 0 local ST_DASH = 1 function HellEater:Init() self.dashTimes = 0 self.dashAngle = 0 self.DASH_ANGLE = self.npc.dataWatcher:AddDouble(0.0) end function HellEater:Update() self:RecvSync() local npc = self.npc local flyOnly = true local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 640 then flyOnly = false if npc.state == ST_READY then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.1) npc.stateTimer = npc.stateTimer + 1 local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) if npc.stateTimer >= 64 then npc.speedX = npc.maxSpeed * math.cos(angle) * 2 npc.speedY = npc.maxSpeed * math.sin(angle) * 2 self.dashAngle = angle npc.state = ST_DASH npc.stateTimer = 0 self.dashTimes = self.dashTimes + 1 else self.dashAngle = self.dashAngle + Utils.FixAngle(angle - self.dashAngle) * 0.1 end elseif npc.state == ST_DASH then -- self.dashAngle = self.speedAngle npc.stateTimer = npc.stateTimer + 1 if self.dashTimes < 4 and npc.stateTimer >= 32 then npc.state = ST_READY npc.stateTimer = 0 end if npc.tickTime % 2 == 0 then EffectUtils.Create(Reg.EffectID("fire_flame"), npc.randX, npc.randY, Utils.RandSym(0.15), Utils.RandSym(0.15), 1, Utils.RandDoubleArea(0.5, 0.25), Utils.RandDoubleArea(0.75, 0.25)) end end end end if flyOnly then self.dashAngle = npc.speedAngle npc.state = ST_READY npc.stateTimer = 0 self.dashTimes = 0 npc.maxSpeed = npc.maxSpeed * 4 npc:Fly(false, 0.1, true) end self:SendSync() end function HellEater:OnTileCollide(oldSpeedX, oldSpeedY) local npc = self.npc npc:Kill() MiscUtils.CreateExplosion(npc.centerXi, npc.centerYi, 6, false, true, false) EffectUtils.CreateExplosion(npc.centerX, npc.centerY) end function HellEater:OnDraw() self.npc.spriteEx.angle = self.dashAngle end function HellEater:SendSync() if NetMode.current == NetMode.Server then self.npc.dataWatcher:UpdateDouble(self.DASH_ANGLE, self.dashAngle) end end function HellEater:RecvSync() if NetMode.current == NetMode.Client then self.dashAngle = self.npc.dataWatcher:GetDouble(self.DASH_ANGLE) end end return HellEater ================================================ FILE: npc_ai/HumanFighter.json ================================================ { "HumanFighter": { "script": { "path": "HumanFighter.lua" } } } ================================================ FILE: npc_ai/HumanFighter.lua ================================================ ---@class TC.HumanFighter:TC.Fighter local HumanFighter = class("HumanFighter", require("Fighter")) local NpcHumanBoneInfo = require("bone2d.NpcHumanBoneInfo") local cameraInGameInstance = require("client.CameraInGame").getInstance() function HumanFighter:Init() local npc = self.npc if self.boneSizeIndex == nil then self.boneSizeIndex = 0 end self.bone = NpcHumanBoneInfo.getInstance():load(npc.id, npc.texture, self.boneSizeIndex) self.itemSlotHeld = nil ---@type Slot self.isUsingItemForAnimation = false self.normalActionStyle = "NORMAL" self.isHeadLook = false self.headLookAngle = 0 self.headLookDenominator = 1.0 self.isBackHandLook = false self.backHandLookAngle = 0 self.isBackHandLookAngleSameDirection = false self.isFrontHandLook = false self.frontHandLookAngle = 0 self.isFrontHandLookAngleSameDirection = false self.isFrontLegOverwrite = false self.frontLegOverwriteAngle = 0 self.isFrontLegLookAngleSameDirection = false self.isBackLegOverwrite = false self.backLegOverwriteAngle = 0 self.isBackLegLookAngleSameDirection = false self.backItemCache = {} end function HumanFighter:PostUpdate() self:UpdateBone() end function HumanFighter:UpdateBone() local npc = self.npc self.bone.joints.position = Vector2.new(npc.centerX, npc.bottomY) if self.itemSlotHeld then NpcHumanBoneInfo.checkHandItem(self:GetHeldItemJoint(), self.itemSlotHeld, self.backItemCache) end local animator = self.bone.animator animator:setBool("OnGround", npc.stand) local speedRate = 0 if npc.maxSpeed > 0 then speedRate = math.abs(npc.speedX) / npc.maxSpeed end speedRate = math.min(math.max(speedRate, 0), 1) animator:setFloat("Speed", speedRate) self.bone.joints.flip = not npc.direction self.bone.joints.scale = Vector2.new(1, 1) self.bone:update() self:UpdateSpecialAnimation() end function HumanFighter:UpdateSpecialAnimation() local hasJointChanged = false if self.isHeadLook and self.headLookDenominator > 0 then hasJointChanged = true local head = self.bone.joints:getJoint("base.body.head") head.angle = self:GetLookAngleInFacingDirection(self.headLookAngle) / self.headLookDenominator end if self.isBackHandLook then hasJointChanged = true local arm = self.bone.joints:getJoint("base.body.back_arm") if self.isBackHandLookAngleSameDirection then arm.angle = self.backHandLookAngle - math.pi * 0.5 else arm.angle = self:GetLookAngleInFacingDirection(self.backHandLookAngle) - math.pi * 0.5 end end if self.isFrontHandLook then hasJointChanged = true local arm = self.bone.joints:getJoint("base.body.front_arm") if self.isFrontHandLookAngleSameDirection then arm.angle = self.frontHandLookAngle - math.pi * 0.5 else arm.angle = self:GetLookAngleInFacingDirection(self.frontHandLookAngle) - math.pi * 0.5 end end if self.isFrontLegOverwrite then hasJointChanged = true local leg = self.bone.joints:getJoint("base.body.front_leg") if self.isFrontLegLookAngleSameDirection then leg.angle = self.frontLegOverwriteAngle else leg.angle = self:GetLookAngleInFacingDirection(self.frontLegOverwriteAngle) end end if self.isBackLegOverwrite then hasJointChanged = true local leg = self.bone.joints:getJoint("base.body.back_leg") if self.isBackLegLookAngleSameDirection then leg.angle = self.backLegOverwriteAngle else leg.angle = self:GetLookAngleInFacingDirection(self.backLegOverwriteAngle) end end if hasJointChanged then self.bone:update(false) end if self.isUsingItemForAnimation then self.isUsingItemForAnimation = false if self.itemSlotHeld and self.itemSlotHeld.hasStack then local stack = self.itemSlotHeld:GetStack() stack:RunOnUsedByNpcEvent(self.npc) local item = stack:GetItem() if item.useSoundGroupID > 0 then SoundUtils.PlaySoundGroup(item.useSoundGroupID, self.npc.centerXi, self.npc.centerYi) end if item.useSoundID > 0 then SoundUtils.PlaySound(item.useSoundID, self.npc.centerXi, self.npc.centerYi) end end end end function HumanFighter:GetLookAngleInFacingDirection(rawAngle) local lookAngle = rawAngle if not (lookAngle > -math.pi * 0.5 and lookAngle < math.pi * 0.5) then lookAngle = math.pi - lookAngle lookAngle = Utils.FixAngle(lookAngle) end return lookAngle end function HumanFighter:GetHeldItemJoint() return NpcHumanBoneInfo.getItemJoint(self.bone, true) end function HumanFighter:OnRender() self.bone.joints:render(cameraInGameInstance.camera) end function HumanFighter:DoExternArmsAnimation(amplitude, period) if amplitude == nil then amplitude = 0.25 end if period == nil then period = 16 end amplitude = math.max(amplitude, 0.0) period = math.max(period, 1) local npc = self.npc self.frontHandLookAngle = math.cos(npc.tickTime / period) * amplitude self.backHandLookAngle = math.sin(npc.tickTime / period) * amplitude end return HumanFighter ================================================ FILE: npc_ai/IceElf.json ================================================ { "IceElf": { "script": { "path": "IceElf.lua" } } } ================================================ FILE: npc_ai/IceElf.lua ================================================ ---@type ModNpc local IceElf = class("IceElf", ModNpc) local e_liquid_paticular = Reg.EffectID("liquid_paticular") function IceElf:Update() local npc = self.npc npc:Fly() if Utils.RandTry(16) then EffectUtils.Create(e_liquid_paticular, npc.randX, npc.randY, Utils.RandSym(1.0), Utils.RandSym(1.0)) end end function IceElf:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 else npc.spriteEx.angle = 0 end end return IceElf ================================================ FILE: npc_ai/JungleSnake.lua ================================================ ---@class TC.JungleSnake:TC.BaseSnake local JungleSnake = class("JungleSnake", require("BaseSnake")) function JungleSnake:Init() JungleSnake.super.Init(self) self:SetSnakeData(5, Reg.NpcID("vine_man_eater_body"), Reg.NpcID("vine_man_eater_tail"), 34, 36, 46, Size.new(44, 32), Size.new(54, 40) ) end function JungleSnake:Update() if NetMode.current == NetMode.Server then return end end return JungleSnake ================================================ FILE: npc_ai/JungleSnake_Head.json ================================================ { "JungleSnake_Head": { "script": { "path": "JungleSnake.lua" } } } ================================================ FILE: npc_ai/LargeBat.json ================================================ { "LargeBat": { "script": { "path": "LargeBat.lua" } } } ================================================ FILE: npc_ai/LargeBat.lua ================================================ ---@class TC.LargeBat:ModNpc local LargeBat = class("LargeBat", ModNpc) function LargeBat:Update() local npc = self.npc if npc.state == 0 then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 64 then npc.stateTimer = 0 npc.state = 1 end npc:Fly() elseif npc.state == 1 then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.35) npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 64 then npc.stateTimer = 0 npc.state = 0 local ba = Utils.RandDouble(math.pi / 2) for i = 0, 3 do local angle = math.pi * 2 / 3 * i + ba local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("lighting_bullet_blue"), npc.centerX, npc.centerY, 3 * math.cos(angle), 3 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true end end end local effect = EffectUtils.Create(Reg.EffectID("chip"), self.npc.randX, self.npc.bottomY + Utils.RandSym(12), Utils.RandSym(0.1), Utils.RandDoubleArea(1, 1), Utils.RandSym(1), 1.0, 0.8, Color.new(200, 200, 200)) effect:SetDisappearTime(30) LightingUtils.Add(npc.centerXi, npc.centerYi, 32) end function LargeBat:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 else npc.spriteEx.angle = 0 end end return LargeBat ================================================ FILE: npc_ai/LargeSpider.json ================================================ { "LargeSpider": { "script": { "path": "LargeSpider.lua" } } } ================================================ FILE: npc_ai/LargeSpider.lua ================================================ ---@class TC.LargeSpider:ModNpc local LargeSpider = class("LargeSpider", ModNpc) local State = { NORMAL = 0, READY_TO_JUMP = 1, FALLEN = 2, } function LargeSpider:Update() local npc = self.npc if not npc.stand then npc.state = State.FALLEN if npc.direction then npc.speedX = npc.speedX + 0.1 else npc.speedX = npc.speedX - 0.1 end npc.speedX = math.max(npc.speedX, -npc.maxSpeed) npc.speedX = math.min(npc.speedX, npc.maxSpeed) else local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.1) if npc.state == State.NORMAL then npc.stateTimer = npc.stateTimer + 1 -- if Utils.RandTry(32) then if npc.stateTimer > 8 then npc.stateTimer = 0 npc.state = State.READY_TO_JUMP end elseif npc.state == State.READY_TO_JUMP then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = State.FALLEN if npc.direction then npc.speedX = Utils.RandDoubleArea(npc.maxSpeed / 2, npc.maxSpeed / 2) else npc.speedX = -Utils.RandDoubleArea(npc.maxSpeed / 2, npc.maxSpeed / 2) end npc.speedY = -Utils.RandDoubleArea(8, 4) end elseif npc.state == State.FALLEN then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = State.NORMAL end end else npc.stateTimer = 0 npc.state = State.NORMAL end end if npc.stand then npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.8) end end function LargeSpider:OnDraw() local npc = self.npc npc.frameTickTime = 0 if not npc.stand then npc.spriteRect.x = npc.spriteDefaultWidth else if npc.state == State.NORMAL then npc.spriteRect.x = 0 else npc.spriteRect.x = npc.spriteDefaultWidth end end end return LargeSpider ================================================ FILE: npc_ai/MagmaBirdo.json ================================================ { "MagmaBirdo": { "script": { "path": "MagmaBirdo.lua" } } } ================================================ FILE: npc_ai/MagmaBirdo.lua ================================================ ---@type ModNpc local MagmaBirdo = class("MagmaBirdo", ModNpc) local ST_NORMAL = 0 local ST_READY_TO_FIRE = 1 local ST_FIRING = 2 function MagmaBirdo:Update() local npc = self.npc if npc.state == ST_NORMAL then local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 240 then if Utils.RandTry(64) then npc.state = ST_READY_TO_FIRE end end end elseif npc.state == ST_READY_TO_FIRE then npc.maxSpeed = npc.maxSpeed * 0.5 npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 128 then npc.stateTimer = 0 npc.state = ST_FIRING end elseif npc.state == ST_FIRING then npc.maxSpeed = npc.maxSpeed * 0.25 if npc.tickTime % 8 == 0 then local angle = npc.speedAngle local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("gun_fire"), npc.centerX + math.cos(angle) * 20, npc.centerY + math.sin(angle) * 20, 10 * math.cos(angle), 10 * math.sin(angle), Attack.new(npc.baseAttack.attack * 0.4, 0, 0)) proj.isCheckPlayer = true end npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 128 then npc.stateTimer = 0 npc.state = ST_NORMAL end end npc:Fly() end function MagmaBirdo:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 end end return MagmaBirdo ================================================ FILE: npc_ai/MagmaElf.json ================================================ { "MagmaElf": { "script": { "path": "MagmaElf.lua" } } } ================================================ FILE: npc_ai/MagmaElf.lua ================================================ ---@type ModNpc local MagmaElf = class("MagmaElf", ModNpc) function MagmaElf:Update() local npc = self.npc npc:Walk() if npc.inLiquid then -- in lava npc.gravity = 0 if npc.speedY > 0 then npc.speedY = math.min(npc.speedY + 0.1, npc.maxSpeed) else npc.speedY = math.max(npc.speedY - 0.1, -npc.maxSpeed) end elseif not npc.inLiquid and npc.oldInLiquid then -- just jump out of lava if npc.speedY > -npc.jumpForce * 1.5 then npc.speedY = -npc.jumpForce * 1.5 end else -- in air npc.gravity = npc.gravity * 0.25 if npc.tickTime % 16 == 0 then EffectUtils.Create(Reg.EffectID("fire_flame"), npc.randX, npc.randY, Utils.RandSym(0.25), Utils.RandSym(0.25), 0, Utils.RandDoubleArea(0.5, 0.5)) end end LightingUtils.Add(npc.centerXi, npc.centerYi, 24, 12, 0, 0) end function MagmaElf:OnTileCollide(oldSpeedX, oldSpeedY) local npc = self.npc if npc.stand then npc.speedY = -npc.jumpForce end end function MagmaElf:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.speedAngle npc.spriteEx.flipHorizontal = false end return MagmaElf ================================================ FILE: npc_ai/MagmaSlime.json ================================================ { "MagmaSlime": { "script": { "path": "MagmaSlime.lua" } } } ================================================ FILE: npc_ai/MagmaSlime.lua ================================================ ---@type ModNpc local MagmaSlime = class("MagmaSlime", require("Slime")) function MagmaSlime:Update() MagmaSlime.super.Update(self) local npc = self.npc if npc.tickTime % 32 == 0 then EffectUtils.Create(Reg.EffectID("fire_flame"), npc.randX, npc.y, Utils.RandSym(1), -Utils.RandDouble(2), 0, Utils.RandDoubleArea(0.75, 0.25)) end LightingUtils.Add(npc.centerXi, npc.centerYi, 24, 12, 0, 0) end return MagmaSlime ================================================ FILE: npc_ai/ManEater.json ================================================ { "ManEater": { "script": { "path": "ManEater.lua" } } } ================================================ FILE: npc_ai/ManEater.lua ================================================ ---@type ModNpc local ManEater = class("ManEater", ModNpc) local ST_READY = 0 local ST_DASH = 1 function ManEater:Init() self.dashAngle = 0.0 self.DASH_ANGLE = self.npc.dataWatcher:AddDouble(0.0) end function ManEater:Update() self:RecvSync() local npc = self.npc local flyOnly = true local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 440 then flyOnly = false if npc.state == ST_READY then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.1) npc.stateTimer = npc.stateTimer + 1 local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) if npc.stateTimer >= 64 then npc.speedX = npc.maxSpeed * math.cos(angle) * 2 npc.speedY = npc.maxSpeed * math.sin(angle) * 2 self.dashAngle = angle npc.state = ST_DASH npc.stateTimer = 0 else self.dashAngle = self.dashAngle + Utils.FixAngle(angle - self.dashAngle) * 0.1 end elseif npc.state == ST_DASH then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer >= 64 then npc.state = ST_READY npc.stateTimer = 0 end if npc.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("liquid_paticular"), npc.randX, npc.randY, Utils.RandSym(0.25), Utils.RandSym(0.25), 1, Utils.RandDoubleArea(1.0, 0.5), Utils.RandDoubleArea(0.75, 0.25), Color.new(255, 100, 100) ) end end end end if flyOnly then self.dashAngle = npc.speedAngle npc.state = ST_READY npc.stateTimer = 0 npc:Fly(true, 0.1, true) end self:SendSync() end function ManEater:OnDraw() local npc = self.npc npc.spriteEx.angle = self.dashAngle end function ManEater:SendSync() if NetMode.current == NetMode.Server then self.npc.dataWatcher:UpdateDouble(self.DASH_ANGLE, self.dashAngle) end end function ManEater:RecvSync() if NetMode.current == NetMode.Client then self.dashAngle = self.npc.dataWatcher:GetDouble(self.DASH_ANGLE) end end return ManEater ================================================ FILE: npc_ai/Meteor.json ================================================ { "Meteor": { "script": { "path": "Meteor.lua" } } } ================================================ FILE: npc_ai/Meteor.lua ================================================ ---@type ModNpc local Meteor = class("Meteor", ModNpc) function Meteor:Update() self.npc:Fly() end function Meteor:OnDraw() self.npc.spriteEx.angle = self.npc.spriteEx.angle + 0.1 end function Meteor:OnTileCollide(oldSpeedX, oldSpeedY) local npc = self.npc if npc.isCollisionLeft then npc.speedX = npc.maxSpeed elseif npc.isCollisionRight then npc.speedX = -npc.maxSpeed elseif npc.stand then npc.speedY = -npc.maxSpeed elseif npc.isCollisionTop then npc.speedY = npc.maxSpeed end local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 360 then npc:Kill() MiscUtils.CreateExplosion(npc.centerXi, npc.centerYi, 4, true, true) EffectUtils.CreateExplosion(npc.centerX, npc.centerY) end end end return Meteor ================================================ FILE: npc_ai/MiniGhast.json ================================================ { "MiniGhast": { "script": { "path": "MiniGhast.lua" } } } ================================================ FILE: npc_ai/MiniGhast.lua ================================================ ---@class TC.MiniGhast:ModNpc local MiniGhast = class("MiniGhast", ModNpc) local ST_NORMAL = 0 local ST_FIRING = 1 function MiniGhast:Update() local npc = self.npc npc:TryMakeSound(1000) npc:Fly(false) local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) if npc.state == ST_NORMAL then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 256 then npc.stateTimer = 0 local shootX = 0 local shootY = npc.centerY if npc.direction then shootX = npc.rightX - 16 else shootX = npc.x + 16 end end elseif npc.state == ST_FIRING then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 32 then npc.stateTimer = 0 npc.state = ST_NORMAL end end else npc.stateTimer = 0 npc.state = ST_NORMAL end npc.color = Color.new(255, 255, 255, 180) end function MiniGhast:OnDraw() local npc = self.npc if npc.state == ST_FIRING then npc.spriteRect.x = npc.spriteDefaultWidth end if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 8 end end function MiniGhast:OnHit() local npc = self.npc -- Let ghost gunners around shoot the players! local npcList = NpcUtils.SearchByCircle(npc.centerX, npc.centerY, 60 * 16) ---@param n Npc for _, n in each(npcList) do local modNpc = n:GetModNpc() if modNpc ~= nil and modNpc.isGhostGuard and modNpc.ghostAllowToShoot == false then SoundUtils.PlaySound(Reg.SoundID("ghast_charge"), n.centerXi, n.centerYi) modNpc.ghostAllowToShoot = true print("TRIGGER GHOST GUNNER") end end end return MiniGhast ================================================ FILE: npc_ai/Paimon.json ================================================ { "Paimon": { "script": { "path": "Paimon.lua" } } } ================================================ FILE: npc_ai/Paimon.lua ================================================ ---@class TC.Paimon:ModNpc local Paimon = class("Paimon", ModNpc) function Paimon:Init() self.npc.noHurt = true self.npc.noCollisionByWeapon = true end function Paimon:Update() local npc = self.npc ---@type Player local target = PlayerUtils.SearchNearestPlayer(npc.centerX, npc.centerY, 1000) if target ~= nil then if npc:GetDistance(target.centerX, target.centerY) < 128 then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.2) npc.speedY = npc.speedY + math.sin(npc.tickTime / 8) / 4 npc.speedX = npc.speedX + math.cos(npc.tickTime / 18) / 6 else local targetAngle = npc:GetAngleTo(target.centerX, target.centerY) npc.speedX, npc.speedY = Utils.ForceSpeed2D(npc.speedX, npc.speedY, 0.2, targetAngle, npc.maxSpeed) end npc.direction = npc.centerX < target.centerX else npc.direction = npc.speedX > 0 end end function Paimon:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 4 end end return Paimon ================================================ FILE: npc_ai/Phantom.json ================================================ { "Phantom": { "script": { "path": "Phantom.lua" } } } ================================================ FILE: npc_ai/Phantom.lua ================================================ ---@type ModNpc local Phantom = class("Phantom", ModNpc) function Phantom:Update() local npc = self.npc npc:Fly() if npc.speedY >= 0 then local b1 = Utils.RandTry(8) local b2 = Utils.RandTry(8) if b1 or b2 then local angle = npc.speedX / npc.maxSpeed / 2 local ex = 32 * math.cos(angle) local ey = 32 * math.sin(angle) if b1 then EffectUtils.Create(Reg.EffectID("ender_flash"), npc.centerX + ex, npc.centerY + ey, Utils.RandSym(0.25), Utils.RandSym(0.25), 0, Utils.RandDoubleArea(1, 1)) end if b2 then EffectUtils.Create(Reg.EffectID("ender_flash"), npc.centerX - ex, npc.centerY - ey, Utils.RandSym(0.25), Utils.RandSym(0.25), 0, Utils.RandDoubleArea(1, 1)) end end else if Utils.RandTry(4) then EffectUtils.Create(Reg.EffectID("ender_flash"), npc.centerX + Utils.RandSym(8), npc.centerY + 8, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1)) end end end function Phantom:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 end local noChangeFrame = false if npc.speedY >= 0 then if npc.frameTickTime <= 1 then noChangeFrame = true end end if npc.frameTickTime > npc.frames * npc.frameSpeed then noChangeFrame = true end if noChangeFrame then npc.frameTickTime = 0 end end return Phantom ================================================ FILE: npc_ai/Pufferfish.json ================================================ { "Pufferfish": { "script": { "path": "Pufferfish.lua" } } } ================================================ FILE: npc_ai/Pufferfish.lua ================================================ ---@type ModNpc local Pufferfish = class("Pufferfish", ModNpc) local ST_NORMAL = 0 local ST_EXPANDING = 1 function Pufferfish:Update() local npc = self.npc npc:Swim() npc.state = ST_NORMAL local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 128 then npc.state = ST_EXPANDING end end end function Pufferfish:OnDraw() local npc = self.npc local scaleRate = npc.spriteEx.scaleRateX if npc.state == ST_EXPANDING then scaleRate = math.min(scaleRate + 0.01, 2) else scaleRate = math.max(scaleRate - 0.01, 1) end npc.spriteEx.scaleRateX = scaleRate npc.spriteEx.scaleRateY = scaleRate if scaleRate > 1 then npc.spriteRect.x = npc.spriteRect.x + npc.spriteDefaultWidth npc.spriteOffsetX = -(scaleRate - 1)* npc.spriteDefaultWidth / 2 npc.spriteOffsetY = -(scaleRate - 1)* npc.spriteDefaultHeight / 2 end end return Pufferfish ================================================ FILE: npc_ai/RaggedMage.json ================================================ { "RaggedMage": { "script": { "path": "RaggedMage.lua" } } } ================================================ FILE: npc_ai/RaggedMage.lua ================================================ ---@class TC.RaggedMage:ModNpc local RaggedMage = class("RaggedMage", ModNpc) local ST_NORMAL = 0 local ST_FIRING = 1 local SHOOT_TIMES = 3 function RaggedMage:Init() self.shootTimes = 0 end function RaggedMage:Update() local npc = self.npc npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.1) local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end if npc.state == ST_NORMAL then npc.stateTimer = npc.stateTimer + 1 if self.shootTimes < SHOOT_TIMES and npc.stateTimer > 64 then npc.stateTimer = 0 npc.state = ST_FIRING self.shootTimes = self.shootTimes + 1 if playerTarget ~= nil then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("lighting_bullet_red_invert2"), npc.centerX, npc.centerY, 2 * math.cos(angle), 2 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end if npc.speedY > 6 or (self.shootTimes >= SHOOT_TIMES and npc.stateTimer > 64) then npc.state = 0 self.shootTimes = 0 npc.stateTimer = 0 local currentX = npc.x local currentY = npc.y local teleportSuccess = npc:RandomTeleport(32) if teleportSuccess then local e_ender_flash = Reg.EffectID("ender_flash") for i = 1, 16 do EffectUtils.Create(e_ender_flash, currentX + Utils.RandInt(npc.width), currentY + Utils.RandInt(npc.height), Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end for i = 1, 16 do EffectUtils.Create(e_ender_flash, npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("portal"), npc.centerXi, npc.centerYi) end end elseif npc.state == ST_FIRING then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = ST_NORMAL end end end function RaggedMage:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.speedX / 8 if npc.state == ST_NORMAL then npc.spriteRect.x = 0 elseif npc.state == ST_FIRING then npc.spriteRect.x = npc.spriteDefaultWidth end end return RaggedMage ================================================ FILE: npc_ai/RedMage.json ================================================ { "RedMage": { "script": { "path": "RedMage.lua" } } } ================================================ FILE: npc_ai/RedMage.lua ================================================ ---@class TC.RedMage:ModNpc local RedMage = class("RedMage", ModNpc) local ST_NORMAL = 0 local ST_FIRING = 1 local SHOOT_TIMES = 3 function RedMage:Init() self.shootTimes = 0 end function RedMage:Update() local npc = self.npc npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.1) local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end if npc.state == ST_NORMAL then npc.stateTimer = npc.stateTimer + 1 if self.shootTimes < SHOOT_TIMES and npc.stateTimer > 64 then npc.stateTimer = 0 npc.state = ST_FIRING self.shootTimes = self.shootTimes + 1 if playerTarget ~= nil then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("shulker_bullet"), npc.centerX, npc.centerY, 2 * math.cos(angle), 2 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end if npc.speedY > 6 or (self.shootTimes >= SHOOT_TIMES and npc.stateTimer > 64) then npc.state = 0 self.shootTimes = 0 npc.stateTimer = 0 local currentX = npc.x local currentY = npc.y local teleportSuccess = npc:RandomTeleport(32) if teleportSuccess then local e_ender_flash = Reg.EffectID("ender_flash") for i = 1, 16 do EffectUtils.Create(e_ender_flash, currentX + Utils.RandInt(npc.width), currentY + Utils.RandInt(npc.height), Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end for i = 1, 16 do EffectUtils.Create(e_ender_flash, npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("portal"), npc.centerXi, npc.centerYi) end end elseif npc.state == ST_FIRING then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 16 then npc.stateTimer = 0 npc.state = ST_NORMAL end end end function RedMage:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.speedX / 8 if npc.state == ST_NORMAL then npc.spriteRect.x = 0 elseif npc.state == ST_FIRING then npc.spriteRect.x = npc.spriteDefaultWidth end end return RedMage ================================================ FILE: npc_ai/RedPhantom.json ================================================ { "RedPhantom": { "script": { "path": "RedPhantom.lua" } } } ================================================ FILE: npc_ai/RedPhantom.lua ================================================ ---@class TC.RedPhantom:ModNpc local RedPhantom = class("RedPhantom", ModNpc) function RedPhantom:Update() local npc = self.npc npc:Fly() if npc.speedY >= 0 then local b1 = Utils.RandTry(8) local b2 = Utils.RandTry(8) if b1 or b2 then local angle = npc.speedX / npc.maxSpeed / 2 local ex = 32 * math.cos(angle) local ey = 32 * math.sin(angle) if b1 then EffectUtils.Create(Reg.EffectID("ender_flash"), npc.centerX + ex, npc.centerY + ey, Utils.RandSym(0.25), Utils.RandSym(0.25), 0, Utils.RandDoubleArea(1, 1)) end if b2 then EffectUtils.Create(Reg.EffectID("ender_flash"), npc.centerX - ex, npc.centerY - ey, Utils.RandSym(0.25), Utils.RandSym(0.25), 0, Utils.RandDoubleArea(1, 1)) end end else if Utils.RandTry(4) then EffectUtils.Create(Reg.EffectID("ender_flash"), npc.centerX + Utils.RandSym(8), npc.centerY + 8, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1)) end end end function RedPhantom:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 end local noChangeFrame = false if npc.speedY >= 0 then if npc.frameTickTime <= 1 then noChangeFrame = true end end if npc.frameTickTime > npc.frames * npc.frameSpeed then noChangeFrame = true end if noChangeFrame then npc.frameTickTime = 0 end end return RedPhantom ================================================ FILE: npc_ai/RockMan.json ================================================ { "RockMan": { "script": { "path": "RockMan.lua" } } } ================================================ FILE: npc_ai/RockMan.lua ================================================ ---@class TC.RockMan:TC.Archer local RockMan = class("RockMan", require("Archer")) function RockMan:Init() RockMan.super.Init(self) self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("soul_laserer"))) end return RockMan ================================================ FILE: npc_ai/RollingFireBall.json ================================================ { "RollingFireBall": { "script": { "path": "RollingFireBall.lua" } } } ================================================ FILE: npc_ai/RollingFireBall.lua ================================================ ---@class TC.RollingFireBall:ModNpc local RollingFireBall = class("RollingFireBall", ModNpc) function RollingFireBall:Update() self.npc:Fly() end function RollingFireBall:OnDraw() self.npc.spriteEx.angle = self.npc.spriteEx.angle + 0.1 end function RollingFireBall:OnTileCollide(oldSpeedX, oldSpeedY) local npc = self.npc if npc.isCollisionLeft then npc.speedX = npc.maxSpeed elseif npc.isCollisionRight then npc.speedX = -npc.maxSpeed elseif npc.stand then npc.speedY = -npc.maxSpeed elseif npc.isCollisionTop then npc.speedY = npc.maxSpeed end local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 360 then npc:Kill() MiscUtils.CreateExplosion(npc.centerXi, npc.centerYi, 4, true, true) EffectUtils.CreateExplosion(npc.centerX, npc.centerY) end end end return RollingFireBall ================================================ FILE: npc_ai/Sheep.json ================================================ { "Sheep": { "pAI": "Sheep_AI", "pDraw": "Sheep_Draw" } } ================================================ FILE: npc_ai/Shulker.json ================================================ { "Shulker": { "script": { "path": "Shulker.lua" } } } ================================================ FILE: npc_ai/Shulker.lua ================================================ ---@type ModNpc local Shulker = class("Shulker", ModNpc) local ST_NORMAL = 0 local ST_OPENING = 1 local ST_OPENED = 2 local ST_CLOSING = 3 function Shulker:Teleport() local npc = self.npc local currentX = npc.x local currentY = npc.y local teleportSuccess = npc:RandomTeleport(16, true) if teleportSuccess then for i = 1, 16 do EffectUtils.Create(Reg.EffectID("ender_flash"), currentX + Utils.RandInt(npc.width), currentY + Utils.RandInt(npc.height), Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end for i = 1, 16 do EffectUtils.Create(Reg.EffectID("ender_flash"), npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(1), 2) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("portal"), npc.centerXi, npc.centerYi) end end function Shulker:Update() local npc = self.npc npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.05) npc.speedY = Utils.SinValue(npc.tickTime, 128) local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end if npc.state == ST_NORMAL then if Utils.RandTry(128) then npc.stateTimer = 0 npc.state = ST_OPENING SoundUtils.PlaySound(Reg.SoundID("shulker_open"), npc.centerXi, npc.centerYi) end elseif npc.state == ST_OPENING then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer >= 32 then npc.stateTimer = 0 npc.state = ST_OPENED end elseif npc.state == ST_OPENED then if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 640 then if npc.tickTime % 128 == 0 then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("shulker_bullet"), npc.centerX, npc.centerY, 4 * math.cos(angle), 4 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end end npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer >= 256 then npc.stateTimer = 0 npc.state = ST_CLOSING SoundUtils.PlaySound(Reg.SoundID("shulker_close"), npc.centerXi, npc.centerYi) end elseif npc.state == ST_CLOSING then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer >= 32 then npc.stateTimer = 0 npc.state = ST_NORMAL end end if npc.tickTime % 128 == 0 then if Utils.RandTry(2) then self:Teleport() end end end function Shulker:OnHit() self:Teleport() end function Shulker:OnDraw() local npc = self.npc npc.spriteEx.angle = npc.speedY / 16 + npc.speedY / 8 if npc.state == ST_NORMAL then npc.frameTickTime = 0 elseif npc.state == ST_OPENING then elseif npc.state == ST_OPENED then npc.frameTickTime = (npc.frames - 1) * npc.frameSpeed elseif npc.state == ST_CLOSING then npc.frameTickTime = npc.frameTickTime - 2 end npc.frameTickTime = math.max(npc.frameTickTime, 0) npc.frameTickTime = math.min(npc.frameTickTime, (npc.frames - 1) * npc.frameSpeed) npc.spriteEx.x = npc.spriteDefaultWidth * npc.frameIndex end return Shulker ================================================ FILE: npc_ai/SkeletonAssaulter.json ================================================ { "SkeletonAssaulter": { "script": { "path": "SkeletonAssaulter.lua" } } } ================================================ FILE: npc_ai/SkeletonAssaulter.lua ================================================ ---@class TC.SkeletonAssaulter:TC.HumanFighter local SkeletonAssaulter = class("SkeletonAssaulter", require("HumanFighter")) local State = { NORMAL = 0, NO_MOVE = 1 } function SkeletonAssaulter:Init() SkeletonAssaulter.super.Init(self) self.inventory = Inventory.new(1) self.npc.dataWatcher:AddInventory(self.inventory) self.itemSlotHeld = self.inventory:GetSlot(0) self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("sniper"))) self.shootTimes = 0 end function SkeletonAssaulter:Update() local npc = self.npc npc.noMove = true local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) npc.state = State.NORMAL if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end self.isHeadLook = true self.headLookAngle = npc.watchAngle self.headLookDenominator = 2.0 self.isBackHandLook = true self.isFrontHandLook = true self.backHandLookAngle = npc.watchAngle self.frontHandLookAngle = npc.watchAngle npc.state = State.NORMAL if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 540 and self.shootTimes ~= 0 then npc.state = State.NO_MOVE end if distance < 540 then if npc.stand or npc.gravity == 0 then if (npc.tickTime % 64 == 0) then self.isUsingItemForAnimation = true self.shootTimes = self.shootTimes + 1 end end end end if npc.state == State.NORMAL then npc.noMove = false elseif npc.state == State.NO_MOVE then npc.noMove = true end if npc.gravity ~= 0 then npc:Walk() elseif npc.noMove then npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.1) else npc:Fly() end end return SkeletonAssaulter ================================================ FILE: npc_ai/SkeletonGuard.json ================================================ { "SkeletonGuard": { "script": { "path": "SkeletonGuard.lua" } } } ================================================ FILE: npc_ai/SkeletonGuard.lua ================================================ ---@class TC.SkeletonGuard:TC.HumanFighter local SkeletonGuard = class("SkeletonGuard", require("HumanFighter")) function SkeletonGuard:Init() SkeletonGuard.super.Init(self) self.isFrontHandLook = true self.isBackHandLook = true self.isFrontHandLookAngleSameDirection = true self.isBackHandLookAngleSameDirection = true self.shootColdTime = 0 self.shootingAnimation = false end function SkeletonGuard:Update() SkeletonGuard.super.Update(self) local npc = self.npc self.frontHandLookAngle = math.cos(self.npc.tickTime / 16) / 16 self.backHandLookAngle = math.sin(self.npc.tickTime / 16) / 16 self.npc:Fly(true) local effect = EffectUtils.Create(Reg.EffectID("chip"), self.npc.randX, self.npc.bottomY + Utils.RandSym(12), Utils.RandSym(0.1), Utils.RandDoubleArea(1, 1), Utils.RandSym(1), 1.0, 0.7, Color.new(200, 200, 200)) effect:SetDisappearTime(20) local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local distance = npc:GetDistance(playerTarget.centerX, playerTarget.centerY) if distance < 360 then npc:Fly(false) -- random fly else npc:Fly() end npc.direction = npc.centerX < playerTarget.centerX if distance < 640 then if npc.tickTime > 0 and npc.tickTime % 128 == 0 then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("lighting_wheel"), npc.centerX, npc.centerY, 3 * math.cos(angle), 3 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true self.shootColdTime = 0 self.shootingAnimation = true end end else npc:Fly(false) end if self.shootingAnimation then self.frontHandLookAngle = -math.sin(self.shootColdTime / 30 * math.pi) self.backHandLookAngle = self.frontHandLookAngle self.shootColdTime = self.shootColdTime + 1 if self.shootColdTime > 30 then self.shootColdTime = 0 self.shootingAnimation = false end npc.speedX = npc.speedX / 2 npc.speedY = npc.speedY / 2 end end return SkeletonGuard ================================================ FILE: npc_ai/Slime.json ================================================ { "Slime": { "script": { "path": "Slime.lua" } } } ================================================ FILE: npc_ai/Slime.lua ================================================ ---@class TC.Slime:ModNpc local Slime = class("Slime", ModNpc) local ST_NORMAL = 0 local ST_READY_TO_JUMP = 1 function Slime:Init() local npc = self.npc local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end self.jumpTryTimes = 0 self.JUMP_TRY_TIMES = npc.dataWatcher:AddInteger(0) end function Slime:Update() self:RecvSync() local npc = self.npc local following = (npc.y > MapUtils.UNDERGROUND_LINE * 16) if npc.inLiquid then npc.gravity = 0 if npc.stand then npc.speedY = -1 elseif npc.speedY > -1 then npc.speedY = npc.speedY - npc.defaultGravity end end if not npc.stand then if npc.direction then npc.speedX = npc.speedX + 0.0625 else npc.speedX = npc.speedX - 0.0625 end npc.speedX = math.max(npc.speedX, -npc.maxSpeed) npc.speedX = math.min(npc.speedX, npc.maxSpeed) end if not npc.inLiquid and npc.stand then if following then local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end end npc.speedX = Utils.SlowSpeed1D(npc.speedX, 0.25) if npc.state == ST_NORMAL then if Utils.RandTry(32) then npc.state = ST_READY_TO_JUMP end elseif npc.state == ST_READY_TO_JUMP then npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 64 then npc.stateTimer = 0 npc.state = ST_NORMAL if npc.direction then npc.speedX = npc.maxSpeed else npc.speedX = -(npc.maxSpeed) end npc.speedY = -Utils.RandDoubleArea(8, 2) end end end self:SendSync() end --- Called when NPC collides the tiles. ---@param oldSpeedX double Represents the X speed before colliding tiles. ---@param oldSpeedY double Represents the Y speed before colliding tiles. function Slime:OnTileCollide(oldSpeedX, oldSpeedY) local npc = self.npc if npc.stand then if not npc.isCollisionLeft and not npc.isCollisionRight then self.jumpTryTimes = 0 end if npc.isCollisionLeft and not npc.direction then if self.jumpTryTimes >= 1 then self.jumpTryTimes = 0 npc.direction = true else npc.speedY = -npc.jumpForce self.jumpTryTimes = self.jumpTryTimes + 1 end elseif npc.isCollisionRight and npc.direction then if self.jumpTryTimes >= 1 then self.jumpTryTimes = 0 npc.direction = false else npc.speedY = -npc.jumpForce self.jumpTryTimes = self.jumpTryTimes + 1 end end elseif npc.inLiquid then if npc.isCollisionLeft and not npc.direction then npc.direction = true elseif npc.isCollisionRight and npc.direction then npc.direction = false end end self:SendSync() end function Slime:SendSync() if NetMode.current == NetMode.Server then self.npc.dataWatcher:UpdateInteger(self.JUMP_TRY_TIMES, self.jumpTryTimes) end end function Slime:RecvSync() if NetMode.current == NetMode.Client then self.jumpTryTimes = self.npc.dataWatcher:GetInteger(self.JUMP_TRY_TIMES) end end function Slime:OnDraw() local npc = self.npc if not npc.stand then npc.spriteRect.x = npc.spriteDefaultWidth end end return Slime ================================================ FILE: npc_ai/Snake_Body.json ================================================ { "Snake_Body": { "script": { "path": "BaseSnakeBody.lua" } } } ================================================ FILE: npc_ai/Snake_Head.json ================================================ { "Snake_Head": { "script": { "path": "BaseSnake.lua" } } } ================================================ FILE: npc_ai/SnowGuardian.json ================================================ { "SnowGuardian": { "script": { "path": "SnowGuardian.lua" } } } ================================================ FILE: npc_ai/SnowGuardian.lua ================================================ ---@class TC.SnowGuardian:TC.SwordHumanFighter local SnowGuardian = class("SnowGuardian", require("SwordHumanFighter")) function SnowGuardian:Init() SnowGuardian.super.Init(self) self:SetHeldItemByIDName("stone_sword") end function SnowGuardian:Update() SnowGuardian.super.Update(self) local npc = self.npc npc:Fly() if npc.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("flash2"), npc.randX, npc.randY, Utils.RandSym(0.2), Utils.RandSym(0.2), 0, Utils.RandDoubleArea(0.5, 0.5)) end end return SnowGuardian ================================================ FILE: npc_ai/SnowGuardianArcher.json ================================================ { "SnowGuardianArcher": { "script": { "path": "SnowGuardianArcher.lua" } } } ================================================ FILE: npc_ai/SnowGuardianArcher.lua ================================================ ---@class TC.SnowGuardianArcher:TC.Archer local SnowGuardianArcher = class("SnowGuardianArcher", require("Archer")) function SnowGuardianArcher:Init() SnowGuardianArcher.super.Init(self) self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("ice_bow"))) end function SnowGuardianArcher:Update() SnowGuardianArcher.super.Update(self) local npc = self.npc if npc.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("flash2"), npc.randX, npc.randY, Utils.RandSym(0.2), Utils.RandSym(0.2), 0, Utils.RandDoubleArea(0.5, 0.5)) end end return SnowGuardianArcher ================================================ FILE: npc_ai/SnowQueen.json ================================================ { "SnowQueen": { "script": { "path": "SnowQueen.lua" } } } ================================================ FILE: npc_ai/SnowQueen.lua ================================================ ---@class TC.SnowQueen:TC.HumanFighter local SnowQueen = class("SnowQueen", require("HumanFighter")) local ST_STAGE_START = 0 local ST_STAGE_MID = 1 local ST_STAGE_LAST = 2 function SnowQueen:Init() SnowQueen.super.Init(self) self.isFrontHandLook = true self.isBackHandLook = true self.isFrontLegOverwrite = true self.isBackLegOverwrite = true self.isFrontHandLookAngleSameDirection = false self.isBackHandLookAngleSameDirection = false self.isFrontLegLookAngleSameDirection = true self.isBackLegLookAngleSameDirection = true self.shootAngle = 0 self:NotifyAllPlayer("snow_queen") end function SnowQueen:Update() local npc = self.npc -- get the target player local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then npc.direction = (playerTarget.centerX > npc.centerX) end -- set the boss stage npc.state = ST_STAGE_START if npc.health < npc.maxHealth / 3 then npc.state = ST_STAGE_LAST elseif npc.health < npc.maxHealth / 3 * 2 then npc.state = ST_STAGE_MID end -- if else state machine if npc.state == ST_STAGE_START then npc:Fly() if npc.tickTime > 0 and npc.tickTime % 64 == 0 then if playerTarget ~= nil then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("snow_flake"), npc.centerX + math.cos(angle) * 32, npc.centerY + math.sin(angle) * 32, 0.5 * math.cos(angle), 0.5 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end elseif npc.state == ST_STAGE_MID then npc:Fly() if npc.tickTime % 64 == 0 then if playerTarget ~= nil then local angle = npc:GetAngleTo(playerTarget.centerX, playerTarget.centerY) local initSpeed = 4 for i = 1, 3 do local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("ice_bullet"), npc.centerX + math.cos(angle) * 32, npc.centerY + math.sin(angle) * 32, initSpeed * math.cos(angle), initSpeed * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true initSpeed = initSpeed + 1 end SoundUtils.PlaySound(Reg.SoundID("fireball"), npc.centerXi, npc.centerYi) end end elseif npc.state == ST_STAGE_LAST then npc:Fly(false) npc.speedY = npc.speedY - 0.01 self.shootAngle = self.shootAngle + 0.1 if npc.tickTime % 4 == 0 then if playerTarget ~= nil then local angle = self.shootAngle local proj = ProjectileUtils.CreateFromNpc(npc, Reg.ProjectileID("ice_bullet"), npc.centerX + math.cos(angle) * 32, npc.centerY + math.sin(angle) * 32, 4 * math.cos(angle), 4 * math.sin(angle), npc.baseAttack) proj.isCheckPlayer = true if npc.tickTime % 16 == 0 then SoundUtils.PlaySound(Reg.SoundID("fireball2"), npc.centerXi, npc.centerYi) end end end end if npc.stand then npc.speedY = -6 end if npc.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("liquid_paticular"), npc.randX, npc.bottomY, Utils.RandSym(0.2), 1) end self.frontLegOverwriteAngle = -Utils.SinValue(npc.frameTickTime, 128) * 0.3 - math.pi / 6 + 0.1 self.backLegOverwriteAngle = -Utils.CosValue(npc.frameTickTime, 128) * 0.3 - math.pi / 4 + 0.1 self.frontHandLookAngle = -Utils.SinValue(npc.frameTickTime, 256) * 0.8 - math.pi / 12 + 2.2 self.backHandLookAngle = -Utils.CosValue(npc.frameTickTime, 256) * 0.4 - math.pi / 8 + 1.8 end function SnowQueen:OnKilled() self:NotifyAllPlayer("snow_queen_killed") if self.hookXi ~= nil and self.hookYi ~= nil then for i = 1, 12 do local effect = EffectUtils.SendFromServer(Reg.EffectID("chip"), self.hookXi * 16 + 8, self.hookYi * 16 + 8, Utils.RandSym(5), Utils.RandSym(5), 0, Utils.RandDoubleArea(1, 1), 1.0, Color.White ) effect.disappearTime = 64 effect.gravity = false end MapUtils.RemoveFront(self.hookXi, self.hookYi) end end function SnowQueen:NotifyAllPlayer(advancementIDName) local advancementID = Reg.AdvancementID(advancementIDName) local players = PlayerUtils.SearchByCircle(self.npc.centerX, self.npc.centerY, 300 * 16) ---@param player Player for _, player in each(players) do player:FinishAdvancement(advancementID) end end return SnowQueen ================================================ FILE: npc_ai/Squid.json ================================================ { "Squid": { "script": { "path": "Squid.lua" } } } ================================================ FILE: npc_ai/Squid.lua ================================================ ---@type ModNpc local Squid = class("Squid", ModNpc) function Squid:Update() local npc = self.npc if not npc.inLiquid then -- bounce in air if npc.stand then npc.speedY = -npc.jumpForce npc.speedX = Utils.RandSym(npc.maxSpeed) end if npc.isCollisionLeft then npc.direction = true npc.speedX = npc.maxSpeed * 0.5 elseif npc.isCollisionRight then npc.direction = false npc.speedX = -npc.maxSpeed * 0.5 end else -- in liquid npc.gravity = 0 if npc.stateTimer == 0 then local rate = Utils.RandDouble(1) local PI = math.pi local angle = 0 if npc.stand then if npc.isCollisionLeft then angle = -rate * PI / 2 elseif npc.isCollisionRight then angle = -rate * PI / 2 - PI / 2 else angle = rate * PI - PI end elseif npc.isCollisionTop then if npc.isCollisionLeft then angle = rate * PI / 2 elseif npc.isCollisionRight then angle = rate * PI / 2 + PI / 2 else angle = rate * PI end elseif npc.isCollisionLeft then angle = rate * PI - PI / 2 elseif npc.isCollisionRight then angle = rate * PI + PI / 2 else angle = rate * 2 * PI - PI end npc.rotateAngle = angle npc.speedX, npc.speedY = Utils.GetXYFromPolar(npc.maxSpeed, angle) end npc.speedX, npc.speedY = Utils.SlowSpeed2D(npc.speedX, npc.speedY, 0.03125) npc.stateTimer = npc.stateTimer + 1 if npc.stateTimer > 64 then npc.stateTimer = 0 end end if npc.stateTimer == 0 then npc.frameTickTime = 0 end end function Squid:OnDraw() self.npc.spriteEx.angle = self.npc.rotateAngle + math.pi / 2 end return Squid ================================================ FILE: npc_ai/SwordHumanFighter.lua ================================================ ---@class TC.SwordHumanFighter:TC.HumanFighter local SwordHumanFighter = class("SwordHumanFighter", require("HumanFighter")) local SwingState = { Waiting = 0, Swinging = 1, } function SwordHumanFighter:Init() self.boneSizeIndex = 0 self.style = 0 if self.npc.data and self.npc.data.tc then local dataTable = self.npc.data.tc if dataTable.boneSizeIndex ~= nil then self.boneSizeIndex = dataTable.boneSizeIndex end if dataTable.style ~= nil then self.style = dataTable.style end end SwordHumanFighter.super.Init(self) self.inventory = Inventory.new(1) self.npc.dataWatcher:AddInventory(self.inventory) self.itemSlotHeld = self.inventory:GetSlot(0) self.isFrontHandLook = true self.isBackHandLook = true self.isFrontHandLookAngleSameDirection = true self.isBackHandLookAngleSameDirection = true self.totalSwingTime = 30 self.totalSwingIntervalTime = 120 self.swingDistance = 120 self.alwaysTrySwing = true self.swingState = 0 self.swingTime = 0 self.SWING_STATE = self.npc.dataWatcher:AddInteger(0) end function SwordHumanFighter:Update() SwordHumanFighter.super.Update(self) self:UpdateSwordSwingLogic() end function SwordHumanFighter:UpdateSwordSwingLogic() if self.alwaysTrySwing and self:HasHeldSword() then local npc = self.npc local isServer = NetMode.current == NetMode.Server if not isServer then local newSwingState = npc.dataWatcher:GetInteger(self.SWING_STATE) if self.swingState ~= newSwingState then self.swingState = newSwingState self.swingTime = 0 end end if self.swingState == SwingState.Waiting then self:OnWaitSwing() local inDistance = false local playerTarget = PlayerUtils.Get(npc.playerTargetIndex) if playerTarget ~= nil then local d = Utils.GetDistance(playerTarget.centerX - npc.centerX, playerTarget.centerY - npc.centerY) if d < self.swingDistance then inDistance = true end end if inDistance then self.swingTime = self.swingTime + 1 if isServer and self.swingTime >= self.totalSwingIntervalTime then self.swingState = SwingState.Swinging self.swingTime = 0 end end elseif self.swingState == SwingState.Swinging then self.isUsingItemForAnimation = true self:OnSwing() self.swingTime = self.swingTime + 1 if self.swingTime >= self.totalSwingTime then self.swingState = SwingState.Waiting self.swingTime = 0 end end if isServer then npc.dataWatcher:UpdateInteger(self.SWING_STATE, self.swingState) end end end function SwordHumanFighter:HasHeldSword() if self.itemSlotHeld.hasStack then local stack = self.itemSlotHeld:GetStack() if stack:GetItem().toolType == "SWORD" then return true end end return false end function SwordHumanFighter:SetHeldItemByIDName(itemIDName) self.itemSlotHeld:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName(itemIDName))) end function SwordHumanFighter:OnWaitSwing() self:DoExternArmsAnimation() end function SwordHumanFighter:OnSwing() local rate = 0 if self.totalSwingTime > 0 then rate = self.swingTime * 1.0 / self.totalSwingTime end self.frontHandLookAngle = -math.pi / 3 + (rate) * 3 self.backHandLookAngle = -math.pi / 3 + (rate) * 3 end return SwordHumanFighter ================================================ FILE: npc_ai/TaintedSlime.json ================================================ { "TaintedSlime": { "script": { "path": "TaintedSlime.lua" } } } ================================================ FILE: npc_ai/TaintedSlime.lua ================================================ ---@type ModNpc local TaintedSlime = class("TaintedSlime", require("Slime")) function TaintedSlime:Update() TaintedSlime.super.Update(self) local npc = self.npc if npc.tickTime % 16 == 0 then EffectUtils.Create(Reg.EffectID("ender_flash"), npc.randX, npc.randY, Utils.RandSym(1), Utils.RandSym(1)) end end return TaintedSlime ================================================ FILE: npc_ai/UndeadMiner.json ================================================ { "UndeadMiner": { "script": { "path": "UndeadMiner.lua" } } } ================================================ FILE: npc_ai/UndeadMiner.lua ================================================ ---@class TC.UndeadMiner:TC.SwordHumanFighter local UndeadMiner = class("UndeadMiner", require("SwordHumanFighter")) function UndeadMiner:Init() UndeadMiner.super.Init(self) self:SetHeldItemByIDName("iron_pickaxe") end function UndeadMiner:Update() UndeadMiner.super.Update(self) LightingUtils.Add(self.npc.centerXi, self.npc.centerYi, 24) self:DoExternArmsAnimation() end return UndeadMiner ================================================ FILE: npc_ai/Villager.json ================================================ { "Villager": { "pAI": "Villager_AI" } } ================================================ FILE: npc_ai/WasteGhost.json ================================================ { "WasteGhost": { "script": { "path": "WasteGhost.lua" } } } ================================================ FILE: npc_ai/WasteGhost.lua ================================================ ---@type ModNpc local WasteGhost = class("WasteGhost", ModNpc) function WasteGhost:Update() local npc = self.npc npc.gravity = npc.gravity * 0.2 npc:Walk() if npc.tickTime % 16 == 0 then local cy = npc.y if npc.speedY < 0 then cy = npc.bottomY end EffectUtils.Create( Reg.EffectID("liquid_paticular"), npc.randX, cy, Utils.RandSym(0.5), 0, 0, Utils.RandDoubleArea(0.5, 0.5), 0, Color.new(255, 200, 100) ) end end function WasteGhost:OnTileCollide(_, _) local npc = self.npc if npc.stand then npc.speedY = -npc.jumpForce end end function WasteGhost:OnDraw() local npc = self.npc if npc.maxSpeed > 0 then npc.spriteEx.angle = npc.speedX / npc.maxSpeed / 2 end end return WasteGhost ================================================ FILE: npc_ai/WitherSkeleton.json ================================================ { "WitherSkeleton": { "script": { "path": "WitherSkeleton.lua" } } } ================================================ FILE: npc_ai/WitherSkeleton.lua ================================================ ---@class TC.WitherSkeleton:TC.SwordHumanFighter local WitherSkeleton = class("WitherSkeleton", require("SwordHumanFighter")) function WitherSkeleton:Init() self.boneSizeIndex = 1 WitherSkeleton.super.Init(self) self:SetHeldItemByIDName("iron_sword") end return WitherSkeleton ================================================ FILE: npc_ai/Wolf.json ================================================ { "Wolf": { "script": { "path": "Wolf.lua" } } } ================================================ FILE: npc_ai/Wolf.lua ================================================ ---@type ModNpc local Wolf = class("Wolf", ModNpc) function Wolf:Update() local npc = self.npc if npc.angry then if Utils.RandTry(512) then npc.angry = false end end npc:TryMakeSound() if npc.angry then npc.maxSpeed = npc.maxSpeed * 1.5 npc:Walk() else npc:RandomWalk() end end function Wolf:PostUpdate() local npc = self.npc if npc.speedX == 0 then npc.frameTickTime = 0 end end function Wolf:OnDraw() local npc = self.npc if npc.angry then npc.spriteRect.y = npc.spriteDefaultHeight end if npc.frameTickTime > 0 then npc.spriteRect.x = npc.spriteRect.x + npc.spriteDefaultWidth end end return Wolf ================================================ FILE: npc_ai/Zombie.json ================================================ { "Zombie": { "script": { "path": "Zombie.lua" } } } ================================================ FILE: npc_ai/Zombie.lua ================================================ ---@class TC.Zombie:TC.SwordHumanFighter local Zombie = class("Zombie", require("SwordHumanFighter")) function Zombie:Init() Zombie.super.Init(self) if Utils.RandTry(20) then self:SetHeldItemByIDName("stone_sword") end end function Zombie:Update() Zombie.super.Update(self) if not self:HasHeldSword() then self:DoExternArmsAnimation() end end return Zombie ================================================ FILE: npc_ai/Zpig.json ================================================ { "Zpig": { "script": { "path": "Zpig.lua" } } } ================================================ FILE: npc_ai/Zpig.lua ================================================ ---@class TC.ZPig:TC.SwordHumanFighter local ZPig = class("ZPig", require("SwordHumanFighter")) function ZPig:Init() ZPig.super.Init(self) self:SetHeldItemByIDName("golden_sword") self.alwaysTrySwing = false end function ZPig:Update() ZPig.super.Update(self) local npc = self.npc npc:TryMakeSound() self.alwaysTrySwing = false if npc.angry then npc.maxSpeed = npc.maxSpeed * 1.5 npc:Walk() self.alwaysTrySwing = true else npc:RandomWalk() end end return ZPig ================================================ FILE: npc_ai_global/GNpc.lua ================================================ ---@type GlobalNpc local GNpc = class("GNpc", GlobalNpc) function GNpc.CheckCreateInstance(npc) return true end function GNpc:CanUpdate() return true end function GNpc:Update() if self.npc.stand then --self.npc.speedY = -5 end end return GNpc ================================================ FILE: npc_ai_global/GlobalNpc.json ================================================ { "GlobalClass": [ "GNpc" ] } ================================================ FILE: npcs/angry_skeleton.json ================================================ { "angry_skeleton": { "ai": "AngrySkeleton", "textureData": "angry_skeleton.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.25, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 50, "defense": 6, "attack": 12, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "loots": [ { "item": "bone", "min": 0, "max": 5 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_angry_skeleton", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/arrow_zombie.json ================================================ { "arrow_zombie": { "ai": "Zombie", "textureData": "arrow_zombie.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [ "zombie_say1", "zombie_say2", "zombie_say3" ], "hurtSounds": [ "zombie_death", "zombie_hurt1", "zombie_hurt2" ], "noBurnSound": true, "loots": [ { "item": "rotten_flesh", "count": [ 1, 4 ] }, { "item": "wooden_arrow", "count": [ 1, 2 ] } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_arrow_zombie", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/bald_zombie.json ================================================ { "bald_zombie": { "ai": "Zombie", "textureData": "bald_zombie.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [ "zombie_say1", "zombie_say2", "zombie_say3" ], "hurtSounds": [ "zombie_death", "zombie_hurt1", "zombie_hurt2" ], "noBurnSound": true, "loots": [ { "item": "rotten_flesh", "count": [ 1, 4 ] }, { "item": "dark_shadow_part", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_bald_zombie", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/bat.json ================================================ { "bat": { "ai": "Bat", "textureData": "bat.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 72, "gfxHeight": 46, "gfxOffsetX": -20, "gfxOffsetY": -7, "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 6, "attack": 7, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "bat_death", "bat_hurt1", "bat_hurt2", "bat_hurt3" ], "loots": [ { "item": "gray_feather", "count": [ 3, 8 ] } ], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "gore": "gore_bat", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/black_rabbit.json ================================================ { "black_rabbit": { "ai": "Animal", "textureData": "black_rabbit.png", "type": "ANIMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 6.0, "disappearTime": 750, "spawnCount": 1.0, "health": 10, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 2, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "rabbit_hurt1", "rabbit_hurt1", "rabbit_hurt2", "rabbit_hurt3" ], "loots": [ { "item": "rabbit_foot", "possibility": 0.5 }, { "item": "rabbit_hide", "count": [1, 2], "possibility": 1.0 }, { "item": "raw_rabbit", "possibility": 0.5 } ], "burnLoots": [ { "item": "rabbit_foot", "count": [1], "possibility": 0.5 }, { "item": "rabbit_hide", "count": [1, 2], "possibility": 1.0 }, { "item": "cooked_rabbit", "count": [1], "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_black_rabbit", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/black_skeleton.json ================================================ { "black_skeleton": { "ai": "BlackSkeleton", "textureData": "black_skeleton.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 6, "attack": 12, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "loots": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "steel_ingot", "min": 0, "max": 1 }, { "item": "dark_shadow_part", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 100, 100, 100 ], "spawn": "LAND", "gore": "gore_black_skeleton", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/blaze.json ================================================ { "blaze": { "ai": "Blaze", "textureData": "blaze.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -4, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.25, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 6, "attack": 18, "knockBack": 5, "knockBackDefense": 0.40, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "blaze_death", "blaze_hit1", "blaze_hit2", "blaze_hit3" ], "loots": [ { "item": "blaze_rod", "count": [ 3, 6 ] } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 640 } } ================================================ FILE: npcs/block_slime.json ================================================ { "block_slime": { "ai": "BlockSlime", "textureData": "block_slime.png", "type": "NORMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 20, "defense": 0, "attack": 5, "knockBack": 2, "knockBackDefense": 0.03, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 4, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "min": 1, "max": 2 } ], "special": 0, "paticularColor": [ 255, 120, 200, 100 ], "spawn": "LAND", "magicRate": 50, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/blood_bat.json ================================================ { "blood_bat": { "ai": "Bat", "textureData": "blood_bat.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 72, "gfxHeight": 46, "gfxOffsetX": -20, "gfxOffsetY": -7, "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 6, "attack": 7, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "bat_death", "bat_hurt1", "bat_hurt2", "bat_hurt3" ], "loots": [ { "item": "gray_feather", "count": [ 1, 13 ] } ], "special": 0, "paticularColor": [ 255, 200, 0, 0 ], "spawn": "AIR", "gore": "gore_blood_bat", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/blood_eye.json ================================================ { "blood_eye": { "ai": "BloodyEye", "textureData": "blood_eye.png", "type": "NORMAL", "width": 40, "height": 40, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 0, "frames": 1, "frameSpeed": 4, "shape": "BOX", "maxSpeed": 1.25, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 6, "attack": 15, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [ { "item": "gold_nugget", "count": [ 1, 5 ] } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "gore": "gore_blood_eye", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/blood_skeleton.json ================================================ { "blood_skeleton": { "ai": "BloodSkeleton", "textureData": "blood_skeleton.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 50, "defense": 6, "attack": 12, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "loots": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "blood_arrow", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_blood_skeleton", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/blood_slime.json ================================================ { "blood_slime": { "ai": "Slime", "textureData": "blood_slime.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -4, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 4, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 2, 5 ] } ], "special": 0, "paticularColor": [ 255, 200, 90, 80 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/blue_slime.json ================================================ { "blue_slime": { "ai": "Slime", "textureData": "blue_slime.png", "type": "NORMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 1, 4 ] } ], "special": 0, "paticularColor": [ 255, 0, 0, 60 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/bone_lee.json ================================================ { "bone_lee": { "ai": "BoneLee", "textureData": "bone_lee.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 4.5, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 120, "defense": 7, "attack": 26, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 17, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "loots": [ { "item": "bone", "min": 0, "max": 5 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_bone_lee", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/bone_officer.json ================================================ { "bone_officer": { "ai": "BoneOfficer", "textureData": "bone_officer.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 7, "attack": 25, "knockBack": 5, "knockBackDefense": 0.60, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "loots": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "magic_cell", "count": [ 3, 5 ] } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_bone_officer", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/bone_sniper.json ================================================ { "bone_sniper": { "ai": "BoneSniper", "textureData": "bone_sniper.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 70, "defense": 6, "attack": 22, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "loots": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "magic_cell", "count": [ 3, 5 ] } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_bone_sniper", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/boney_skeleton.json ================================================ { "boney_skeleton": { "ai": "BoneySkeleton", "textureData": "boney_skeleton.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.75, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 6, "attack": 12, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "loots": [ { "item": "bone", "min": 3, "max": 9 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_boney_skeleton", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/bouncy_slime.json ================================================ { "bouncy_slime": { "ai": "BouncySlime", "textureData": "bouncy_slime.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -4, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 5.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 50, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 4, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "min": 2, "max": 5 } ], "special": 0, "paticularColor": [ 255, 77, 77, 77 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/brown_mushroom_cow.json ================================================ { "brown_mushroom_cow": { "ai": "Animal", "textureData": "brown_mushroom_cow.png", "type": "ANIMAL", "width": 60, "height": 60, "gfxWidth": 64, "gfxHeight": 72, "gfxOffsetX": -2, "gfxOffsetY": -12, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 15, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 3, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "cow_say1", "cow_say2", "cow_say3" ], "hurtSounds": [ "cow_hurt1", "cow_hurt1", "cow_hurt2", "cow_hurt3" ], "loots": [ { "item": "raw_beef", "count": [1, 3], "possibility": 1.0 }, { "item": "leather", "count": [1, 2], "possibility": 0.5 }, { "item": "brown_mushroom", "count": [1, 4], "possibility": 1.0 } ], "burnLoots": [ { "item": "steak", "count": [1, 3], "possibility": 1.0 }, { "item": "leather", "count": [1, 2], "possibility": 0.5 }, { "item": "brown_mushroom", "count": [1, 4], "possibility": 1.0 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_brown_mushroom_cow", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/brown_rabbit.json ================================================ { "brown_rabbit": { "ai": "Animal", "textureData": "brown_rabbit.png", "type": "ANIMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 6.0, "disappearTime": 750, "spawnCount": 1.0, "health": 10, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 2, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "rabbit_hurt1", "rabbit_hurt1", "rabbit_hurt2", "rabbit_hurt3" ], "loots": [ { "item": "rabbit_foot", "possibility": 0.5 }, { "item": "rabbit_hide", "count": [ 1, 2 ] }, { "item": "raw_rabbit", "possibility": 0.5 } ], "burnLoots": [ { "item": "rabbit_foot", "possibility": 0.5 }, { "item": "rabbit_hide", "count": [ 1, 2 ] }, { "item": "cooked_rabbit", "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_brown_rabbit", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/cat.json ================================================ { "cat": { "ai": "Cat", "textureData": "cat.png", "type": "ANIMAL", "width": 32, "height": 32, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": -8, "gfxOffsetY": -16, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 4.0, "jumpForce": 6.0, "disappearTime": 750, "spawnCount": 1.0, "health": 20, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 3, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "cat_meow1", "cat_meow2", "cat_meow3" ], "hurtSounds": [ "cat_hit1", "cat_hit1", "cat_hit2", "cat_hit3" ], "loots": [ { "item": "leather", "count": [ 1, 3 ], "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/chicken.json ================================================ { "chicken": { "ai": "Chicken", "textureData": "chicken.png", "type": "ANIMAL", "width": 24, "height": 24, "gfxWidth": 28, "gfxHeight": 28, "gfxOffsetX": -2, "gfxOffsetY": -4, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 10, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 3, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "chicken_say1", "chicken_say2", "chicken_say3" ], "hurtSounds": [ "chicken_hurt1", "chicken_hurt1", "chicken_hurt2" ], "loots": [ { "item": "raw_chicken", "count": [ 1, 3 ] }, { "item": "feather", "count": [ 1, 4 ], "possibility": 0.5 } ], "burnLoots": [ { "item": "cooked_chicken", "count": [ 1, 3 ] }, { "item": "feather", "count": [ 1, 4 ], "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_chicken", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/cow.json ================================================ { "cow": { "ai": "Animal", "textureData": "cow.png", "type": "ANIMAL", "width": 60, "height": 60, "gfxWidth": 64, "gfxHeight": 64, "gfxOffsetX": -2, "gfxOffsetY": -4, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 20, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 3, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "cow_say1", "cow_say2", "cow_say3" ], "hurtSounds": [ "cow_hurt1", "cow_hurt1", "cow_hurt2", "cow_hurt3" ], "loots": [ { "item": "raw_beef", "count": [ 1, 3 ] }, { "item": "leather", "count": [ 1, 3 ], "possibility": 0.5 } ], "burnLoots": [ { "item": "steak", "count": [ 1, 3 ] }, { "item": "leather", "count": [ 1, 3 ], "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_cow", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/creeper.json ================================================ { "creeper": { "ai": "Creeper", "textureData": "creeper.png", "type": "NORMAL", "width": 24, "height": 50, "gfxWidth": 32, "gfxHeight": 64, "gfxOffsetX": -4, "gfxOffsetY": -14, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 8, "attack": 10, "knockBack": 2, "knockBackDefense": 0.15, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "creeper_death", "creeper1", "creeper2", "creeper3" ], "loots": [ { "item": "gunpowder", "min": 2, "max": 4 } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_creeper", "magicRate": 22, "checkPlayerTarget": true, "visionNoCrossTile": true } } ================================================ FILE: npcs/crison_eye.json ================================================ { "crison_eye": { "ai": "CrisonEye", "textureData": "crison_eye.png", "type": "NORMAL", "width": 112, "height": 112, "gfxWidth": 192, "gfxHeight": 112, "gfxOffsetX": -48, "gfxOffsetY": 0, "frameStyle": 0, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.2, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 2600, "defense": 5, "attack": 22, "knockBack": 8, "knockBackDefense": 0.99, "gravity": false, "climbWall": false, "foreground": true, "noFixByBlock": true, "friendly": false, "exps": 217, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [ { "item": "diamond", "count": [ 1, 2 ] }, { "item": "star_ingot", "count": [ 5, 12 ] }, { "item": "evil_part", "count": [ 8, 20 ] }, { "item": "magic_cell", "count": [ 18, 25 ] } ], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/crystal_monster.json ================================================ { "crystal_monster": { "ai": "CrystalMonster", "textureData": "crystal_monster.png", "type": "SMITE", "width": 48, "height": 64, "gfxWidth": 48, "gfxHeight": 64, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "maxSpeed": 2.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 10, "attack": 18, "knockBack": 5, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": true, "noFixByBlock": false, "friendly": false, "exps": 22, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [ { "item": "white_crystal", "min": 1, "max": 2 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 50, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 256 } } ================================================ FILE: npcs/cursed_skull.json ================================================ { "cursed_skull": { "ai": "CursedSkull", "textureData": "cursed_skull.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 1.2, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 6, "attack": 17, "knockBack": 5, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": true, "noFixByBlock": true, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "gore": "gore_cursed_skull", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/dark_mage.json ================================================ { "dark_mage": { "ai": "DarkMage", "textureData": "dark_mage.png", "type": "NORMAL", "width": 28, "height": 48, "gfxWidth": 40, "gfxHeight": 48, "gfxOffsetX": -6, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 0.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 8, "attack": 18, "knockBack": 2, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "shulker_hit1", "shulker_hit1" ], "loots": [ { "item": "emerald", "min": 0, "max": 1 }, { "item": "red_crystal", "min": 0, "max": 1 }, { "item": "yellow_crystal", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 33, 33, 33 ], "spawn": "LAND", "gore": "gore_evoker", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 720 } } ================================================ FILE: npcs/dead_mage.json ================================================ { "dead_mage": { "ai": "DeadMage", "textureData": "dead_mage.png", "type": "NORMAL", "width": 28, "height": 64, "gfxWidth": 40, "gfxHeight": 64, "gfxOffsetX": -6, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 0.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 10, "attack": 10, "knockBack": 2, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "shulker_hit1", "shulker_hit1" ], "loots": [ { "item": "emerald", "min": 0, "max": 1 }, { "item": "red_crystal", "min": 0, "max": 1 }, { "item": "yellow_crystal", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 33, 33, 33 ], "spawn": "LAND", "gore": "gore_evoker", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 720 } } ================================================ FILE: npcs/desert_slime.json ================================================ { "desert_slime": { "ai": "Slime", "textureData": "desert_slime.png", "type": "NORMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 11.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 220, 160, 0 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/doge_zombie.json ================================================ { "doge_zombie": { "ai": "Zombie", "textureData": "doge_zombie.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 8, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [ "wolf_bark1", "wolf_bark2", "wolf_bark3" ], "hurtSounds": [ "wolf_hurt1", "wolf_hurt2", "wolf_hurt3" ], "loots": [ { "item": "rotten_flesh", "min": 1, "max": 4 }, { "item": "bone", "min": 1, "max": 2 } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_doge_zombie", "magicRate": 28, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/dolphin.json ================================================ { "dolphin": { "ai": "Dolphin", "textureData": "dolphin.png", "type": "ANIMAL", "width": 72, "height": 40, "gfxWidth": 96, "gfxHeight": 48, "gfxOffsetX": -8, "gfxOffsetY": -4, "frameStyle": 1, "frames": 4, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 4.0, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 30, "defense": 3, "attack": 1, "knockBack": 0, "knockBackDefense": 0.30, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 3, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "dolphin_hurt1", "dolphin_hurt1", "dolphin_hurt2", "dolphin_hurt3" ], "loots": [ { "item": "raw_cod", "count": [ 1, 3 ] }, { "item": "raw_salmon", "count": [ 1, 2 ], "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "WATER", "gore": "gore_dolphin", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/dragon_skull.json ================================================ { "dragon_skull": { "ai": "CursedSkull", "textureData": "dragon_skull.png", "type": "NORMAL", "width": 64, "height": 32, "gfxWidth": 64, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 1.2, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 120, "defense": 16, "attack": 17, "knockBack": 15, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": true, "noFixByBlock": true, "friendly": false, "exps": 11, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "drops": [], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/drowned.json ================================================ { "drowned": { "ai": "Zombie", "textureData": "drowned.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [ "zombie_say1", "zombie_say2", "zombie_say3" ], "hurtSounds": [ "zombie_death", "zombie_hurt1", "zombie_hurt2" ], "noBurnSound": true, "loots": [ { "item": "rotten_flesh", "count": [ 1, 4 ] }, { "item": "gold_ingot", "count": [ 1, 2 ], "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "WATER", "gore": "gore_drowned", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/dungeon_creeper.json ================================================ { "dungeon_creeper": { "ai": "DungeonCreeper", "textureData": "dungeon_creeper.png", "type": "NORMAL", "width": 24, "height": 50, "gfxWidth": 32, "gfxHeight": 64, "gfxOffsetX": -4, "gfxOffsetY": -14, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 8, "attack": 13, "knockBack": 3, "knockBackDefense": 0.35, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 8, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "creeper_death", "creeper1", "creeper2", "creeper3" ], "drops": [ { "item": "gunpowder", "min": 2, "max": 4 }, { "item": "magic_cell", "count": [ 3, 5 ] } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_creeper", "magicRate": 22, "checkPlayerTarget": true, "visionNoCrossTile": true } } ================================================ FILE: npcs/dungeon_eater_body.json ================================================ { "dungeon_eater_body": { "ai": "DungeonEater_Body", "textureData": "dungeon_eater_body.png", "type": "ARTHROPODS", "width": 44, "height": 36, "gfxWidth": 44, "gfxHeight": 36, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 5.0, "jumpForce": 1.0, "disappearTime": 100000000, "spawnCount": 0.20, "health": 80, "defense": 4, "attack": 15, "knockBack": 10, "knockBackDefense": 1.0, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": true, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [], "loots": [], "special": 0, "paticularColor": [ 255, 100, 100, 100 ], "spawn": "AIR", "noShowHp": true, "gore": "gore_lava_snake_body" } } ================================================ FILE: npcs/dungeon_eater_head.json ================================================ { "dungeon_eater_head": { "ai": "DungeonEater_Head", "textureData": "dungeon_eater_head.png", "type": "ARTHROPODS", "width": 50, "height": 40, "gfxWidth": 50, "gfxHeight": 40, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 5.0, "jumpForce": 1.0, "disappearTime": 750, "spawnCount": 1.0, "health": 2600, "defense": 4, "attack": 20, "knockBack": 10, "knockBackDefense": 0.9, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": true, "friendly": false, "exps": 600, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "attack1", "attack2" ], "loots": [ { "item": "ancient_sample", "count": [ 10, 13 ] } ], "special": 0, "paticularColor": [ 255, 100, 100, 100 ], "spawn": "AIR", "isBoss": true, "noShowHp": true, "gore": "gore_lava_snake_head", "magicRate": 1, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/dungeon_eater_tail.json ================================================ { "dungeon_eater_tail": { "ai": "DungeonEater_Body", "textureData": "dungeon_eater_tail.png", "type": "ARTHROPODS", "width": 54, "height": 40, "gfxWidth": 54, "gfxHeight": 40, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 5.0, "jumpForce": 1.0, "disappearTime": 100000000, "spawnCount": 1.0, "health": 80, "defense": 4, "attack": 25, "knockBack": 10, "knockBackDefense": 1.0, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": true, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [], "loots": [], "special": 0, "paticularColor": [ 255, 100, 100, 100 ], "spawn": "AIR", "noShowHp": true, "gore": "gore_lava_snake_tail" } } ================================================ FILE: npcs/dungeon_knight.json ================================================ { "dungeon_knight": { "ai": "DungeonKnight", "textureData": "dungeon_knight.png", "type": "SMITE", "width": 24, "height": 64, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 10, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 300, "defense": 20, "attack": 25, "knockBack": 5, "knockBackDefense": 0.90, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 17, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "knight_ingot", "min": 4, "max": 6 }, { "item": "diamond", "min": 1, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_angry_skeleton", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/dungeon_slime.json ================================================ { "dungeon_slime": { "ai": "BlockSlime", "textureData": "dungeon_slime.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -4, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 6.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 0, "attack": 10, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "drops": [ { "item": "slimeball", "min": 2, "max": 5 } ], "special": 0, "paticularColor": [ 255, 77, 77, 77 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/dungeon_soul.json ================================================ { "dungeon_soul": { "ai": "DungeonSoul", "textureData": "dungeon_soul.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 6, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.25, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 6, "attack": 18, "knockBack": 5, "knockBackDefense": 0.40, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "blaze_death", "blaze_hit1", "blaze_hit2", "blaze_hit3" ], "drops": [ { "item": "blaze_rod", "min": 3, "max": 6 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 640 } } ================================================ FILE: npcs/eagle.json ================================================ { "eagle": { "ai": "Eagle", "textureData": "eagle.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 96, "gfxHeight": 96, "gfxOffsetX": -32, "gfxOffsetY": -32, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 5.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 2, "attack": 18, "knockBack": 6, "knockBackDefense": 0.20, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [ { "item": "gray_feather", "count": [ 3, 7 ] } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "gore": "gore_eagle", "magicRate": 40, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/ender_dragon.json ================================================ { "ender_dragon": { "ai": "Ender_Dragon", "textureData": "ender_dragon.png", "type": "BOSS", "width": 240, "height": 200, "gfxWidth": 360, "gfxHeight": 320, "gfxOffsetX": -60, "gfxOffsetY": -60, "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "BOX", "maxSpeed": 9.0, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 20, "attack": 20, "knockBack": 10, "knockBackDefense": 0.80, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 66, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [], "loots": [], "special": 0, "paticularColor": [ 255, 33, 33, 33 ], "spawn": "AIR", "magicRate": 1 } } ================================================ FILE: npcs/enderman.json ================================================ { "enderman": { "ai": "Enderman", "textureData": "enderman.png", "type": "NORMAL", "width": 24, "height": 64, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 10, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 9, "attack": 18, "knockBack": 5, "knockBackDefense": 0.30, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 15, "sunBurning": false, "angry": true, "antiLava": false, "saySounds": [ "enderman_idle1", "enderman_idle2", "enderman_idle3" ], "hurtSounds": [ "enderman_death", "enderman_hit1", "enderman_hit2", "enderman_hit3" ], "loots": [ { "item": "ender_pearl", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 50, 50, 50 ], "spawn": "LAND", "gore": "gore_enderman", "magicRate": 20, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/evil.json ================================================ { "evil": { "ai": "Evil", "textureData": "evil.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 96, "gfxHeight": 96, "gfxOffsetX": -32, "gfxOffsetY": -32, "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 160, "defense": 2, "attack": 18, "knockBack": 6, "knockBackDefense": 0.20, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 14, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "phantom_death", "phantom_hurt1", "phantom_hurt2", "phantom_hurt3" ], "drops": [ { "item": "evil_part", "min": 1, "max": 3 } ], "special": 0, "paticularColor": [ 255, 50, 50, 50 ], "spawn": "AIR", "gore": "gore_phantom", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/evoker.json ================================================ { "evoker": { "ai": "Evoker", "textureData": "evoker.png", "type": "NORMAL", "width": 28, "height": 48, "gfxWidth": 40, "gfxHeight": 48, "gfxOffsetX": -6, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 0.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 10, "attack": 10, "knockBack": 2, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "shulker_hit1", "shulker_hit1" ], "loots": [ { "item": "emerald", "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 33, 33, 33 ], "spawn": "LAND", "gore": "gore_evoker", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 720 } } ================================================ FILE: npcs/eye_guard.json ================================================ { "eye_guard": { "ai": "EyeGuard", "textureData": "eye_guard.png", "type": "SMITE", "width": 48, "height": 48, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 2, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.25, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 180, "defense": 6, "attack": 18, "knockBack": 5, "knockBackDefense": 0.20, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "blaze_death", "blaze_hit1", "blaze_hit2", "blaze_hit3" ], "drops": [ { "item": "blaze_rod", "min": 3, "max": 6 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 640 } } ================================================ FILE: npcs/eye_guard_laser.json ================================================ { "eye_guard_laser": { "ai": "EyeGuardLaser", "textureData": "eye_guard_laser.png", "type": "SMITE", "width": 48, "height": 48, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 2, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.25, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 180, "defense": 6, "attack": 18, "knockBack": 5, "knockBackDefense": 0.40, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "blaze_death", "blaze_hit1", "blaze_hit2", "blaze_hit3" ], "drops": [ { "item": "blaze_rod", "min": 3, "max": 6 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 640 } } ================================================ FILE: npcs/flame_soul.json ================================================ { "flame_soul": { "ai": "FlameSoul", "textureData": "flame_soul.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 6, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.25, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 6, "attack": 18, "knockBack": 5, "knockBackDefense": 0.40, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "blaze_death", "blaze_hit1", "blaze_hit2", "blaze_hit3" ], "drops": [ { "item": "blaze_rod", "min": 3, "max": 6 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 640 } } ================================================ FILE: npcs/flower_creeper.json ================================================ { "flower_creeper": { "ai": "Creeper", "textureData": "flower_creeper.png", "type": "NORMAL", "width": 24, "height": 50, "gfxWidth": 32, "gfxHeight": 64, "gfxOffsetX": -4, "gfxOffsetY": -14, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 8, "attack": 10, "knockBack": 2, "knockBackDefense": 0.15, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "creeper_death", "creeper1", "creeper2", "creeper3" ], "loots": [ { "item": "gunpowder", "count": [ 3, 5 ] } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_flower_creeper", "magicRate": 22, "checkPlayerTarget": true, "visionNoCrossTile": true } } ================================================ FILE: npcs/fly_eye.json ================================================ { "fly_eye": { "ai": "FlyEye", "textureData": "fly_eye.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 72, "gfxHeight": 46, "gfxOffsetX": -20, "gfxOffsetY": -7, "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 70, "defense": 6, "attack": 7, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [ { "item": "strange_len", "count": [1, 2] } ], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/fly_mouth.json ================================================ { "fly_mouth": { "ai": "FlyEye", "textureData": "fly_mouth.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 72, "gfxHeight": 46, "gfxOffsetX": -20, "gfxOffsetY": -7, "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "BOX", "maxSpeed": 5.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 70, "defense": 4, "attack": 12, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "drops": [], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/fly_skeleton.json ================================================ { "fly_skeleton": { "ai": "FlySkeleton", "textureData": "fly_skeleton.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 16, "knockBack": 5, "knockBackDefense": 0.50, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 8, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "drops": [], "special": 1, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "AIR", "spawnWall": "aurora_block", "magicRate": 100, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/ghast.json ================================================ { "ghast": { "ai": "Ghast", "textureData": "ghast.png", "type": "SMITE", "width": 72, "height": 72, "gfxWidth": 96, "gfxHeight": 96, "gfxOffsetX": -12, "gfxOffsetY": -12, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "maxSpeed": 1.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 10, "attack": 10, "knockBack": 5, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": true, "noFixByBlock": true, "friendly": false, "exps": 14, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [ "ghast_moan1", "ghast_moan2", "ghast_moan3" ], "hurtSounds": [ "ghast_death", "affectionate_scream" ], "loots": [ { "item": "ghast_tear", "count": [ 1, 4 ] } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 20, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 640 } } ================================================ FILE: npcs/ghost_gunner.json ================================================ { "ghost_gunner": { "ai": "GhostGunner", "textureData": "ghost_gunner.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 65, "defense": 7, "attack": 18, "knockBack": 5, "knockBackDefense": 0.50, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 13, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "drops": [ { "item": "ghost_element", "min": 0, "max": 1 } ], "special": 1, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "AIR", "spawnWall": "more_dungeons:stone_wall_white", "magicRate": 100, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/ghost_soul.json ================================================ { "ghost_soul": { "ai": "GhostSoul", "textureData": "ghost_soul.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": -8, "gfxOffsetY": -8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.25, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 6, "attack": 18, "knockBack": 5, "knockBackDefense": 0.40, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "blaze_death", "blaze_hit1", "blaze_hit2", "blaze_hit3" ], "drops": [ { "item": "blaze_rod", "min": 3, "max": 6 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 640 } } ================================================ FILE: npcs/giant_cursed_skull.json ================================================ { "giant_cursed_skull": { "ai": "GiantCursedSkull", "textureData": "giant_cursed_skull.png", "type": "NORMAL", "width": 64, "height": 64, "gfxWidth": 64, "gfxHeight": 64, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 2, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.2, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 220, "defense": 16, "attack": 27, "knockBack": 5, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": true, "noFixByBlock": true, "friendly": false, "exps": 17, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "drops": [], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "gore": "gore_giant_cursed_skull", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/green_slime.json ================================================ { "green_slime": { "ai": "Slime", "textureData": "green_slime.png", "type": "NORMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 16, "defense": 0, "attack": 4, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 4, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 1, 2 ] } ], "special": 0, "paticularColor": [ 255, 120, 200, 100 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/grim_reaper.json ================================================ { "grim_reaper": { "ai": "GrimReaper", "textureData": "grim_reaper.png", "type": "NORMAL", "width": 28, "height": 48, "gfxWidth": 40, "gfxHeight": 48, "gfxOffsetX": -6, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 0.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 10, "attack": 10, "knockBack": 2, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "shulker_hit1", "shulker_hit1" ], "drops": [ { "item": "emerald", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 33, 33, 33 ], "spawn": "LAND", "gore": "gore_evoker", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 720 } } ================================================ FILE: npcs/guardian.json ================================================ { "guardian": { "ai": "Guardian", "textureData": "guardian.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 52, "gfxHeight": 48, "gfxOffsetX": -10, "gfxOffsetY": -8, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 10, "attack": 10, "knockBack": 5, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "blaze_death", "blaze_hit1", "blaze_hit2", "blaze_hit3" ], "loots": [ { "item": "guardian" }, { "item": "prismarine_crystals", "count": [ 1, 4 ] }, { "item": "raw_cod", "count": [ 1, 2 ], "possibility": 0.5 }, { "item": "prismarine_shard", "count": [ 2, 5 ] } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "WATER", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 400 } } ================================================ FILE: npcs/husk.json ================================================ { "husk": { "ai": "Zombie", "textureData": "husk.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "zombie_say1", "zombie_say2", "zombie_say3" ], "hurtSounds": [ "zombie_death", "zombie_hurt1", "zombie_hurt2" ], "noBurnSound": true, "loots": [ { "item": "rotten_flesh", "count": [ 1, 4 ] } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_husk", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/ice_elf.json ================================================ { "ice_elf": { "ai": "IceElf", "textureData": "ice_elf.png", "type": "SMITE", "width": 50, "height": 50, "gfxWidth": 50, "gfxHeight": 50, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 2, "frameSpeed": 8, "maxSpeed": 2.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 10, "attack": 7, "knockBack": 5, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": true, "noFixByBlock": true, "friendly": false, "exps": 6, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 50, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 256 } } ================================================ FILE: npcs/ice_slime.json ================================================ { "ice_slime": { "ai": "BlockSlime", "textureData": "ice_slime.png", "type": "NORMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 20, "defense": 0, "attack": 5, "knockBack": 2, "knockBackDefense": 0.03, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 4, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "min": 1, "max": 2 }, { "item": "ice", "min": 1, "max": 2 } ], "special": 0, "paticularColor": [ 255, 0, 200, 255 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/iron_zombie.json ================================================ { "iron_zombie": { "ai": "Zombie", "textureData": "iron_zombie.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 65, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "zombie_say1", "zombie_say2", "zombie_say3" ], "hurtSounds": [ "blaze_death", "blaze_hit1", "blaze_hit2", "blaze_hit3" ], "loots": [ { "item": "rotten_flesh", "count": [ 1, 4 ] }, { "item": "magic_cell", "count": [ 1, 3 ] }, { "item": "iron_ingot", "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_iron_zombie", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/jungle_bat.json ================================================ { "jungle_bat": { "ai": "Bat", "textureData": "jungle_bat.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 72, "gfxHeight": 46, "gfxOffsetX": -20, "gfxOffsetY": -7, "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "BOX", "maxSpeed": 4.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 6, "attack": 7, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "bat_death", "bat_hurt1", "bat_hurt2", "bat_hurt3" ], "loots": [ { "item": "gray_feather", "count": [ 4, 8 ] } ], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "gore": "gore_jungle_bat", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_bat.json ================================================ { "large_bat": { "ai": "LargeBat", "textureData": "large_bat.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 96, "gfxHeight": 96, "gfxOffsetX": -32, "gfxOffsetY": -32, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 6, "attack": 17, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 12, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "bat_death", "bat_hurt1", "bat_hurt2", "bat_hurt3" ], "drops": [ { "item": "blue_crystal", "min": 1, "max": 2 } ], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "gore": "gore_bat", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_black_slime.json ================================================ { "large_black_slime": { "ai": "Slime", "textureData": "large_black_slime.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -4, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 50, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 4, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 2, 5 ] } ], "special": 0, "paticularColor": [ 255, 77, 77, 77 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_block_slime.json ================================================ { "large_block_slime": { "ai": "BlockSlime", "textureData": "large_block_slime.png", "type": "NORMAL", "width": 48, "height": 48, "gfxWidth": 64, "gfxHeight": 64, "gfxOffsetX": -8, "gfxOffsetY": -16, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "min": 1, "max": 4 }, { "item": "slime_block", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 120, 200, 100 ], "spawn": "LAND", "magicRate": 50, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_desert_slime.json ================================================ { "large_desert_slime": { "ai": "Slime", "textureData": "large_desert_slime.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -4, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 11.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 0, "attack": 8, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 3, 5 ] } ], "special": 0, "paticularColor": [ 255, 220, 160, 0 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_green_slime.json ================================================ { "large_green_slime": { "ai": "Slime", "textureData": "large_green_slime.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -4, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 4, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 2, 5 ] } ], "special": 0, "paticularColor": [ 255, 120, 200, 100 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_ice_slime.json ================================================ { "large_ice_slime": { "ai": "BlockSlime", "textureData": "large_ice_slime.png", "type": "NORMAL", "width": 48, "height": 48, "gfxWidth": 64, "gfxHeight": 64, "gfxOffsetX": -8, "gfxOffsetY": -16, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "min": 1, "max": 4 }, { "item": "slime_block", "min": 0, "max": 1 }, { "item": "ice", "min": 3, "max": 6 } ], "special": 0, "paticularColor": [ 255, 0, 200, 255 ], "spawn": "LAND", "magicRate": 50, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_jungle_bat.json ================================================ { "large_jungle_bat": { "ai": "Bat", "textureData": "large_jungle_bat.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 72, "gfxHeight": 46, "gfxOffsetX": -20, "gfxOffsetY": -7, "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "BOX", "maxSpeed": 3.5, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 6, "attack": 7, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "bat_death", "bat_hurt1", "bat_hurt2", "bat_hurt3" ], "loots": [ { "item": "gray_feather", "count": [ 1, 4 ] } ], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "gore": "gore_large_jungle_bat", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_spider.json ================================================ { "large_spider": { "ai": "LargeSpider", "textureData": "large_spider.png", "type": "NORMAL", "width": 32, "height": 48, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": -8, "gfxOffsetY": 0, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 8.0, "jumpForce": 3.0, "disappearTime": 750, "spawnCount": 1.0, "health": 70, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 6, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "drops": [ { "item": "red_crystal", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 77, 77, 77 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_tainted_slime.json ================================================ { "large_tainted_slime": { "ai": "TaintedSlime", "textureData": "large_tainted_slime.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -4, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 4, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 2, 5 ] } ], "special": 1, "paticularColor": [ 255, 144, 100, 194 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_waste_block_slime.json ================================================ { "large_waste_block_slime": { "ai": "BlockSlime", "textureData": "large_waste_block_slime.png", "type": "NORMAL", "width": 48, "height": 48, "gfxWidth": 64, "gfxHeight": 64, "gfxOffsetX": -8, "gfxOffsetY": -16, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "min": 1, "max": 4 }, { "item": "slime_block", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 160, 100, 60 ], "spawn": "LAND", "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/large_waste_slime.json ================================================ { "large_waste_slime": { "ai": "Slime", "textureData": "large_waste_slime.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -4, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 0, "attack": 6, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 4, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 2, 5 ] } ], "special": 0, "paticularColor": [ 255, 100, 70, 40 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/light_blue_butterfly.json ================================================ { "light_blue_butterfly": { "ai": "Butterfly", "textureData": "light_blue_butterfly.png", "type": "ANIMAL", "width": 16, "height": 16, "gfxWidth": 22, "gfxHeight": 22, "gfxOffsetX": -3, "gfxOffsetY": -3, "frameStyle": 0, "frames": 1, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 0.25, "health": 5, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 0, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "rabbit_hurt1", "rabbit_hurt1", "rabbit_hurt2", "rabbit_hurt3" ], "loots": [], "special": 0, "paticularColor": [ 255, 100, 150, 200 ], "spawn": "AIR", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/mad_skeleton.json ================================================ { "mad_skeleton": { "ai": "DungeonSkeleton", "textureData": "mad_skeleton.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 8, "attack": 20, "knockBack": 5, "knockBackDefense": 0.20, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "lead_ingot", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_mad_skeleton", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "data": { "tc": { "boneSizeIndex": 0, "style": 0 } } } } ================================================ FILE: npcs/mad_skeleton_armed.json ================================================ { "mad_skeleton_armed": { "ai": "DungeonSkeleton", "textureData": "mad_skeleton_armed.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.65, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 140, "defense": 12, "attack": 20, "knockBack": 5, "knockBackDefense": 0.30, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "wooden_arrow", "min": 0, "max": 2 }, { "item": "flesh_part", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_mad_skeleton_armed", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "data": { "tc": { "boneSizeIndex": 0, "style": 1 } } } } ================================================ FILE: npcs/mad_skeleton_tall.json ================================================ { "mad_skeleton_tall": { "ai": "DungeonSkeleton", "textureData": "mad_skeleton_tall.png", "type": "SMITE", "width": 24, "height": 64, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 10, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.65, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 150, "defense": 10, "attack": 25, "knockBack": 5, "knockBackDefense": 0.40, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "wooden_arrow", "min": 0, "max": 2 }, { "item": "flesh_part", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_mad_skeleton_tall", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "data": { "tc": { "boneSizeIndex": 1, "style": 2 } } } } ================================================ FILE: npcs/mad_skeleton_tall_armed.json ================================================ { "mad_skeleton_tall_armed": { "ai": "DungeonSkeleton", "textureData": "mad_skeleton_tall_armed.png", "type": "SMITE", "width": 24, "height": 64, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 10, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 150, "defense": 8, "attack": 34, "knockBack": 5, "knockBackDefense": 0.40, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "wooden_arrow", "min": 0, "max": 2 }, { "item": "copper_ingot", "min": 0, "max": 1 }, { "item": "flesh_part", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_mad_skeleton_tall_armed", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "data": { "tc": { "boneSizeIndex": 1, "style": 2 } } } } ================================================ FILE: npcs/mad_skeleton_tall_helmet_armed.json ================================================ { "mad_skeleton_tall_helmet_armed": { "ai": "DungeonSkeleton", "textureData": "mad_skeleton_tall_helmet_armed.png", "type": "SMITE", "width": 24, "height": 64, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 10, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 160, "defense": 12, "attack": 30, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "wooden_arrow", "min": 0, "max": 2 }, { "item": "steel_ingot", "min": 0, "max": 1 }, { "item": "flesh_part", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_mad_skeleton_tall_helmet_armed", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "data": { "tc": { "boneSizeIndex": 1, "style": 3 } } } } ================================================ FILE: npcs/magma_birdo.json ================================================ { "magma_birdo": { "ai": "MagmaBirdo", "textureData": "magma_birdo.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 96, "gfxHeight": 96, "gfxOffsetX": -32, "gfxOffsetY": -32, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 2, "attack": 18, "knockBack": 6, "knockBackDefense": 0.20, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": true, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [ { "item": "gray_feather", "count": [ 3, 7 ] }, { "item": "gunpowder", "count": [ 1, 3 ] } ], "special": 1, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "gore": "gore_magma_birdo", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/magma_elf.json ================================================ { "magma_elf": { "ai": "MagmaElf", "textureData": "magma_elf.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 48, "gfxHeight": 32, "gfxOffsetX": -8, "gfxOffsetY": 0, "frameStyle": 1, "frames": 2, "frameSpeed": 8, "maxSpeed": 2.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 10, "attack": 7, "knockBack": 5, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [], "special": 0, "paticularColor": [ 255, 255, 200, 0 ], "spawn": "LAND", "magicRate": 50, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/magma_slime.json ================================================ { "magma_slime": { "ai": "MagmaSlime", "textureData": "magma_slime.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 4.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 10, "attack": 12, "knockBack": 2, "knockBackDefense": 0.30, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "magma_cream", "count": [ 1, 3 ] } ], "special": 2, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/man_eater.json ================================================ { "man_eater": { "ai": "ManEater", "textureData": "man_eater.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 64, "gfxHeight": 52, "gfxOffsetX": -16, "gfxOffsetY": -10, "frameStyle": 0, "frames": 2, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.5, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 2, "attack": 7, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "gore": "gore_man_eater", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/meteor.json ================================================ { "meteor": { "ai": "Meteor", "textureData": "meteor.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 2, "attack": 18, "knockBack": 6, "knockBackDefense": 0.20, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [ { "item": "gunpowder", "count": [ 2, 5 ] } ], "special": 1, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/mini_ghast.json ================================================ { "mini_ghast": { "ai": "MiniGhast", "textureData": "mini_ghast.png", "type": "SMITE", "width": 48, "height": 48, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 2, "frameSpeed": 8, "maxSpeed": 1.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 70, "defense": 5, "attack": 10, "knockBack": 5, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": true, "noFixByBlock": true, "friendly": false, "exps": 2, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [ "ghast_moan1", "ghast_moan2", "ghast_moan3" ], "hurtSounds": [ "ghast_death", "affectionate_scream" ], "loots": [ { "item": "ghost_crystal" } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "spawnWall": "more_dungeons:stone_wall_white", "magicRate": 20, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 640 } } ================================================ FILE: npcs/mummy.json ================================================ { "mummy": { "ai": "Zombie", "textureData": "mummy.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "zombie_say1", "zombie_say2", "zombie_say3" ], "hurtSounds": [ "zombie_death", "zombie_hurt1", "zombie_hurt2" ], "noBurnSound": true, "loots": [ { "item": "rotten_flesh", "count": [ 1, 4 ] }, { "item": "string", "count": [ 1, 4 ] } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_mummy", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/phantom.json ================================================ { "phantom": { "ai": "Phantom", "textureData": "phantom.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 96, "gfxHeight": 96, "gfxOffsetX": -32, "gfxOffsetY": -32, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 2, "attack": 18, "knockBack": 6, "knockBackDefense": 0.20, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "phantom_death", "phantom_hurt1", "phantom_hurt2", "phantom_hurt3" ], "loots": [ { "item": "phantom_membrane", "count": [ 1, 3 ] }, { "item": "dark_shadow_part", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 50, 50, 50 ], "spawn": "AIR", "gore": "gore_phantom", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/pig.json ================================================ { "pig": { "ai": "Animal", "textureData": "pig.png", "type": "ANIMAL", "width": 48, "height": 40, "gfxWidth": 64, "gfxHeight": 48, "gfxOffsetX": -8, "gfxOffsetY": -8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 12, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 3, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "pig_say1", "pig_say2", "pig_say3" ], "hurtSounds": [ "pig_death", "pig_say1", "pig_say2", "pig_say3" ], "loots": [ { "item": "raw_porkchop", "count": [ 1, 3 ] } ], "burnLoots": [ { "item": "cooked_porkchop", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_pig", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/pufferfish.json ================================================ { "pufferfish": { "ai": "Pufferfish", "textureData": "pufferfish.png", "type": "ANIMAL", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 6.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 10, "attack": 10, "knockBack": 4, "knockBackDefense": 0.30, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "pufferfish_hurt1", "pufferfish_hurt1", "pufferfish_hurt2" ], "loots": [ { "item": "pufferfish" }, { "item": "bone", "possibility": 0.5 }, { "item": "bone_meal", "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "WATER", "magicRate": 0, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/purple_slime.json ================================================ { "purple_slime": { "ai": "Slime", "textureData": "purple_slime.png", "type": "NORMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 4.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 50, "defense": 0, "attack": 7, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 6, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 1, 5 ] } ], "special": 0, "paticularColor": [ 255, 60, 0, 60 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/ragged_mage.json ================================================ { "ragged_mage": { "ai": "RaggedMage", "textureData": "ragged_mage.png", "type": "NORMAL", "width": 28, "height": 48, "gfxWidth": 40, "gfxHeight": 48, "gfxOffsetX": -6, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 0.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 130, "defense": 10, "attack": 20, "knockBack": 2, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "shulker_hit1", "shulker_hit1" ], "drops": [ { "item": "red_crystal", "min": 0, "max": 1 }, { "item": "yellow_crystal", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 33, 33, 33 ], "spawn": "LAND", "gore": "gore_evoker", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 720 } } ================================================ FILE: npcs/red_butterfly.json ================================================ { "red_butterfly": { "ai": "Butterfly", "textureData": "red_butterfly.png", "type": "ANIMAL", "width": 16, "height": 16, "gfxWidth": 22, "gfxHeight": 22, "gfxOffsetX": -3, "gfxOffsetY": -3, "frameStyle": 0, "frames": 1, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 0.25, "health": 5, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 0, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "rabbit_hurt1", "rabbit_hurt1", "rabbit_hurt2", "rabbit_hurt3" ], "loots": [], "special": 0, "paticularColor": [ 255, 200, 0, 0 ], "spawn": "AIR", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/red_mage.json ================================================ { "red_mage": { "ai": "RedMage", "textureData": "red_mage.png", "type": "NORMAL", "width": 28, "height": 48, "gfxWidth": 40, "gfxHeight": 48, "gfxOffsetX": -6, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 0.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 130, "defense": 4, "attack": 10, "knockBack": 2, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "shulker_hit1", "shulker_hit1" ], "drops": [ { "item": "emerald", "min": 0, "max": 1 }, { "item": "red_crystal", "min": 0, "max": 1 }, { "item": "yellow_crystal", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 33, 33, 33 ], "spawn": "LAND", "gore": "gore_evoker", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 720 } } ================================================ FILE: npcs/red_mushroom_cow.json ================================================ { "red_mushroom_cow": { "ai": "Animal", "textureData": "red_mushroom_cow.png", "type": "ANIMAL", "width": 60, "height": 60, "gfxWidth": 64, "gfxHeight": 72, "gfxOffsetX": -2, "gfxOffsetY": -12, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 15, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 3, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "cow_say1", "cow_say2", "cow_say3" ], "hurtSounds": [ "cow_hurt1", "cow_hurt1", "cow_hurt2", "cow_hurt3" ], "loots": [ { "item": "raw_beef", "count": [ 1, 3 ] }, { "item": "leather", "count": [ 1, 3 ], "possibility": 0.5 }, { "item": "red_mushroom", "count": [ 1, 4 ] } ], "burnLoots": [ { "item": "steak", "count": [ 1, 3 ] }, { "item": "leather", "count": [ 1, 3 ], "possibility": 0.5 }, { "item": "red_mushroom", "count": [ 1, 4 ] } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_red_mushroom_cow", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/red_phantom.json ================================================ { "red_phantom": { "ai": "RedPhantom", "textureData": "red_phantom.png", "type": "SMITE", "width": 32, "height": 32, "gfxWidth": 96, "gfxHeight": 96, "gfxOffsetX": -32, "gfxOffsetY": -32, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 2, "attack": 18, "knockBack": 6, "knockBackDefense": 0.20, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "phantom_death", "phantom_hurt1", "phantom_hurt2", "phantom_hurt3" ], "drops": [ { "item": "phantom_membrane", "min": 1, "max": 3 }, { "item": "dark_shadow_part", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 50, 50, 50 ], "spawn": "AIR", "gore": "gore_phantom", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/rock_man.json ================================================ { "rock_man": { "ai": "RockMan", "textureData": "rock_man.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.5, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 19, "attack": 13, "knockBack": 10, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 22, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "gold_ingot", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_angry_skeleton", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/rolling_fire_ball.json ================================================ { "rolling_fire_ball": { "ai": "RollingFireBall", "textureData": "rolling_fire_ball.png", "type": "SMITE", "width": 48, "height": 48, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 120, "defense": 2, "attack": 18, "knockBack": 6, "knockBackDefense": 0.20, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "drops": [ { "item": "gunpowder", "min": 2, "max": 5 } ], "special": 1, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/sheep.json ================================================ { "sheep": { "ai": "Sheep", "textureData": "sheep.png", "type": "ANIMAL", "width": 48, "height": 40, "gfxWidth": 64, "gfxHeight": 48, "gfxOffsetX": -8, "gfxOffsetY": -8, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 15, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 3, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "sheep_say1", "sheep_say2", "sheep_say3" ], "hurtSounds": [ "sheep_say1", "sheep_say1", "sheep_say2", "sheep_say3" ], "loots": [ { "item": "wool_white", "count": [ 2, 4 ] }, { "item": "raw_mutton", "count": [ 1, 3 ] } ], "burnLoots": [ { "item": "wool_white", "count": [ 2, 4 ] }, { "item": "cooked_mutton", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_sheep", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/shulker.json ================================================ { "shulker": { "ai": "Shulker", "textureData": "shulker.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 32, "gfxHeight": 48, "gfxOffsetX": 0, "gfxOffsetY": -8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 75, "defense": 7, "attack": 17, "knockBack": 6, "knockBackDefense": 0.80, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "shulker_hit1", "shulker_hit1" ], "loots": [ ], "special": 0, "paticularColor": [ 255, 120, 100, 80 ], "spawn": "AIR", "gore": "gore_shulker", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false, "checkTargetDistance": 666 } } ================================================ FILE: npcs/skeleton.json ================================================ { "skeleton": { "ai": "BoneArcher", "textureData": "skeleton.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 50, "defense": 6, "attack": 12, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "loots": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "wooden_arrow", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_skull", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/skeleton_assaulter.json ================================================ { "skeleton_assaulter": { "ai": "SkeletonAssaulter", "textureData": "skeleton_assaulter.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 6, "attack": 30, "knockBack": 2, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 25, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "wooden_arrow", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_skeleton_assaulter", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/skeleton_blue_armed.json ================================================ { "skeleton_blue_armed": { "ai": "DungeonSkeleton", "textureData": "skeleton_blue_armed.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 7, "attack": 12, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "wooden_arrow", "min": 0, "max": 2 }, { "item": "iron_ingot", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_skeleton_blue_armed", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/skeleton_blue_armed_masked.json ================================================ { "skeleton_blue_armed_masked": { "ai": "DungeonSkeleton", "textureData": "skeleton_blue_armed_masked.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 110, "defense": 7, "attack": 12, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "wooden_arrow", "min": 0, "max": 2 }, { "item": "tin_ingot", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_skeleton_blue_armed_masked", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/skeleton_blue_knight.json ================================================ { "skeleton_blue_knight": { "ai": "DungeonSkeleton", "textureData": "skeleton_blue_knight.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 120, "defense": 16, "attack": 18, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "wooden_arrow", "min": 0, "max": 2 }, { "item": "knight_ingot", "min": 1, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_skeleton_blue_knight", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/skeleton_fire_armed.json ================================================ { "skeleton_fire_armed": { "ai": "DungeonSkeleton", "textureData": "skeleton_fire_armed.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 150, "defense": 13, "attack": 24, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "wooden_arrow", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_skeleton_fire_armed", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/skeleton_fire_armed_swordsman.json ================================================ { "skeleton_fire_armed_swordsman": { "ai": "DungeonSkeleton", "textureData": "skeleton_fire_armed_swordsman.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 130, "defense": 8, "attack": 28, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "iron_ingot", "min": 0, "max": 1 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_skeleton_fire_armed_swordsman", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/skeleton_guard.json ================================================ { "skeleton_guard": { "ai": "SkeletonGuard", "textureData": "skeleton_guard.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 6, "attack": 12, "knockBack": 5, "knockBackDefense": 0.50, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 5 }, { "item": "wooden_arrow", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_skeleton_guard", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/small_fire_hell_eater.json ================================================ { "small_fire_hell_eater": { "ai": "FireHellEater", "textureData": "small_fire_hell_eater.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 48, "gfxHeight": 32, "gfxOffsetX": -8, "gfxOffsetY": 0, "frameStyle": 0, "frames": 2, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 4.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 8, "defense": 6, "attack": 16, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": true, "noFixByBlock": true, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [], "special": 2, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "gore": "gore_small_hell_eater", "magicRate": 200, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/small_hell_eater.json ================================================ { "small_hell_eater": { "ai": "HellEater", "textureData": "small_hell_eater.png", "type": "NORMAL", "width": 32, "height": 32, "gfxWidth": 48, "gfxHeight": 32, "gfxOffsetX": -8, "gfxOffsetY": 0, "frameStyle": 0, "frames": 2, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.5, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 10, "defense": 6, "attack": 16, "knockBack": 4, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [], "special": 1, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "AIR", "gore": "gore_small_hell_eater", "magicRate": 200, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/snow_guardian.json ================================================ { "snow_guardian": { "ai": "SnowGuardian", "textureData": "snow_guardian.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 16, "knockBack": 5, "knockBackDefense": 0.50, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 8, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [ { "item": "ice_element" } ], "special": 1, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "AIR", "spawnWall": "aurora_block", "magicRate": 100, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/snow_guardian_archer.json ================================================ { "snow_guardian_archer": { "ai": "SnowGuardianArcher", "textureData": "snow_guardian.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 16, "knockBack": 5, "knockBackDefense": 0.50, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 8, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [], "special": 1, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "AIR", "spawnWall": "aurora_block", "magicRate": 100, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/snow_queen.json ================================================ { "snow_queen": { "ai": "SnowQueen", "textureData": "snow_queen.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 2100, "defense": 6, "attack": 20, "knockBack": 5, "knockBackDefense": 0.50, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 350, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [ { "item": "snow_queen_loot" }, { "item": "ice_bow" }, { "item": "blue_ice", "count": [ 12, 16 ] }, { "item": "diamond", "count": [ 1, 2 ] }, { "item": "ice_element", "count": [ 32, 48 ] } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "isBoss": true, "noShowHp": true, "magicRate": 1, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/snow_slime.json ================================================ { "snow_slime": { "ai": "Slime", "textureData": "snow_slime.png", "type": "NORMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 16, "defense": 0, "attack": 4, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 1, 2 ] } ], "special": 0, "paticularColor": [ 255, 160, 220, 255 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/spider.json ================================================ { "spider": { "ai": "Fighter", "textureData": "spider.png", "type": "ARTHROPODS", "width": 32, "height": 28, "gfxWidth": 48, "gfxHeight": 32, "gfxOffsetX": -8, "gfxOffsetY": -4, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 6.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 6, "attack": 8, "knockBack": 3, "knockBackDefense": 0.30, "gravity": true, "climbWall": true, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "spider_say1", "spider_say2", "spider_say3" ], "hurtSounds": [ "spider_death", "spider_say1", "spider_say2", "spider_say3" ], "loots": [ { "item": "string", "count": [ 1, 4 ] }, { "item": "spider_eye", "count": [ 1, 2 ], "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 50, 50, 20 ], "spawn": "LAND", "gore": "gore_spider", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/squid.json ================================================ { "squid": { "ai": "Squid", "textureData": "squid.png", "type": "ANIMAL", "width": 20, "height": 20, "gfxWidth": 32, "gfxHeight": 48, "gfxOffsetX": -6, "gfxOffsetY": -14, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 0.25, "health": 10, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 3, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "rabbit_hurt1", "rabbit_hurt1", "rabbit_hurt2", "rabbit_hurt3" ], "loots": [ { "item": "ink_sac", "count": [ 2, 4 ] } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "WATER", "gore": "gore_squid", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/tainted_creeper.json ================================================ { "tainted_creeper": { "ai": "Creeper", "textureData": "tainted_creeper.png", "type": "NORMAL", "width": 24, "height": 50, "gfxWidth": 32, "gfxHeight": 64, "gfxOffsetX": -4, "gfxOffsetY": -14, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 8, "attack": 10, "knockBack": 2, "knockBackDefense": 0.15, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "creeper_death", "creeper1", "creeper2", "creeper3" ], "loots": [ { "item": "gunpowder", "count": [ 8, 12 ] }, { "item": "magic_cell", "count": [ 2, 3 ] }, { "item": "dark_shadow_part", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_tainted_creeper", "magicRate": 22, "checkPlayerTarget": true, "visionNoCrossTile": true } } ================================================ FILE: npcs/tainted_skeleton.json ================================================ { "tainted_skeleton": { "ai": "BoneArcher", "textureData": "tainted_skeleton.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 60, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "loots": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "fire_bullet", "min": 0, "max": 6 }, { "item": "dark_shadow_part", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_tainted_skeleton", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/tainted_slime.json ================================================ { "tainted_slime": { "ai": "TaintedSlime", "textureData": "tainted_slime.png", "type": "NORMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 4.0, "jumpForce": 12.0, "disappearTime": 750, "spawnCount": 1.0, "health": 50, "defense": 0, "attack": 8, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 1, 6 ] } ], "special": 1, "paticularColor": [ 255, 155, 88, 226 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/turtle.json ================================================ { "turtle": { "ai": "Animal", "textureData": "turtle.png", "type": "ANIMAL", "width": 32, "height": 24, "gfxWidth": 48, "gfxHeight": 32, "gfxOffsetX": -8, "gfxOffsetY": -8, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 0.5, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 35, "defense": 10, "attack": 1, "knockBack": 0, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 3, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "turtle_death", "turtle_hurt1", "turtle_hurt2", "turtle_hurt3" ], "loots": [ { "item": "scute", "count": [ 1, 4 ] }, { "item": "kelp", "count": [ 1, 3 ], "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_turtle", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/undead_miner.json ================================================ { "undead_miner": { "ai": "UndeadMiner", "textureData": "undead_miner.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 70, "defense": 7, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "drops": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "iron_pickaxe", "min": 0, "max": 1 }, { "item": "flesh_part", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_undead_miner", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/vampire_miner.json ================================================ { "vampire_miner": { "ai": "Zombie", "textureData": "vampire_miner.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.5, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 120, "defense": 7, "attack": 22, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 15, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "zombie_death", "zombie_hurt1", "zombie_hurt2" ], "drops": [ { "item": "blood", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 150, 150, 150 ], "spawn": "LAND", "gore": "gore_vampire_miner", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/villager_zombie.json ================================================ { "villager_zombie": { "ai": "Zombie", "textureData": "villager_zombie.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [ "zombie_say1", "zombie_say2", "zombie_say3" ], "hurtSounds": [ "zombie_death", "zombie_hurt1", "zombie_hurt2" ], "noBurnSound": true, "loots": [ { "item": "rotten_flesh", "count": [ 1, 4 ] } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_villager_zombie", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/vine_man_eater_body.json ================================================ { "vine_man_eater_body": { "ai": "Snake_Body", "textureData": "vine_man_eater_body.png", "type": "ARTHROPODS", "width": 44, "height": 32, "gfxWidth": 44, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 5.0, "jumpForce": 1.0, "disappearTime": 750, "spawnCount": 1.0, "health": 10, "defense": 10, "attack": 10, "knockBack": 10, "knockBackDefense": 99.0, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": true, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": true, "linkNpcId": "vine_man_eater_tail", "linkValue": 36, "saySounds": [], "hurtSounds": [], "loots": [], "special": 0, "paticularColor": [ 255, 100, 100, 100 ], "spawn": "AIR", "noShowHp": true } } ================================================ FILE: npcs/vine_man_eater_head.json ================================================ { "vine_man_eater_head": { "ai": "JungleSnake_Head", "textureData": "vine_man_eater_head.png", "type": "ARTHROPODS", "width": 50, "height": 32, "gfxWidth": 50, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 3.0, "jumpForce": 1.0, "disappearTime": 750, "spawnCount": 1.0, "health": 20, "defense": 10, "attack": 10, "knockBack": 10, "knockBackDefense": 99.0, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": true, "friendly": false, "exps": 20, "sunBurning": false, "angry": false, "antiLava": true, "linkNpcId": "vine_man_eater_body", "linkValue": 34, "linkCount": 24, "saySounds": [], "hurtSounds": [], "loots": [], "special": 0, "paticularColor": [ 255, 100, 100, 100 ], "spawn": "AIR", "magicRate": 10 } } ================================================ FILE: npcs/vine_man_eater_tail.json ================================================ { "vine_man_eater_tail": { "ai": "Snake_Body", "textureData": "vine_man_eater_tail.png", "type": "ARTHROPODS", "width": 54, "height": 40, "gfxWidth": 54, "gfxHeight": 40, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 5.0, "jumpForce": 1.0, "disappearTime": 750, "spawnCount": 1.0, "health": 10, "defense": 10, "attack": 10, "knockBack": 10, "knockBackDefense": 1.0, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": true, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": true, "linkValue": 46, "saySounds": [], "hurtSounds": [], "loots": [], "special": 0, "paticularColor": [ 255, 100, 100, 100 ], "spawn": "AIR", "noShowHp": true } } ================================================ FILE: npcs/waste_block_slime.json ================================================ { "waste_block_slime": { "ai": "BlockSlime", "textureData": "waste_block_slime.png", "type": "NORMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 2.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 20, "defense": 0, "attack": 5, "knockBack": 2, "knockBackDefense": 0.03, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 4, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "min": 1, "max": 2 } ], "special": 0, "paticularColor": [ 255, 160, 100, 60 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/waste_ghost.json ================================================ { "waste_ghost": { "ai": "WasteGhost", "textureData": "waste_ghost.png", "type": "SMITE", "width": 38, "height": 38, "gfxWidth": 38, "gfxHeight": 38, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "maxSpeed": 2.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 10, "attack": 7, "knockBack": 5, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "gore3", "gore1", "gore2" ], "loots": [], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "AIR", "magicRate": 50, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/waste_mummy.json ================================================ { "waste_mummy": { "ai": "Zombie", "textureData": "waste_mummy.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [ "zombie_say1", "zombie_say2", "zombie_say3" ], "hurtSounds": [ "zombie_death", "zombie_hurt1", "zombie_hurt2" ], "noBurnSound": true, "loots": [ { "item": "rotten_flesh", "count": [ 1, 4 ] }, { "item": "string", "min": 1, "max": 4 } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_waste_mummy", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/white_rabbit.json ================================================ { "white_rabbit": { "ai": "Animal", "textureData": "white_rabbit.png", "type": "ANIMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 6.0, "disappearTime": 750, "spawnCount": 1.0, "health": 10, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 2, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "rabbit_hurt1", "rabbit_hurt1", "rabbit_hurt2", "rabbit_hurt3" ], "loots": [ { "item": "rabbit_foot", "possibility": 0.5 }, { "item": "rabbit_hide", "count": [ 1, 2 ] }, { "item": "raw_rabbit", "possibility": 0.5 } ], "burnLoots": [ { "item": "rabbit_foot", "possibility": 0.5 }, { "item": "rabbit_hide", "count": [ 1, 2 ] }, { "item": "cooked_rabbit", "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_white_rabbit", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/wither_skeleton.json ================================================ { "wither_skeleton": { "ai": "WitherSkeleton", "textureData": "wither_skeleton.png", "type": "SMITE", "width": 24, "height": 64, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 10, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.5, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 100, "defense": 13, "attack": 20, "knockBack": 7, "knockBackDefense": 0.60, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 10, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "skeleton_death", "skeleton1", "skeleton2", "skeleton3" ], "loots": [ { "item": "bone", "min": 0, "max": 2 }, { "item": "coal", "min": 0, "max": 2 } ], "special": 0, "paticularColor": [ 255, 33, 33, 33 ], "spawn": "LAND", "gore": "gore_wither_skeleton", "magicRate": 25, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/wolf.json ================================================ { "wolf": { "ai": "Wolf", "textureData": "wolf.png", "type": "ANIMAL", "width": 48, "height": 48, "gfxWidth": 80, "gfxHeight": 64, "gfxOffsetX": -16, "gfxOffsetY": -16, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 6.0, "jumpForce": 8.0, "disappearTime": 750, "spawnCount": 1.0, "health": 40, "defense": 5, "attack": 5, "knockBack": 5, "knockBackDefense": 0.35, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 5, "sunBurning": false, "angry": true, "antiLava": false, "saySounds": [ "wolf_bark1", "wolf_bark2", "wolf_bark3" ], "hurtSounds": [ "wolf_death", "wolf_hurt1", "wolf_hurt2", "wolf_hurt3" ], "loots": [ { "item": "leather", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "magicRate": 0, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/worm_body.json ================================================ { "worm_body": { "ai": "Snake_Body", "textureData": "worm_body.png", "type": "ARTHROPODS", "width": 46, "height": 52, "gfxWidth": 46, "gfxHeight": 52, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 5.0, "jumpForce": 1.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 5, "attack": 25, "knockBack": 10, "knockBackDefense": 1.0, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": true, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [], "loots": [], "special": 0, "paticularColor": [ 255, 100, 100, 100 ], "spawn": "AIR", "noShowHp": true, "gore": "gore_worm_body" } } ================================================ FILE: npcs/worm_head.json ================================================ { "worm_head": { "ai": "HellDestroyer_Head", "textureData": "worm_head.png", "type": "ARTHROPODS", "width": 78, "height": 52, "gfxWidth": 78, "gfxHeight": 52, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 5.0, "jumpForce": 1.0, "disappearTime": 750, "spawnCount": 1.0, "health": 2800, "defense": 5, "attack": 25, "knockBack": 10, "knockBackDefense": 0.9, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": true, "friendly": false, "exps": 400, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [ "attack1", "attack2" ], "loots": [ { "item": "nether_destroyer_loot" }, { "item": "super_air_sword" }, { "item": "dungeon_eater" }, { "item": "ancient_sample", "count": [ 3, 4 ] }, { "item": "netherite_ingot", "count": [ 2, 3 ] } ], "special": 0, "paticularColor": [ 255, 100, 100, 100 ], "spawn": "AIR", "isBoss": true, "noShowHp": true, "gore": "gore_worm_head", "magicRate": 1, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/worm_tail.json ================================================ { "worm_tail": { "ai": "Snake_Body", "textureData": "worm_tail.png", "type": "ARTHROPODS", "width": 60, "height": 64, "gfxWidth": 60, "gfxHeight": 64, "gfxOffsetX": 0, "gfxOffsetY": 0, "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 5.0, "jumpForce": 1.0, "disappearTime": 750, "spawnCount": 1.0, "health": 80, "defense": 5, "attack": 25, "knockBack": 10, "knockBackDefense": 1.0, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": true, "friendly": false, "exps": 7, "sunBurning": false, "angry": false, "antiLava": true, "saySounds": [], "hurtSounds": [], "loots": [], "special": 0, "paticularColor": [ 255, 100, 100, 100 ], "spawn": "AIR", "noShowHp": true, "gore": "gore_worm_tail" } } ================================================ FILE: npcs/yellow_butterfly.json ================================================ { "yellow_butterfly": { "ai": "Butterfly", "textureData": "yellow_butterfly.png", "type": "ANIMAL", "width": 16, "height": 16, "gfxWidth": 22, "gfxHeight": 22, "gfxOffsetX": -3, "gfxOffsetY": -3, "frameStyle": 0, "frames": 1, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 5.0, "disappearTime": 750, "spawnCount": 0.25, "health": 5, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": false, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 0, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "rabbit_hurt1", "rabbit_hurt1", "rabbit_hurt2", "rabbit_hurt3" ], "loots": [], "special": 0, "paticularColor": [ 255, 200, 200, 0 ], "spawn": "AIR", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/yellow_rabbit.json ================================================ { "yellow_rabbit": { "ai": "Animal", "textureData": "yellow_rabbit.png", "type": "ANIMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 4, "frameSpeed": 6, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 6.0, "disappearTime": 750, "spawnCount": 1.0, "health": 10, "defense": 0, "attack": 1, "knockBack": 0, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 2, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "rabbit_hurt1", "rabbit_hurt1", "rabbit_hurt2", "rabbit_hurt3" ], "loots": [ { "item": "rabbit_foot", "possibility": 0.5 }, { "item": "rabbit_hide", "count": [ 1, 2 ] }, { "item": "raw_rabbit", "possibility": 0.5 } ], "burnLoots": [ { "item": "rabbit_foot", "possibility": 0.5 }, { "item": "rabbit_hide", "count": [ 1, 2 ] }, { "item": "cooked_rabbit", "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 100, 50 ], "spawn": "LAND", "gore": "gore_yellow_rabbit", "magicRate": 0, "checkPlayerTarget": false, "visionNoCrossTile": false } } ================================================ FILE: npcs/yellow_slime.json ================================================ { "yellow_slime": { "ai": "Slime", "textureData": "yellow_slime.png", "type": "NORMAL", "width": 24, "height": 24, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": -4, "gfxOffsetY": -8, "frameStyle": 1, "frames": 2, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 3.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 24, "defense": 0, "attack": 5, "knockBack": 2, "knockBackDefense": 0.05, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": false, "angry": false, "antiLava": false, "saySounds": [], "hurtSounds": [ "slime_attack1", "slime_attack1", "slime_attack2" ], "loots": [ { "item": "slimeball", "count": [ 1, 3 ] } ], "special": 0, "paticularColor": [ 255, 160, 160, 0 ], "spawn": "LAND", "magicRate": 80, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: npcs/zombie.json ================================================ { "zombie": { "ai": "Zombie", "textureData": "zombie.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 6, "attack": 14, "knockBack": 5, "knockBackDefense": 0.50, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": false, "exps": 5, "sunBurning": true, "angry": false, "antiLava": false, "saySounds": [ "zombie_say1", "zombie_say2", "zombie_say3" ], "hurtSounds": [ "zombie_death", "zombie_hurt1", "zombie_hurt2" ], "noBurnSound": true, "loots": [ { "item": "rotten_flesh", "count": [ 1, 4 ] } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_zombie", "magicRate": 30, "checkPlayerTarget": true, "visionNoCrossTile": false, "data": { "tc": { "message": "this is a test message!!", "testValue": 123 } } } } ================================================ FILE: npcs/zombie_pigman.json ================================================ { "zombie_pigman": { "ai": "Zpig", "textureData": "zombie_pigman.png", "type": "SMITE", "width": 24, "height": 46, "gfxWidth": 48, "gfxHeight": 48, "gfxOffsetX": 4, "gfxOffsetY": 8, "frameStyle": 1, "frames": 4, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 1.0, "jumpForce": 9.0, "disappearTime": 750, "spawnCount": 1.0, "health": 45, "defense": 7, "attack": 14, "knockBack": 5, "knockBackDefense": 0.10, "gravity": true, "climbWall": false, "foreground": false, "noFixByBlock": false, "friendly": true, "exps": 5, "sunBurning": false, "angry": true, "antiLava": true, "saySounds": [ "zpig1", "zpig2", "zpig3" ], "hurtSounds": [ "zpigdeath", "zpighurt1" ], "loots": [ { "item": "rotten_flesh", "count": [ 1, 4 ] }, { "item": "gold_nugget", "count": [ 1, 4 ], "possibility": 0.5 } ], "special": 0, "paticularColor": [ 255, 200, 50, 20 ], "spawn": "LAND", "gore": "gore_zombie_pigman", "magicRate": 60, "checkPlayerTarget": true, "visionNoCrossTile": false } } ================================================ FILE: package.json ================================================ { "id": "tc", "displayName": "TerraCraft", "version": "1.1.0", "description": "Vanilla Mod of TerraCraft.", "tips": "Vanilla Mod of TerraCraft.", "gameVersion": "Obsidian Edition", "useSaver": true, "authors": [ "BlueYoshi" ], "credits": "", "websites": [ { "title": "Github", "url": "https://github.com/skyblueyoshi/TerraCraft" }, { "title": "Homepage", "url": "http://blueyoshi.cn/terracraft" } ], "objectFolders": { "advancements": "advancements", "biome_types": "biome_types", "biomes": "biomes", "block_entity_ai": "block_entity_ai", "block_presets": "block_presets", "blocks": "blocks", "buffs": "buffs", "buildings": "buildings", "commands": "contents/commands", "effect_ai": "effect_ai", "effects": "effects", "enchantments": "enchantments", "item_ai": "item_ai", "items": "items", "liquids": "liquids", "mod_textures": "mod_textures", "npc_ai": "npc_ai", "npc_ai_global": "npc_ai_global", "npcs": "npcs", "player": "player", "projectile_ai": "projectile_ai", "projectile_ai_global": "projectile_ai_global", "projectiles": "projectiles", "recipe_config": "recipe_config", "recipes": "recipes", "skeletons": "contents/skeletons", "skins": "skins", "spawns": "spawns", "trees": "trees" } } ================================================ FILE: player/GPlayer.lua ================================================ ---@class TC.GPlayer:GlobalPlayer local GPlayer = class("GPlayer", GlobalPlayer) local InputControl = require("client.InputControl") local PlayerBoneInfo = require("bone2d.PlayerBoneInfo") local ControlAimMode = require("client.ControlAimMode") local cameraInGameInstance = require("client.CameraInGame").getInstance() local EnchantmentProxies = require("enchantments.EnchantmentProxies") local BuffProxies = require("buffs.BuffProxies") local AdvancementTriggers = require("advancements.AdvancementTriggers") local MiscHelper = require("util.MiscHelper") local NetworkProxy = require("network.NetworkProxy") local RPC_ID = require("network.RPC_ID") local SettingsData = require("settings.SettingsData") local DebugHelper = require("DebugHelper") local PlayerConstants = require("PlayerConstants") local GRAVITY = PlayerConstants.GRAVITY local WALK_FORCE = PlayerConstants.WALK_FORCE local TURN_FORCE = PlayerConstants.TURN_FORCE local DECELERATE_STOP = PlayerConstants.DECELERATE_STOP local DECELERATE_STOP_AIR = PlayerConstants.DECELERATE_STOP_AIR local MAX_SPEED_WALK = PlayerConstants.MAX_SPEED_WALK local MAX_SPEED_UP = PlayerConstants.MAX_SPEED_UP local MAX_SPEED_DOWN = PlayerConstants.MAX_SPEED_DOWN local JUMP_SPEED = PlayerConstants.JUMP_SPEED local JUMP_UP_TIME = PlayerConstants.JUMP_UP_TIME local INTERACTION_DISTANCE = PlayerConstants.INTERACTION_DISTANCE local MOVE_RATE_DISTANCE = PlayerConstants.MOVE_RATE_DISTANCE local Behavior = { None = 0, Placing = 1, Digging = 2, SwordAttacking = 3, BowShooting = 4, StaffShooting = 5, GunShooting = 6, Eating = 7, LoadingLiquid = 8, PullingLiquid = 9, LoadingBottle = 10, Throwing = 11, PlacingWire = 12, RemovingWire = 13, LoadingBowl = 14, Shearing = 15, Seeding = 16, Ripening = 17, Farming = 18, } local ToolBehaviorProxies = { AXE = Behavior.Digging, PICKAXE = Behavior.Digging, DRILL = Behavior.Digging, SAW = Behavior.Digging, SWORD = Behavior.SwordAttacking, BOW = Behavior.BowShooting, CROSS_BOW = Behavior.GunShooting, GUN = Behavior.GunShooting, STAFF = Behavior.StaffShooting, WIRE_CUTTER = Behavior.RemovingWire, SHEARS = Behavior.Shearing, HOE = Behavior.Farming, BOOMERANG = Behavior.Throwing, ENDER_MIRROR = Behavior.Eating, } local BoneAction = { None = 0, Placing = 1, Digging = 2, SwordAttacking = 3, BowShooting = 4, StaffShooting = 5, GunShooting = 6, HoldLooking = 7, Eating = 8, } local MapOpType = { None = 0, LoadingLiquid = 1, PullingLiquid = 2, LoadingBottle = 3, LoadingBowl = 4, Farming = 5, Seeding = 6, Ripening = 7, } local FullDress = { diamond = { items = { Reg.ItemID("diamond_helmet"), Reg.ItemID("diamond_chestplate"), Reg.ItemID("diamond_leggings"), }, advancementID = Reg.AdvancementID("diamond_wear"), }, netherite = { items = { Reg.ItemID("nether_helmet"), Reg.ItemID("nether_chestplate"), Reg.ItemID("nether_leggings"), }, advancementID = Reg.AdvancementID("netherite_full_wear"), }, gold = { items = { Reg.ItemID("golden_helmet"), Reg.ItemID("golden_chestplate"), Reg.ItemID("golden_leggings"), }, advancementID = Reg.AdvancementID("gold_wear"), }, super_diamond = { items = { Reg.ItemID("super_diamond_helmet"), Reg.ItemID("super_diamond_chestplate"), Reg.ItemID("super_diamond_leggings"), }, defense = 8, advancementID = Reg.AdvancementID("super_diamond_wear"), }, lava = { items = { Reg.ItemID("lava_helmet"), Reg.ItemID("lava_chestplate"), Reg.ItemID("lava_leggings"), }, fireDefense = true, lighting = true, }, ancient = { items = { Reg.ItemID("ancient_helmet"), Reg.ItemID("ancient_chestplate"), Reg.ItemID("ancient_leggings"), }, defense = 12, attack = 7, fireDefense = true, lighting = true, speed = 0.3, advancementID = Reg.AdvancementID("ancient_wear"), }, knight = { items = { Reg.ItemID("knight_helmet"), Reg.ItemID("knight_chestplate"), Reg.ItemID("knight_leggings"), }, defense = 6, attack = 5, advancementID = Reg.AdvancementID("knight_wear"), }, magic_gold = { items = { Reg.ItemID("magic_gold_helmet"), Reg.ItemID("magic_gold_chestplate"), Reg.ItemID("magic_gold_leggings"), }, defense = 2, manaAddSpeed = 0.8, advancementID = Reg.AdvancementID("magic_gold_wear"), }, magic_silver = { items = { Reg.ItemID("magic_silver_helmet"), Reg.ItemID("magic_silver_chestplate"), Reg.ItemID("magic_silver_leggings"), }, defense = 2, manaAddSpeed = 0.8, }, magic_shadow = { items = { Reg.ItemID("magic_shadow_helmet"), Reg.ItemID("magic_shadow_chestplate"), Reg.ItemID("magic_shadow_leggings"), }, defense = 3, speed = 0.3, manaAddSpeed = 0.8, }, star = { items = { Reg.ItemID("star_helmet"), Reg.ItemID("star_chestplate"), Reg.ItemID("star_leggings"), }, defense = 4, attack = 5, lighting = true, manaAddSpeed = 0.9, advancementID = Reg.AdvancementID("star_wear"), }, flesh = { items = { Reg.ItemID("flesh_helmet"), Reg.ItemID("flesh_chestplate"), Reg.ItemID("flesh_leggings"), }, attack = 7, advancementID = Reg.AdvancementID("flesh_wear"), }, fine_tin = { items = { Reg.ItemID("fine_tin_helmet"), Reg.ItemID("fine_tin_chestplate"), Reg.ItemID("fine_tin_leggings"), }, attack = 3, speed = 0.2, }, shadow = { items = { Reg.ItemID("shadow_helmet"), Reg.ItemID("shadow_chestplate"), Reg.ItemID("shadow_leggings"), }, manaAddSpeed = 0.5, }, } local DressMappings = { {}, {}, {} } for k, v in pairs(FullDress) do for i, id in ipairs(v.items) do DressMappings[i][id] = k end end function GPlayer:Awake() -- player bone data --- @type JointBody2D self.bone = PlayerBoneInfo.createBySkinID(self.player.skinID) self.frontItemJoint = PlayerBoneInfo.getItemJoint(self.bone, false) self.backItemJoint = PlayerBoneInfo.getItemJoint(self.bone, true) self.frontItemCache = {} self.backItemCache = {} self.currentAction = BoneAction.None self.lastTickAction = BoneAction.None self.currentActionTick = 0 self.currentActionMaxTicks = 0 self.throwingBoomerang = false self.throwingBoomerangTime = 0 self.manaAddSpeed = 128 -- 先做3个饰品格子,以后谁有模组开发需求再加格子 self.accessoryInventory = Inventory.new(3) self.player.dataWatcher:AddInventory(self.accessoryInventory) self.trashInventory = Inventory.new(1) self.player.dataWatcher:AddInventory(self.trashInventory) self.BONE_ACTION = self.player.remoteDataWatcher:AddInteger(BoneAction.None, true) if NetMode.current == NetMode.Client then -- control and movement data self.left = false self.right = false self.up = false self.down = false self.jump = false self.justJump = false self.moving = false self.jumpUpTime = 0 self.swimTime = 0 self.walkingSoundTime = 0 self.lastAimOffsetX = 0 self.lastAimOffsetY = 0 self.aimOffsetX = 0 self.aimOffsetY = 0 self.showingAimPoint = false self.placeColdTime = 0 self.equipmentSkinCacheData = nil self.observeMode = false self.doorOpenColdTime = 0 self.doorCloseColdTime = 0 self.recipeBookHookUI = nil self.deathUI = nil self._clientInteractProxies = { [Behavior.Placing] = GPlayer.ClientPlacing, [Behavior.PlacingWire] = GPlayer.ClientPlacingWire, [Behavior.RemovingWire] = GPlayer.ClientRemovingWire, [Behavior.Eating] = GPlayer.ClientEating, [Behavior.LoadingLiquid] = GPlayer.ClientLoadingLiquid, [Behavior.LoadingBowl] = GPlayer.ClientLoadingBowl, [Behavior.PullingLiquid] = GPlayer.ClientPullingLiquid, [Behavior.LoadingBottle] = GPlayer.ClientLoadingBottle, [Behavior.Shearing] = GPlayer.ClientShearing, [Behavior.Seeding] = GPlayer.ClientSeeding, [Behavior.Ripening] = GPlayer.ClientRipening, [Behavior.Throwing] = GPlayer.ClientThrowing, [Behavior.Digging] = GPlayer.ClientDigging, [Behavior.Farming] = GPlayer.ClientFarming, [Behavior.SwordAttacking] = GPlayer.ClientSwordAttacking, [Behavior.BowShooting] = GPlayer.ClientBowShooting, [Behavior.GunShooting] = GPlayer.ClientGunShooting, [Behavior.StaffShooting] = GPlayer.ClientStaffShooting, } else self.player.health = PlayerConstants.StartHealth self.player.maxHealth = PlayerConstants.StartMaxHealth self.player.mana = PlayerConstants.StartMana self.player.maxMana = PlayerConstants.StartMaxMana self.player.foodLevel = PlayerConstants.StartFoodLevel self.player.foodSaturationLevel = PlayerConstants.StartSaturationLevel self._mapOpFunc = { [MapOpType.LoadingLiquid] = self.ServerLoadingLiquid, [MapOpType.PullingLiquid] = self.ServerPullingLiquid, [MapOpType.LoadingBottle] = self.ServerLoadingBottle, [MapOpType.LoadingBowl] = self.ServerLoadingBowl, [MapOpType.Farming] = self.ServerFarming, [MapOpType.Seeding] = self.ServerSeeding, [MapOpType.Ripening] = self.ServerRipen, } end -- animation event self._animationBeginFunc = { [BoneAction.Placing] = self.OnPlacingAnimationBegin, [BoneAction.Eating] = self.OnEatingAnimationBegin, [BoneAction.Digging] = self.OnDiggingAnimationBegin, [BoneAction.SwordAttacking] = self.OnSwordAttackingAnimationBegin, [BoneAction.BowShooting] = self.OnBowShootingAnimationBegin, [BoneAction.StaffShooting] = self.OnStaffShootingAnimationBegin, [BoneAction.GunShooting] = self.OnGunShootingAnimationBegin, [BoneAction.HoldLooking] = self.OnHoldLookingAnimationBegin, } self._animationUpdateFunc = { [BoneAction.Digging] = self.OnDiggingAnimationUpdate, [BoneAction.SwordAttacking] = self.OnSwordAttackingAnimationUpdate, [BoneAction.BowShooting] = self.OnBowShootingAnimationUpdate, [BoneAction.StaffShooting] = self.OnStaffShootingAnimationUpdate, [BoneAction.GunShooting] = self.OnGunShootingAnimationUpdate, [BoneAction.HoldLooking] = self.OnHoldLookingAnimationUpdate, } self._animationEndFunc = { [BoneAction.Placing] = self.OnPlacingAnimationEnd, [BoneAction.Eating] = self.OnEatingAnimationEnd, [BoneAction.Digging] = self.OnDiggingAnimationEnd, [BoneAction.SwordAttacking] = self.OnSwordAttackingAnimationEnd, [BoneAction.BowShooting] = self.OnBowShootingAnimationEnd, [BoneAction.StaffShooting] = self.OnStaffShootingAnimationEnd, [BoneAction.GunShooting] = self.OnGunShootingAnimationEnd, [BoneAction.HoldLooking] = self.OnHoldLookingAnimationEnd, } self.bone.animator:createEventAtTimePoint("Placing", 1.0):addListener( { self.OnPlacingAnimationEnd, self } ) self.bone.animator:createEventAtTimePoint("Eating", 1.0):addListener( { self.OnEatingAnimationEnd, self } ) self.bone.animator:createEventAtTimePoint("SwordAttacking", 1.0):addListener( { self.OnSwordAttackingAnimationEnd, self } ) end function GPlayer:Init() self.player:FinishAdvancement(Reg.AdvancementID("inventory")) DebugHelper.RunDebugStart(self.player) end function GPlayer:OnFirstTimeJoin() self:BackpackAddItemByIDName("grass_sword") self:BackpackAddItemByIDName("grass_axe") self:BackpackAddItemByIDName("grass_pickaxe") self:BackpackAddItemByIDName("torch", 16) end function GPlayer:BackpackAddItemByIDName(idName, count) if count == nil then count = 1 end self.player.backpackInventory:AddItemStack(ItemStack.new(ItemRegistry.GetItemByIDName(idName), count)) end function GPlayer:Motion() -- only control current client player if not self.player.isCurrentClientPlayer then return end local player = self.player local lastJump = self.jump player.defaultMaxSpeed = MAX_SPEED_WALK player.defaultJumpTime = JUMP_UP_TIME player.defaultFallSpeed = MAX_SPEED_DOWN player.defaultJumpSpeed = JUMP_SPEED local inputControl = InputControl.getInstance() if not player.dying then self.left = InputControl.isPressing("left") self.right = InputControl.isPressing("right") self.up = InputControl.isPressing("up") self.down = InputControl.isPressing("down") self.jump = InputControl.isPressing("jump") else -- do not move when dying self.left = false self.right = false self.up = false self.down = false self.jump = false end self.justJump = not lastJump and self.jump -- ignore if pressing two reverse direction buttons at the same time if self.left and self.right then self.left, self.right = false, false end if self.up and self.down then self.up, self.down = false, false end self.moving = self.left or self.right player.isDownPlatform = player.stand and self.down local stickyRate = 1.0 if player.inLiquid then --TODO:LiquidNS::Data &ld = liquidData->GetData(e.touchLiquidID); stickyRate = ld.stickyRate; stickyRate = 0.5 end local maxSpeed = player.defaultMaxSpeed * player.speedRate * stickyRate if self.moving then -- change direction player.direction = self.right -- walking local walkForce = WALK_FORCE * stickyRate -- TODO:walkForce *= blockData->GetData(hostBlockId).slipperiness local turnForce = TURN_FORCE local speedFlag = player.speedX > 0 player.speedX = player.speedX + (((self.right and speedFlag) or (self.left and not speedFlag)) and walkForce or turnForce) * (self.right and 1.0 or -1.0) else -- slowing down local decelerateForce = player.stand and DECELERATE_STOP or DECELERATE_STOP_AIR -- TODO:if (e.stand && hostBlockId > 0) decelerateForce *= hostSlipperiness; player.speedX = Utils.SlowSpeed1D(player.speedX, decelerateForce) end if player.speedX > maxSpeed then player.speedX = Utils.SlowSpeed1D(player.speedX, DECELERATE_STOP) if player.speedX < maxSpeed then player.speedX = maxSpeed end elseif player.speedX < -maxSpeed then player.speedX = Utils.SlowSpeed1D(player.speedX, DECELERATE_STOP) if player.speedX > -maxSpeed then player.speedX = -maxSpeed end end local gravity = GRAVITY local maxFallSpeed = player.defaultFallSpeed * player.fallSpeedRate local maxUpSpeed = MAX_SPEED_UP * player.jumpSpeedRate if player.inLiquid then maxFallSpeed = maxFallSpeed * stickyRate * 0.5 maxUpSpeed = maxFallSpeed end if not (self.jump and self.jumpUpTime > 0) then -- no press jump if player.inLiquid then player.speedY = player.speedY + gravity * stickyRate if self.jump then player.speedY = player.speedY - gravity self.swimTime = self.swimTime + 1 end else player.speedY = player.speedY + gravity self.swimTime = 0 end end if not player.inLiquid then self.swimTime = 0 end local maxJumpTime = math.ceil(player.defaultJumpTime * player.jumpRate) if player.stand and self.justJump then self.jumpUpTime = maxJumpTime elseif self.jump and not player.isCollisionTop then -- Jump from water if player.speedY < 0 and player.oldInLiquid and not player.inLiquid then self.jumpUpTime = math.ceil(maxJumpTime * 0.8) player.speedY = math.max(player.speedY, -maxUpSpeed) end self.jumpUpTime = math.max(self.jumpUpTime - 1, 0) else self.jumpUpTime = 0 end if self.jumpUpTime > 0 then player.speedY = -player.defaultJumpSpeed * player.jumpSpeedRate end player.speedY = math.min(math.max(player.speedY, -maxUpSpeed), maxFallSpeed) if self.observeMode then local s = 24 if self.left then player.speedX = -s elseif self.right then player.speedX = s else player.speedX = 0 end if self.up then player.speedY = -s elseif self.down then player.speedY = s else player.speedY = 0 end end player.ignoreCollisionWithTiles = self.observeMode if player.stand and math.abs(player.speedX) > 1.0 then self.walkingSoundTime = self.walkingSoundTime + 1 else self.walkingSoundTime = 0 end if player.stand then local blockID = MapUtils.GetFrontID(player.hostXi, player.hostYi) if blockID then local data = BlockUtils.GetData(blockID) if self.walkingSoundTime > 24 then self.walkingSoundTime = 0 if data.stepSoundId then SoundUtils.PlaySound(data.stepSoundId) end if data.stepSoundGroupId then SoundUtils.PlaySoundGroup(data.stepSoundGroupId) end end end end self.showingAimPoint = true -- aim by joystick if inputControl.aimMode == ControlAimMode.PressOnly then self.aimOffsetX = 0 self.aimOffsetY = 0 self.lastAimOffsetX = 0 self.lastAimOffsetY = 0 elseif inputControl.aimMode == ControlAimMode.LookDirectionOrShoot then self.lastAimOffsetX = 0 self.lastAimOffsetY = 0 if SettingsData.isMobileOperation then if inputControl.aimDistance > 0 then self.aimOffsetX = math.cos(inputControl.aimAngle) * INTERACTION_DISTANCE * 1.6 self.aimOffsetY = math.sin(inputControl.aimAngle) * INTERACTION_DISTANCE * 1.3 end else -- PC self.aimOffsetX = inputControl.pcMouseAtMapX - player.centerX self.aimOffsetY = inputControl.pcMouseAtMapY - player.centerY end elseif inputControl.aimMode == ControlAimMode.LookPositionOrUse then if SettingsData.isMobileOperation then if inputControl.aimInstanceClicked then self.lastAimOffsetX = self.aimOffsetX self.lastAimOffsetY = self.aimOffsetY end if inputControl.aimPressing then local angle = inputControl.aimAngle self.aimOffsetX = self.lastAimOffsetX + math.cos(angle) * MOVE_RATE_DISTANCE * inputControl.aimDistance self.aimOffsetY = self.lastAimOffsetY + math.sin(angle) * MOVE_RATE_DISTANCE * inputControl.aimDistance local tempVec2 = Vector2.new(self.aimOffsetX, self.aimOffsetY) inputControl.aimAngle = tempVec2.angle if tempVec2.length > INTERACTION_DISTANCE then self.aimOffsetX = math.cos(inputControl.aimAngle) * INTERACTION_DISTANCE self.aimOffsetY = math.sin(inputControl.aimAngle) * INTERACTION_DISTANCE end end else -- PC self.lastAimOffsetX = 0 self.lastAimOffsetY = 0 self.aimOffsetX = inputControl.pcMouseAtMapX - player.centerX self.aimOffsetY = inputControl.pcMouseAtMapY - player.centerY end end -- Mouse scrolling self:CheckScrollMouse() -- Drop items if InputControl.isInstantPressing("Drop") then local dropOne = true if InputControl.isPressing("Shift") then dropOne = false end NetworkProxy.RPCSendServerBound(Mod.current, RPC_ID.SB_DROP_ITEM_HELD, dropOne) end end function GPlayer:Update() local player = self.player PlayerBoneInfo.checkHandItem(self.backItemJoint, self:GetHeldSlot(), self.backItemCache) self.bone.joints.position = Vector2.new(player.centerX, player.bottomY) local animator = self.bone.animator animator:setBool("OnGround", player.stand) local speedRate = 0 local speed = math.abs(player.speedX) local lastSpeed = animator:getFloat("Speed") if speed > 3 then speedRate = 0.5 elseif player.isCollisionLeft or player.isCollisionRight then speedRate = 0 else speedRate = speed / 3.0 * 0.5 end if speedRate == 0 and lastSpeed ~= 0 then speedRate = Utils.SlowSpeed1D(lastSpeed, 0.1) end local heldSlot = self:GetHeldSlot() self.player.holdColdTime = 0 if heldSlot.hasStack then local itemStack = heldSlot:GetStack() local item = itemStack:GetItem() if item.isBlock then elseif item.isTool then self.player.holdColdTime = math.max(8, item.coldTime) end end if NetMode.current == NetMode.Server then -- drop item local trashSlot = self.trashInventory:GetSlot(0) if trashSlot.hasStack then player:DropItem(trashSlot:GetStack()) trashSlot:ClearStack() end local biomeID = player.biomeID AdvancementTriggers.getInstance():TriggerEnterBiome(player, biomeID) if self.throwingBoomerang then self.throwingBoomerangTime = self.throwingBoomerangTime - 1 if self.throwingBoomerangTime <= 0 then self.throwingBoomerangTime = 0 self.throwingBoomerang = false end end end DebugHelper.RunDebug(player) if NetMode.current == NetMode.Client then if player.isCurrentClientPlayer then self:ClientInteract() end end self.bone.joints.scale = Vector2.new(1.0, 1.0) animator:setFloat("Speed", speedRate) animator:setFloat("AirSpeed", player.speedY) self.bone.joints.flip = not player.facingDirection self.bone:update() self:UpdateBone() heldSlot = self:GetHeldSlot() if heldSlot.hasStack then heldSlot:GetStack():RunOnHeldEvent(player) end end function GPlayer:UpdateBone() local player = self.player local isServer = NetMode.current == NetMode.Server local heldSlot = self:GetHeldSlot() self.bone.animator:setLayerTimeScale(1, 1.0) self.lastTickAction = self.currentAction -- change the skin by equipment if not isServer then local changeSkinData = false if self.equipmentSkinCacheData == nil then changeSkinData = true else local equipmentInventory = player.equipmentInventory for i = 0, 5 do local slot = equipmentInventory:GetSlot(i) local cacheID = self.equipmentSkinCacheData[i + 1] if slot.hasStack then if slot:GetStack():GetItem().id ~= cacheID then changeSkinData = true break end elseif cacheID ~= 0 then changeSkinData = true break end end end if changeSkinData then -- save equipment data to cache self.equipmentSkinCacheData = {} local equipmentInventory = player.equipmentInventory for i = 0, 5 do local slot = equipmentInventory:GetSlot(i) if slot.hasStack then self.equipmentSkinCacheData[i + 1] = slot:GetStack():GetItem().id else self.equipmentSkinCacheData[i + 1] = 0 end end local HAT_INDICES = { 3, 0 } local CLOTH_INDICES = { 4, 1 } local PANT_INDICES = { 5, 2 } local hatTex, clothTex, pantTex local showHair = true for i = 1, 2 do local index = HAT_INDICES[i] local slot = equipmentInventory:GetSlot(index) if slot.hasStack and slot:GetStack():GetItem().toolType == "HELMET" then hatTex = slot:GetStack():GetItem().entityTextureLocation showHair = slot:GetStack():GetItem().showHair break end end for i = 1, 2 do local index = CLOTH_INDICES[i] local slot = equipmentInventory:GetSlot(index) if slot.hasStack and slot:GetStack():GetItem().toolType == "CHESTPLATE" then clothTex = slot:GetStack():GetItem().entityTextureLocation break end end for i = 1, 2 do local index = PANT_INDICES[i] local slot = equipmentInventory:GetSlot(index) if slot.hasStack and slot:GetStack():GetItem().toolType == "LEGGINGS" then pantTex = slot:GetStack():GetItem().entityTextureLocation break end end PlayerBoneInfo.setSkinByID(self.bone, self.player.skinID) local skinTable = PlayerBoneInfo.getSkinTableByID(self.player.skinID) if not showHair then skinTable.hair = nil end if hatTex then skinTable.hat = hatTex end if clothTex then skinTable.cloth = clothTex end if pantTex then skinTable.pant = pantTex end PlayerBoneInfo.setSkin(self.bone, skinTable) end end if self.currentAction == BoneAction.None then -- client: using current action by specify item -- server: get the new action from client side self.currentAction = player.remoteDataWatcher:GetInteger(self.BONE_ACTION) self.currentActionTick = 0 self.currentActionMaxTicks = 0 local beginFunc = self._animationBeginFunc[self.currentAction] if beginFunc then beginFunc(self) else self.currentAction = BoneAction.None end end if heldSlot.hasStack then local item = heldSlot:GetStack():GetItem() local holdingItemAnm = false if item.isBlock or item.isMaterial then holdingItemAnm = true end self.bone.animator:setBool("HoldingItem", holdingItemAnm) end if self.currentAction ~= BoneAction.None then local updateFunc = self._animationUpdateFunc[self.currentAction] if updateFunc then updateFunc(self) end if self.currentActionTick >= self.currentActionMaxTicks + 1 then local endFunc = self._animationEndFunc[self.currentAction] if endFunc then endFunc(self) end self.currentActionTick = 0 self.bone.animator:setTrigger("StopAction") else self.currentActionTick = self.currentActionTick + 1 end end if not isServer then -- swim animation (kicking legs) if not player.stand and self.swimTime > 0 then local angle1 = -Utils.SinValue(self.swimTime, 32) * 0.5 local angle2 = -angle1 local body = self.bone.joints:getJoint("base.body") local front_leg = body:getChild("front_leg") local back_leg = body:getChild("back_leg") front_leg.angle = angle1 back_leg.angle = angle2 end end if player.dying then self.bone.animator:setBool("Death", true) if not isServer then if self.deathUI == nil then self.deathUI = require("ui.DeathUI").new() -- TODO:关闭其他打开的GUI end end else self.bone.animator:setBool("Death", false) if not isServer then if self.deathUI ~= nil then self.deathUI:closeWindow() self.deathUI = nil end end end self.bone:update(false) end function GPlayer:OnSwordAttackingAnimationBegin() self.bone.animator:setTrigger("SwordAttacking") self.currentActionMaxTicks = self.player.holdColdTime end function GPlayer:EndAction() if self.currentAction ~= BoneAction.None then self.currentAction = BoneAction.None self.currentActionTick = 0 return true end return false end function GPlayer:OnSwordAttackingAnimationEnd() self:EndAction() end function GPlayer:OnSwordAttackingAnimationUpdate() local timeScale = self.currentActionMaxTicks > 0 and (60.0 / self.currentActionMaxTicks) or 1.0 self.bone.animator:setLayerTimeScale(1, timeScale) self:UseHeldItem() end function GPlayer:OnPlacingAnimationBegin() self.bone.animator:setTrigger("Placing") self.currentActionMaxTicks = 16 end function GPlayer:OnPlacingAnimationEnd() self:EndAction() end function GPlayer:OnEatingAnimationBegin() self.bone.animator:setTrigger("Eating") self.currentActionMaxTicks = 16 if NetMode.current == NetMode.Server then self:TryUseHeldItem() else local xi = Utils.Cell(self.player.centerX) local yi = Utils.Cell(self.player.centerY) SoundUtils.PlaySound(Reg.SoundID("drink"), xi, yi) end end function GPlayer:OnEatingAnimationEnd() self:EndAction() end function GPlayer:OnDiggingAnimationBegin() self.bone.animator:setTrigger("StopAction") self.currentActionMaxTicks = self.player.holdColdTime end function GPlayer:OnDiggingAnimationEnd() if self:EndAction() then self.player.direction = self.player.facingDirection end end function GPlayer:OnDiggingAnimationUpdate() if self.currentActionMaxTicks <= 0 then return end self:UpdateLookAngle() local body = self.bone.joints:getJoint("base.body") local head = body:getChild("head") local back_arm = body:getChild("back_arm") local rate = self.currentActionTick / self.currentActionMaxTicks local lookAngle = self:GetLookAngleInFacingDirection() back_arm.angle = lookAngle + math.pi * 0.5 * (2 * rate - 2.0) head.angle = (math.abs(lookAngle + math.pi / 2) - math.pi / 2) / 8 end function GPlayer:OnBowShootingAnimationBegin() self.bone.animator:setTrigger("StopAction") self.currentActionMaxTicks = self.player.holdColdTime self:UseHeldItem() end function GPlayer:OnBowShootingAnimationEnd() self:EndAction() end function GPlayer:OnBowShootingAnimationUpdate() if self.currentActionMaxTicks <= 0 then return end self:UpdateLookAngle() end function GPlayer:OnStaffShootingAnimationBegin() self.bone.animator:setTrigger("StopAction") self.currentActionMaxTicks = self.player.holdColdTime end function GPlayer:OnStaffShootingAnimationEnd() self:EndAction() end function GPlayer:OnStaffShootingAnimationUpdate() if self.currentActionMaxTicks <= 0 then return end self:UpdateLookAngle() self:UseHeldItem() end function GPlayer:OnGunShootingAnimationBegin() self.bone.animator:setTrigger("StopAction") self.currentActionMaxTicks = self.player.holdColdTime end function GPlayer:OnGunShootingAnimationEnd() self:EndAction() end function GPlayer:OnGunShootingAnimationUpdate() if self.currentActionMaxTicks <= 0 then return end self:UpdateLookAngle() self:UseHeldItem() end function GPlayer:OnHoldLookingAnimationBegin() self.bone.animator:setTrigger("StopAction") self.currentActionMaxTicks = 11 end function GPlayer:OnHoldLookingAnimationEnd() self:EndAction() end function GPlayer:OnHoldLookingAnimationUpdate() if self.currentActionMaxTicks <= 0 then return end self:UpdateLookAngle() end function GPlayer:CheckScrollMouse() local player = self.player if not player.isCurrentClientPlayer then return end local deltaY = InputControl.getInstance().pcMouseScrollDeltaY if deltaY == 0 then return end InputControl.getInstance().pcMouseScrollDeltaY = 0 local UIManager = require("ui.UIManager") if UIManager.getInstance():hasUIGroup(require("ui.UIDefault").GROUP_GAME_WINDOW) then return end if deltaY > 0 then if player.heldSlotIndex == 0 then player.heldSlotIndex = 9 else player.heldSlotIndex = player.heldSlotIndex - 1 end else if player.heldSlotIndex == 9 then player.heldSlotIndex = 0 else player.heldSlotIndex = player.heldSlotIndex + 1 end end end function GPlayer:CheckDoorAutoOperation() -- Auto door operation is only available in mobile. if not SettingsData.isMobileOperation then return end local player = self.player if self.doorOpenColdTime > 0 then self.doorOpenColdTime = self.doorOpenColdTime - 1 end if self.doorCloseColdTime > 0 then self.doorCloseColdTime = self.doorCloseColdTime - 1 end if math.abs(player.speedX) < 0.5 then return end local frontDir = player.speedX > 0 and 1 or -1 local xi = player.centerXi + frontDir * 2 local xi2 = player.centerXi - frontDir * 2 local yi = player.centerYi if self.doorOpenColdTime == 0 then local frontID = MapUtils.GetFrontID(xi, yi) if frontID > 0 then local blockData = BlockUtils.GetData(frontID) if blockData.isDoorClosed then player:RequestClickMap(xi, yi) self.doorOpenColdTime = 32 end end end if self.doorCloseColdTime == 0 then local frontID = MapUtils.GetFrontID(xi2, yi) if frontID > 0 then local blockData = BlockUtils.GetData(frontID) if blockData.isDoorOpened then player:RequestClickMap(xi2, yi) self.doorCloseColdTime = 32 end end end end function GPlayer:ClientInteract() local player = self.player if not player.isCurrentClientPlayer then return end if player.heldSlotIndexJustChanged then self.aimOffsetX = 0 self.aimOffsetY = 0 self.lastAimOffsetX = 0 self.lastAimOffsetY = 0 end local inputControl = InputControl.getInstance() local pressingNum = InputControl.getCurrentPressingKeyNum() if pressingNum ~= -1 and (pressingNum >= 0 and pressingNum <= 9) then if pressingNum == 0 then player.heldSlotIndex = 9 else player.heldSlotIndex = pressingNum - 1 end end if inputControl.isMapClicking then inputControl.isMapClicking = false local clickPosition = inputControl.touchMapPosition:clone() local realPosition = Vector2.new(clickPosition.x + MiscUtils.screenX, clickPosition.y + MiscUtils.screenY) if realPosition:getDistance(Vector2.new(player.centerX, player.centerY)) < INTERACTION_DISTANCE then local xi = Utils.Cell(realPosition.x) local yi = Utils.Cell(realPosition.y) player:RequestClickMap(xi, yi) end end -- hide wire render MapUtils.SetWireVisible(false) -- hide block preview MapUtils.ClearBlockRenderPreview() -- auto open or close door self:CheckDoorAutoOperation() player:SetSmartMode(SmartMode.None) local heldSlot = self:GetHeldSlot() local behavior = Behavior.None -- refresh the player action player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.None) -- refresh placing time if self.placeColdTime ~= 0 then self.placeColdTime = math.max(self.placeColdTime - 1, 0) end self.player.holdColdTime = 0 player.facingDirection = player.direction if heldSlot.hasStack then local itemStack = heldSlot:GetStack() local item = itemStack:GetItem() if item.isBlock then -- holding a block item behavior = Behavior.Placing elseif item.isTool then -- holding a tool item local tempBehavior = ToolBehaviorProxies[item.toolType] if tempBehavior ~= nil then behavior = tempBehavior end self.player.holdColdTime = math.max(8, item.coldTime) elseif item.isMaterial then -- holding a material item local itemID = item.id if item.isSeed then behavior = Behavior.Seeding elseif item.eatable then behavior = Behavior.Eating elseif MiscHelper.IsEmptyBucket(itemID) then behavior = Behavior.LoadingLiquid elseif MiscHelper.IsEmptyGrassBottle(itemID) then behavior = Behavior.LoadingBottle elseif MiscHelper.IsPullableBucket(itemID) then behavior = Behavior.PullingLiquid elseif MiscHelper.IsEmptyBowl(itemID) then behavior = Behavior.LoadingBowl elseif MiscHelper.IsBoneMeal(itemID) then behavior = Behavior.Ripening else local modItem = itemStack:GetModItem() if modItem then if modItem.isBossCaller then behavior = Behavior.Eating end end end else if item.type == ItemType.Projectile then if item.canThrow then behavior = Behavior.Throwing end elseif item.type == ItemType.Wire then behavior = Behavior.PlacingWire end end end if behavior ~= Behavior.None then local fun = self._clientInteractProxies[behavior] if fun then fun(self) end end end function GPlayer:ClientSwordAttacking() local inputControl = InputControl.getInstance() inputControl.aimMode = ControlAimMode.PressOnly local player = self.player local heldSlot = self:GetHeldSlot() if heldSlot.hasStack and (inputControl.aimTriggerUsing or inputControl.isPcMouseLeftPressingAtMap) then if not SettingsData.isMobileOperation then -- PC end player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.SwordAttacking) local item = heldSlot:GetStack():GetItem() player.holdColdTime = item.coldTime end end function GPlayer:ClientBowShooting() local inputControl = InputControl.getInstance() inputControl.aimMode = ControlAimMode.LookDirectionOrShoot local player = self.player local heldSlot = self:GetHeldSlot() if heldSlot.hasStack and (inputControl.aimTriggerUsing or inputControl.isPcMouseLeftPressingAtMap) then self.player.direction = self.player.facingDirection player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.BowShooting) local item = heldSlot:GetStack():GetItem() player.holdColdTime = item.coldTime end self:UpdateLookAngle() end function GPlayer:ClientStaffShooting() local inputControl = InputControl.getInstance() inputControl.aimMode = ControlAimMode.LookDirectionOrShoot local player = self.player local heldSlot = self:GetHeldSlot() if heldSlot.hasStack and (inputControl.aimTriggerUsing or inputControl.isPcMouseLeftPressingAtMap) then self.player.direction = self.player.facingDirection player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.StaffShooting) local item = heldSlot:GetStack():GetItem() player.holdColdTime = item.coldTime end end function GPlayer:ClientGunShooting() local inputControl = InputControl.getInstance() inputControl.aimMode = ControlAimMode.LookDirectionOrShoot local player = self.player local heldSlot = self:GetHeldSlot() player.lookAngle = 0 if not player.facingDirection then player.lookAngle = math.pi end if heldSlot.hasStack and (not SettingsData.isMobileOperation or inputControl.aimPressing) then self:UpdateLookAngle() self.player.direction = self.player.facingDirection if inputControl.aimTriggerUsing or inputControl.isPcMouseLeftPressingAtMap then player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.GunShooting) local item = heldSlot:GetStack():GetItem() player.holdColdTime = item.coldTime --else -- player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.HoldLooking) -- player.holdColdTime = 1 end end end function GPlayer:ClientPlacing() local xi, yi, op = self:CheckAimPositionInMap() local player = self.player local heldSlot = self:GetHeldSlot() if heldSlot.hasStack then local blockID = heldSlot:GetStack():GetItem().blockID if blockID > 0 then local canPlace = false if InputControl.getInstance().operatingWall then canPlace = MapUtils.CanPlaceWall(xi, yi, blockID) else canPlace = MapUtils.CanPlaceFront(xi, yi, blockID) end if canPlace and not SettingsData.isMobileOperation and not self:InInteractionDistanceIPos(xi, yi) then canPlace = false end local ox = self.player.centerX + self.aimOffsetX local oy = self.player.centerY + self.aimOffsetY MapUtils.SetBlockRenderPreview(blockID, ox, oy, canPlace, player.centerX, player.centerY) end end if heldSlot.hasStack and op == 1 then player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.Placing) -- skip placing if self.placeColdTime > 0 then return end if not SettingsData.isMobileOperation and not self:InInteractionDistanceIPos(xi, yi) then return end player:RequestPlaceBlock(xi, yi, player.heldSlotIndex, InputControl.getInstance().operatingWall) self.placeColdTime = 8 player.direction = xi * 16 + 8 > player.centerX end end function GPlayer:ClientPlacingWire() local xi, yi, op = self:CheckAimPositionInMap() local player = self.player local heldSlot = self:GetHeldSlot() MapUtils.SetWireVisible(true) -- skip placing if self.placeColdTime > 0 then return end if not SettingsData.isMobileOperation and not self:InInteractionDistanceIPos(xi, yi) then return end if heldSlot.hasStack and op == 1 then player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.Placing) if player:RequestPlaceWire(xi, yi, player.heldSlotIndex) then SoundUtils.PlaySoundGroup(Reg.SoundGroupID("cloth")) end self.placeColdTime = 8 player.direction = xi * 16 + 8 > player.centerX end end function GPlayer:_CanRemoveWire(xi, yi) local heldSlot = self:GetHeldSlot() if not heldSlot.hasStack then return false end local item = heldSlot:GetStack():GetItem() if item.toolType ~= "WIRE_CUTTER" then return false end return MapUtils.HasWire(xi, yi) end function GPlayer:ClientRemovingWire() local xi, yi, op = self:CheckAimPositionInMap() local player = self.player MapUtils.SetWireVisible(true) if not SettingsData.isMobileOperation and not self:InInteractionDistanceIPos(xi, yi) then return end if op == 1 then if self:_CanRemoveWire(xi, yi) then MapUtils.RemoveWire(xi, yi) player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.Placing) self.placeColdTime = 8 player.direction = xi * 16 + 8 > player.centerX NetworkProxy.RPCSendServerBound(Mod.current, RPC_ID.SB_REMOVE_WIRE, xi, yi) end end end function GPlayer:OnRemovingWireBound(xi, yi) if self:_CanRemoveWire(xi, yi) then MapUtils.RemoveWireAndDrop(xi, yi) SoundUtils.PlaySoundGroup(Reg.SoundGroupID("cloth"), xi, yi) else MapUtils.SyncUnit(xi, yi) end end function GPlayer:ClientEating() local inputControl = InputControl.getInstance() local player = self.player local heldSlot = self:GetHeldSlot() if heldSlot.hasStack and (inputControl.aimTriggerUsing or inputControl.isPcMouseLeftInstantDownAtMap) then local stack = heldSlot:GetStack() if stack:CanUse(player) then player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.Eating) end end end function GPlayer:ClientThrowing() local inputControl = InputControl.getInstance() inputControl.aimMode = ControlAimMode.LookDirectionOrShoot local player = self.player local heldSlot = self:GetHeldSlot() player.lookAngle = 0 if not player.facingDirection then player.lookAngle = math.pi end if heldSlot.hasStack and (inputControl.aimPressing or not SettingsData.isMobileOperation) then self:UpdateLookAngle() self.player.direction = self.player.facingDirection if inputControl.aimTriggerUsing or inputControl.isPcMouseLeftInstantDownAtMap then if self.placeColdTime > 0 then return end player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.Placing) self.placeColdTime = 16 NetworkProxy.RPCSendServerBound(Mod.current, RPC_ID.SB_PLAYER_THROWING, player.lookAngle) end end end function GPlayer:CheckThrowing(angle) local heldSlot = self:GetHeldSlot() if not heldSlot.hasStack then return false end local item = heldSlot:GetStack():GetItem() local player = self.player -- Check if item is boomerang if item.toolType == "BOOMERANG" then if self.throwingBoomerang then return false end local proj = ProjectileUtils.CreateFromPlayer(player, item.projectileID, player.centerX, player.centerY, item.speed * math.cos(angle), item.speed * math.sin(angle), item.baseAttack ) proj.targetTime = 100 proj.isCheckPlayer = false proj.isCheckNpc = true local mp = proj:GetModProjectile() if mp then mp.playerOwnerIndex = EntityIndex.new(player.entityIndex.entityID, player.entityIndex.uniqueID) self.throwingBoomerangTime = 1000 self.throwingBoomerang = true end else if not (item.type == ItemType.Projectile and item.canThrow) then return false end local proj = ProjectileUtils.CreateFromPlayer(player, item.projectileID, player.centerX, player.centerY, item.speed * math.cos(angle), item.speed * math.sin(angle), item.baseAttack ) proj.isCheckPlayer = false proj.isCheckNpc = true proj.targetTime = item.coldTime heldSlot:DecrStackSize(1) end return true end function GPlayer:OnThrowingServerBound(angle) local ok = self:CheckThrowing(angle) if not ok then self:GetHeldSlot():SyncAll() end end function GPlayer:ClientDoMapOp(opType, conditionFunc, removeOneOnSend) local xi, yi, op = self:CheckAimPositionInMap() local player = self.player local heldSlot = self:GetHeldSlot() if heldSlot.hasStack and op == 1 then if self.placeColdTime > 0 then return end if not SettingsData.isMobileOperation and not self:InInteractionDistanceIPos(xi, yi) then return end player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.Placing) if conditionFunc ~= nil and not conditionFunc(self, xi, yi, heldSlot) then return end if removeOneOnSend == nil then removeOneOnSend = true end if removeOneOnSend then heldSlot:DecrStackSize(1) end NetworkProxy.RPCSendServerBound(Mod.current, RPC_ID.SB_PLAYER_MAP_OPERATION, opType, xi, yi ) self.placeColdTime = 8 player.direction = xi * 16 + 8 > player.centerX end end ---_CanLoadLiquid ---@param xi int ---@param yi int ---@param heldSlot Slot function GPlayer:_CanLoadLiquid(xi, yi, heldSlot) if not (heldSlot.hasStack and MiscHelper.IsEmptyBucket(heldSlot:GetStack():GetItem().id)) then return false end local npcs = NpcUtils.SearchByRect(xi * 16 + 8, yi * 16 + 8, 1, 1) ---@param npc Npc for _, npc in each(npcs) do if MiscHelper.IsCow(npc.id) then return true end end local liquidID, amount = MapUtils.GetLiquidIDAmount(xi, yi) if not (liquidID > 0 and amount > 60) then return false end if MiscHelper.GetBucketIDFromLiquidID(liquidID) == 0 then return false end return true end function GPlayer:ServerLoadingLiquid(xi, yi) local player = self.player local heldSlot = self:GetHeldSlot() if not self:_CanLoadLiquid(xi, yi, heldSlot) then return false end local npcs = NpcUtils.SearchByRect(xi * 16 + 8, yi * 16 + 8, 1, 1) ---@param npc Npc for _, npc in each(npcs) do if MiscHelper.IsCow(npc.id) then heldSlot:DecrStackSize(1) local remain = player.backpackInventory:AddItemStack(ItemStack.new(ItemRegistry.GetItemByID(MiscHelper.GetMilkBucketID()))) if remain:Valid() then player:DropItem(remain) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("swim"), xi, yi) return true end end local liquidID = MapUtils.GetLiquidID(xi, yi) if liquidID == 0 then return false end heldSlot:DecrStackSize(1) MapUtils.RemoveLiquid(xi, yi) MapUtils.TriggerLiquid(xi - 1, yi) MapUtils.TriggerLiquid(xi, yi - 1) MapUtils.TriggerLiquid(xi, yi + 1) MapUtils.TriggerLiquid(xi + 1, yi) local liquidBucketID = MiscHelper.GetBucketIDFromLiquidID(liquidID) if liquidBucketID > 0 then local remain = player.backpackInventory:AddItemStack(ItemStack.new(ItemRegistry.GetItemByID(liquidBucketID))) if remain:Valid() then player:DropItem(remain) end end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("swim"), xi, yi) return true end function GPlayer:ClientLoadingLiquid() self:ClientDoMapOp(MapOpType.LoadingLiquid, self._CanLoadLiquid) end ---_GetLoadBowlNpc ---@param xi int ---@param yi int ---@return Npc function GPlayer:_GetLoadBowlNpc(xi, yi) local npcs = NpcUtils.SearchByRect(xi * 16 + 8, yi * 16 + 8, 1, 1) ---@param npc Npc for _, npc in each(npcs) do if MiscHelper.IsMushroomCow(npc.id) then return npc end end return nil end ---_CanLoadBowl ---@param xi int ---@param yi int ---@param heldSlot Slot function GPlayer:_CanLoadBowl(xi, yi, heldSlot) if not (heldSlot.hasStack and MiscHelper.IsEmptyBowl(heldSlot:GetStack():GetItem().id)) then return false end return self:_GetLoadBowlNpc(xi, yi) ~= nil end function GPlayer:ServerLoadingBowl(xi, yi) local player = self.player local heldSlot = self:GetHeldSlot() if not self:_CanLoadBowl(xi, yi, heldSlot) then return false end local npc = self:_GetLoadBowlNpc(xi, yi) if npc == nil then return false end heldSlot:DecrStackSize(1) local remain = player.backpackInventory:AddItemStack(ItemStack.new(ItemRegistry.GetItemByID(MiscHelper.GetMushroomBowl()))) if remain:Valid() then player:DropItem(remain) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("swim"), xi, yi) return true end function GPlayer:ClientLoadingBowl() self:ClientDoMapOp(MapOpType.LoadingBowl, self._CanLoadBowl) end function GPlayer:ClientShearing() --TODO: --self:ClientDoMapOp(MapOpType.Shearing, self._CanShearing) end ---_CanLoadBottle ---@param xi int ---@param yi int ---@param heldSlot Slot function GPlayer:_CanLoadBottle(xi, yi, heldSlot) local liquidID = MapUtils.GetLiquidID(xi, yi) if not (heldSlot.hasStack and MiscHelper.IsEmptyGrassBottle(heldSlot:GetStack():GetItem().id)) then return false end if not (liquidID > 0) then return false end return liquidID == Reg.LiquidID("water") end function GPlayer:ServerLoadingBottle(xi, yi) local player = self.player local heldSlot = self:GetHeldSlot() if not self:_CanLoadBottle(xi, yi, heldSlot) then return false end heldSlot:DecrStackSize(1) local remain = player.backpackInventory:AddItemStack(ItemStack.new(ItemRegistry.GetItemByID(Reg.ItemID("potion_water")))) if remain:Valid() then player:DropItem(remain) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("swim"), xi, yi) return true end function GPlayer:ClientLoadingBottle() self:ClientDoMapOp(MapOpType.LoadingBottle, self._CanLoadBottle) end function GPlayer:_CanPullLiquid(xi, yi, heldSlot) if not heldSlot.hasStack then return false end if MapUtils.IsSolid(xi, yi) then return false end local liquidPullID = MiscHelper.GetLiquidIDFromBucket(heldSlot:GetStack():GetItem().id) if liquidPullID == 0 then return end local liquidID = MapUtils.GetLiquidID(xi, yi) if liquidID == 0 or liquidID == liquidPullID then return true end return false end function GPlayer:ServerPullingLiquid(xi, yi) local player = self.player local heldSlot = self:GetHeldSlot() if not self:_CanPullLiquid(xi, yi, heldSlot) then return false end local liquidPullID = MiscHelper.GetLiquidIDFromBucket(heldSlot:GetStack():GetItem().id) MapUtils.SetLiquid(xi, yi, liquidPullID) MapUtils.TriggerLiquid(xi, yi) heldSlot:DecrStackSize(1) local remain = player.backpackInventory:AddItemStack(ItemStack.new(ItemRegistry.GetItemByID(MiscHelper.GetEmptyBucketID()))) if remain:Valid() then player:DropItem(remain) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("swim"), xi, yi) return true end function GPlayer:ClientPullingLiquid() self:ClientDoMapOp(MapOpType.PullingLiquid, self._CanPullLiquid) end ---_CanFarm ---@param xi int ---@param yi int ---@param heldSlot Slot function GPlayer:_CanFarm(xi, yi, heldSlot) if not heldSlot.hasStack then return false end if heldSlot:GetStack():GetItem().toolType ~= "HOE" then return end local blockID = MapUtils.GetFrontID(xi, yi) if blockID == 0 then return false end return MiscHelper.CanTransformToFramland(blockID) end function GPlayer:ServerFarming(xi, yi) local player = self.player local heldSlot = self:GetHeldSlot() if not self:_CanFarm(xi, yi, heldSlot) then return false end MapUtils.RemoveFront(xi, yi) MapUtils.PlaceFront(xi, yi, MiscHelper.GetFarmlandID()) if player.gameMode ~= GameMode.Creative then --heldSlot:GetStack():LoseDurable(1) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("farm"), xi, yi) return true end function GPlayer:ClientFarming() self:ClientDoMapOp(MapOpType.Farming, self._CanFarm, false) end ---@param xi int ---@param yi int ---@param heldSlot Slot function GPlayer:_CanSeeding(xi, yi, heldSlot) if not heldSlot.hasStack then return false end if not MapUtils.IsAreaValid(xi, yi, 1, 2) then return false end if MapUtils.HasFront(xi, yi) then return false end local downID = MapUtils.GetFrontID(xi, yi + 1) if downID == 0 then return false end if not MapUtils.IsSolid(xi, yi + 1) then return false end local item = heldSlot:GetStack():GetItem() if not (item.isSeed and item.blockID > 0) then return false end if not MapUtils.CanPlaceFront(xi, yi, item.blockID) then return false end local data = BlockUtils.GetData(downID) if not data:CanSeed(item.id) then return false end return true end function GPlayer:ServerSeeding(xi, yi) local heldSlot = self:GetHeldSlot() if not self:_CanSeeding(xi, yi, heldSlot) then return false end local item = heldSlot:GetStack():GetItem() MapUtils.PlaceFront(xi, yi, item.blockID) heldSlot:DecrStackSize(1) SoundUtils.PlaySoundGroup(Reg.SoundGroupID("farm"), xi, yi) return true end function GPlayer:ClientSeeding() self:ClientDoMapOp(MapOpType.Seeding, self._CanSeeding) end ---@param xi int ---@param yi int ---@param heldSlot Slot function GPlayer:_CanRipen(xi, yi, heldSlot) if not heldSlot.hasStack then return false end if not MiscHelper.IsBoneMeal(heldSlot:GetStack():GetItem().id) then return false end if not MapUtils.HasFront(xi, yi) then return false end return true end function GPlayer:ServerRipen(xi, yi) local heldSlot = self:GetHeldSlot() if not self:_CanRipen(xi, yi, heldSlot) then return false end MapUtils.DoRandomTick(xi, yi) heldSlot:DecrStackSize(1) SoundUtils.PlaySound(Reg.SoundID("shear"), xi, yi) return true end function GPlayer:ClientRipening() self:ClientDoMapOp(MapOpType.Ripening, self._CanRipen) end function GPlayer:OnMapOpServerBound(opType, xi, yi) local heldSlot = self:GetHeldSlot() local success = false local func = self._mapOpFunc[opType] if func ~= nil then success = func(self, xi, yi) end if not success then MapUtils.SyncUnit(xi, yi) heldSlot:SyncAll() end end function GPlayer.GetMiningToolType(toolType) if toolType == "DRILL" then return "PICKAXE" elseif toolType == "SAW" then return "AXE" end return toolType end function GPlayer:ClientDigging() local xi, yi, op = self:CheckAimPositionInMap() local player = self.player -- Just switch the held slot, skip process if player.heldSlotIndexJustChanged then return end local operatingWall = InputControl.getInstance().operatingWall local heldSlot = self:GetHeldSlot() if not heldSlot.hasStack then return end local stack = heldSlot:GetStack() local item = stack:GetItem() local isSmart = InputControl.getInstance().isSmart if not item.isTool then return end local toolType = GPlayer.GetMiningToolType(item.toolType) if isSmart then player:SetSmartMode(SmartMode.Digging, xi, yi, operatingWall, stack, toolType) end if op == 1 then local readyToRequest = false if isSmart and player.isSmartPositionFound then xi, yi = player:GetSmartPosition() readyToRequest = true else if SettingsData.isMobileOperation then readyToRequest = true else readyToRequest = self:InInteractionDistanceIPos(xi, yi) end end if readyToRequest then player:RequestDigBlock(xi, yi, player.heldSlotIndex, operatingWall, toolType) player.remoteDataWatcher:UpdateInteger(self.BONE_ACTION, BoneAction.Digging) end end end function GPlayer:InInteractionDistanceIPos(xi, yi) local player = self.player return player:GetDistance(xi * 16 + 8, yi * 16 + 8) < INTERACTION_DISTANCE end function GPlayer:OnRender() self.bone.joints:render(cameraInGameInstance.camera) local slot = self:GetHeldSlot() if slot.hasStack then local stack = slot:GetStack() stack:RunOnHeldRenderEvent(self.player) end end function GPlayer:TryUseHeldItem() local slot = self:GetHeldSlot() if slot.hasStack then local stack = slot:GetStack() if stack:CanUse(self.player) then self:UseHeldItem() end end end function GPlayer:UseHeldItem() local slot = self:GetHeldSlot() if slot.hasStack then local stack = slot:GetStack() stack:RunOnUsedEvent(self.player) local killed = false if stack:GetItem().maxDurable > 0 and stack.durable == 0 then if stack:RunOnDurableEmptyEvent(self.player) then slot:ClearStack() killed = true end end if not killed then local modItem = stack:GetModItem() if modItem ~= nil and modItem.IsKilledAfterUsed ~= nil and modItem:IsKilledAfterUsed() then if modItem.OnKilledAfterUsed then modItem:OnKilledAfterUsed(self.player) end slot:DecrStackSize(1) killed = true end end end end function GPlayer:GetHeldItemJoint() return self.bone.joints:getJoint("base.body.back_arm.back_hand.back_item") end function GPlayer:UpdateLookAngle() if NetMode.current == NetMode.Client and self.player.isCurrentClientPlayer then self.player.lookAngle = 0 if SettingsData.isMobileOperation then if InputControl.getInstance().aimDistance > 0 then self.player.lookAngle = Vector2.new(self.aimOffsetX, self.aimOffsetY).angle else if not self.player.facingDirection then self.player.lookAngle = math.pi end end else -- PC self.player.lookAngle = Vector2.new(self.aimOffsetX, self.aimOffsetY).angle end self:FacingByLookAngle() end end function GPlayer:FacingByLookAngle() if self.aimOffsetX ~= 0 then local lastFacing = self.player.facingDirection self.player.facingDirection = self.aimOffsetX > 0 if self.player.facingDirection ~= lastFacing then self.bone.joints.flip = not self.player.facingDirection self.bone:update(false) end end end function GPlayer:GetLookAngleInFacingDirection() local lookAngle = self.player.lookAngle if not (lookAngle > -math.pi * 0.5 and lookAngle < math.pi * 0.5) then lookAngle = math.pi - lookAngle lookAngle = Utils.FixAngle(lookAngle) end return lookAngle end function GPlayer:CheckAimPositionInMap() InputControl.getInstance().aimMode = ControlAimMode.LookPositionOrUse return self:GetAimPositionInMap() end function GPlayer:GetAimPositionInMap() local xi = Utils.Cell(self.player.centerX + self.aimOffsetX) local yi = Utils.Cell(self.player.centerY + self.aimOffsetY) local op = 0 if SettingsData.isMobileOperation then if InputControl.getInstance().aimTriggerUsing then op = 1 end else -- PC if InputControl.getInstance().isPcMouseLeftPressingAtMap then op = 1 elseif InputControl.getInstance().isPcMouseRightPressingAtMap then op = 2 end end return xi, yi, op end function GPlayer:GetHeldSlot() return self.player.backpackInventory:GetSlot(self.player.heldSlotIndex) end function GPlayer:GetAmmoIndexInBackpack(ammoID, ammoLevel, searchBest) local backpack = self.player.backpackInventory local count = backpack.slotCount local res = -1 local baseAmmoRes = -1 local minBestAmmoLevel = -1 for i = 1, count do local slot = backpack:GetSlot(i - 1) if slot.hasStack then local item = slot:GetStack():GetItem() if item.isProjectile and item.ammoID == ammoID then if not searchBest and item.ammoLevel == ammoLevel then res = i - 1 break elseif searchBest and item.ammoLevel > minBestAmmoLevel then minBestAmmoLevel = item.ammoLevel res = i - 1 elseif baseAmmoRes ~= -1 and item.ammoLevel == 0 then baseAmmoRes = i - 1 end end end end -- Use the same ammo level slot first. -- If no same level slot found, then we use level 0 slot. if res == -1 then res = baseAmmoRes end return res end function GPlayer:RecalculateProperties() local player = self.player local enchantmentProxies = EnchantmentProxies.getInstance() local buffProxies = BuffProxies.getInstance() player.baseAttack:Restore() player.baseDefense:Restore() self.manaAddSpeed = 128 if player.dying then return end DebugHelper.RunDebugProp(player) local heldSlot = self:GetHeldSlot() if heldSlot.hasStack then local stack = heldSlot:GetStack() local item = stack:GetItem() player.baseAttack.attack = player.baseAttack.attack + item.baseAttack.attack player.baseAttack.knockBack = player.baseAttack.knockBack + item.baseAttack.knockBack player.baseAttack.crit = player.baseAttack.crit + item.baseAttack.crit enchantmentProxies:OnHeld(stack, player) end local equipmentInventory = player.equipmentInventory local fullDressName = nil for i = 0, 2 do local equipmentSlot = equipmentInventory:GetSlot(i) if equipmentSlot.hasStack then local stack = equipmentSlot:GetStack() local item = stack:GetItem() player.baseDefense.defense = player.baseDefense.defense + item.defense enchantmentProxies:OnEquipped(i, stack, player) if i == 0 then fullDressName = DressMappings[i + 1][item.id] elseif fullDressName then local name = DressMappings[i + 1][item.id] if name ~= fullDressName then fullDressName = nil end end else fullDressName = nil end end if player.tickTime % 64 == 0 then local backpackInventory = player.backpackInventory for i = 0, backpackInventory.slotCount - 1 do local slot = backpackInventory:GetSlot(i) if slot.hasStack then enchantmentProxies:OnUpdateSecond(slot:GetStack(), player) end end for i = 0, 2 do local slot = equipmentInventory:GetSlot(i) if slot.hasStack then enchantmentProxies:OnUpdateSecond(slot:GetStack(), player) end end end buffProxies:OnUpdatePlayer(player) if fullDressName then self:OnFullDress(fullDressName) end if NetMode.current == NetMode.Server then -- food if player.gameMode ~= GameMode.Creative then local interval = 256 if math.abs(player.speedX) < 0.5 then interval = 1024 end if player.foodSaturationLevel > 0 then if player.tickTime % interval == 0 then player.foodSaturationLevel = player.foodSaturationLevel - 1 end else player.foodSaturationLevel = 0 if player.foodLevel > 0 then if player.tickTime % interval == 0 then player.foodLevel = player.foodLevel - 1 end else if player.tickTime % 32 == 0 then player:Strike(DeathReason.STARVE, Attack.new(1, 0, 0)) end end end end -- auto add hp if player.health < player.maxHealth then if player.foodLevel >= 90 then if player.foodLevel == 100 then if player.tickTime % 64 == 0 then player:Heal(1, false) end else if player.tickTime % 128 == 0 then player:Heal(1, false) end end end end -- auto add magic local maxAutoMana = math.floor(player.maxMana * 0.80) if player.mana < maxAutoMana then local sp = math.max(1, math.ceil(self.manaAddSpeed)) if player.tickTime % sp == 0 then local offset = math.min(4, maxAutoMana - player.mana) if offset > 0 then player:AddMagic(offset, false) end end end end for i = 1, self.accessoryInventory.slotCount do local slot = self.accessoryInventory:GetSlot(i - 1) if slot.hasStack then local stack = slot:GetStack() local modItem = stack:GetModItem() if modItem ~= nil and modItem.OnAccessoryUpdate ~= nil then modItem:OnAccessoryUpdate(player) end end end end function GPlayer:OnFullDress(fullDressName) local data = FullDress[fullDressName] if data == nil then return end local player = self.player if data.advancementID ~= nil then player:FinishAdvancement(data.advancementID) end if data.defense ~= nil then player.baseDefense.defense = player.baseDefense.defense + data.defense end if data.attack ~= nil then player.baseAttack.attack = player.baseAttack.attack + data.attack end if data.fireDefense then if player.tickTime % 64 == 0 then player:AddBuff(Reg.BuffID("fire_defense"), 100) end end if data.lighting then LightingUtils.Add(player.centerXi, player.centerYi, 32) end if data.speed ~= nil then player.speedRate = player.speedRate + data.speed if math.abs(player.speedX) > 2 then if player.tickTime % 8 == 0 then if player.stand then EffectUtils.Create(Reg.EffectID("smoke"), player.randX, player.bottomY, Utils.RandSym(0.25), Utils.RandSym(0.25), Utils.RandSym(0.1), 0.25) else EffectUtils.Create(Reg.EffectID("smoke"), player.randX, player.randY, -player.speedX / 8 + Utils.RandSym(0.5), -player.speedY / 8 + Utils.RandSym(0.5), Utils.RandSym(0.1), 0.5, 0.2) end end end end if data.manaAddSpeed ~= nil then self.manaAddSpeed = self.manaAddSpeed * data.manaAddSpeed end end function GPlayer:HasAccessory(itemID) for i = 1, self.accessoryInventory.slotCount do local slot = self.accessoryInventory:GetSlot(i - 1) if slot.hasStack then local stack = slot:GetStack() if stack:GetItem().id == itemID then return true end end end return false end function GPlayer:OnHitByNpc(npc) local player = self.player local enchantmentProxies = EnchantmentProxies.getInstance() for i = 0, 2 do local equipmentSlot = equipmentInventory:GetSlot(i) if equipmentSlot.hasStack then local stack = equipmentSlot:GetStack() enchantmentProxies:OnEquippedHitByNpc(i, stack, player, npc) end end end function GPlayer:OnHitByProjectile(projectile) local player = self.player local enchantmentProxies = EnchantmentProxies.getInstance() for i = 0, 2 do local equipmentSlot = equipmentInventory:GetSlot(i) if equipmentSlot.hasStack then local stack = equipmentSlot:GetStack() enchantmentProxies:OnEquippedHitByProjectile(i, stack, player, projectile) end end end ---GetInstance ---@param player Player ---@return TC.GPlayer function GPlayer.GetInstance(player) return player:GetGlobalPlayer("tc:GPlayer") end function GPlayer:Save() return { accessoryInventory = self.accessoryInventory:Serialization(), } end function GPlayer:Load(tagTable) if tagTable.accessoryInventory ~= nil then Inventory.Deserialization(self.accessoryInventory, tagTable.accessoryInventory) end end function GPlayer:SaveCSC() local player = self.player local csc = { health = player.health, maxHealth = player.maxHealth, mana = player.mana, maxMana = player.maxMana, foodSaturationLevel = player.foodSaturationLevel, foodLevel = player.foodLevel, expLevel = player.expLevel, remainExp = player.remainExp, backpackInventory = player.backpackInventory:Serialization(), equipmentInventory = player.equipmentInventory:Serialization(), enderInventory = player.enderInventory:Serialization(), accessoryInventory = self.accessoryInventory:Serialization(), } --print("save csc:", csc) return csc end function GPlayer:LoadCSC(csc) --print("load csc:", csc) local player = self.player if csc.health ~= nil then player.health = csc.health end if csc.maxHealth ~= nil then player.maxHealth = csc.maxHealth end if csc.mana ~= nil then player.mana = csc.mana end if csc.maxMana ~= nil then player.maxMana = csc.maxMana end if csc.foodSaturationLevel ~= nil then player.foodSaturationLevel = csc.foodSaturationLevel end if csc.foodLevel ~= nil then player.foodLevel = csc.foodLevel end if csc.expLevel ~= nil then player.expLevel = csc.expLevel end if csc.remainExp ~= nil then player.remainExp = csc.remainExp end if csc.backpackInventory ~= nil then Inventory.Deserialization(player.backpackInventory, csc.backpackInventory) end if csc.equipmentInventory ~= nil then Inventory.Deserialization(player.equipmentInventory, csc.equipmentInventory) end if csc.enderInventory ~= nil then Inventory.Deserialization(player.enderInventory, csc.enderInventory) end if csc.accessoryInventory ~= nil then Inventory.Deserialization(self.accessoryInventory, csc.accessoryInventory) end end function GPlayer:OnInventoryChanged() --print("OnInventoryChanged") end function GPlayer:OnInventoryItemAdded(itemID, stackSize) --print("OnInventoryItemAdded", Reg.ItemIDName(itemID), stackSize) AdvancementTriggers.getInstance():TriggerGetItem(self.player, itemID, stackSize) if self.recipeBookHookUI ~= nil then self.recipeBookHookUI:RefreshDisplayState() end end function GPlayer:OnInventoryItemRemoved(itemID, stackSize) --print("OnInventoryItemRemoved", Reg.ItemIDName(itemID), stackSize) end function GPlayer:OnAdvancementMade(advancementID) --print("OnAdvancementMade", Reg.AdvancementIDName(advancementID)) local HudUI = require("ui.hud.HudUI") HudUI.showAdvancementTip(advancementID) end function GPlayer:OnAdvancementRemoved(advancementID) --print("OnAdvancementRemoved", Reg.AdvancementIDName(advancementID)) end function GPlayer:OnKilled() --print("player killed") end local s_advancement_hunter = Reg.AdvancementID("hunter") local s_advancement_leather = Reg.AdvancementID("leather") ---OnKillNpc ---@param npc Npc function GPlayer:OnKillNpc(npc) AdvancementTriggers.getInstance():TriggerKillNpc(self.player, npc) -- kill any npc if not self.player:IsAdvancementFinished(s_advancement_leather) then self.player:FinishAdvancement(s_advancement_leather) end -- kill enemy if not self.player:IsAdvancementFinished(s_advancement_hunter) then if not npc.friendly or npc.angry then self.player:FinishAdvancement(s_advancement_hunter) end end end function GPlayer:OnRespawn() --print("player respawn") local player = self.player player.health = 100 if player.health > player.maxHealth then player.health = player.maxHealth end player.mana = 0 player.foodLevel = 100 player.foodSaturationLevel = 100 if not self:HasAccessory(Reg.ItemID("gold_talisman")) then player.expLevel = math.floor(player.expLevel * 0.8) else player.expLevel = math.floor(player.expLevel * 0.9) end player.remainExp = 0 end return GPlayer ================================================ FILE: player/GlobalPlayer.json ================================================ { "GlobalClass": [ "GPlayer" ] } ================================================ FILE: player/PlayerConstants.lua ================================================ local PlayerConstants = { StartHealth = 100, StartMaxHealth = 100, StartMana = 100, StartMaxMana = 100, StartFoodLevel = 100, StartSaturationLevel = 100, MaxHealthA = 400, -- 暮色森林层前,最大400 MaxManaA = 1000, -- 暮色森林层前,最大1000 GRAVITY = 0.40625, WALK_FORCE = 0.1, TURN_FORCE = 0.2, DECELERATE_STOP = 0.2131, DECELERATE_STOP_AIR = 0.1, MAX_SPEED_WALK = 3.0, MAX_SPEED_UP = 9.25, MAX_SPEED_DOWN = 12.0, JUMP_SPEED = 5.1, JUMP_UP_TIME = 19, INTERACTION_DISTANCE = 144, MOVE_RATE_DISTANCE = 192, } return PlayerConstants ================================================ FILE: projectile_ai/AirBullet.json ================================================ { "AirBullet": { "script": { "path": "AirBullet.lua" }, "modData": [ [ "int", "bounceTimes" ] ] } } ================================================ FILE: projectile_ai/AirBullet.lua ================================================ ---@type ModProjectile local AirBullet = class("AirBullet", ModProjectile) ---@param oldSpeedX double ---@param oldSpeedY double function AirBullet:TileBounce(oldSpeedX, oldSpeedY) local projectile = self.projectile if projectile.stand or projectile.isCollisionTop then projectile.speedY = -oldSpeedY elseif projectile.isCollisionLeft or projectile.isCollisionRight then projectile.speedX = -oldSpeedX end projectile.modData.bounceTimes = projectile.modData.bounceTimes + 1 end function AirBullet:TouchBounce() local projectile = self.projectile local angle = projectile.speedAngle angle = angle + math.pi + Utils.RandSym(0.2) local speed = Utils.GetDistance(projectile.speedX, projectile.speedY) projectile.speedX = speed * math.cos(angle) projectile.speedY = speed * math.sin(angle) projectile.modData.bounceTimes = projectile.modData.bounceTimes + 1 end function AirBullet:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("chip"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(0.5), projectile.speedY / 4 - Utils.RandDouble(2), Utils.RandSym(1), Utils.RandDoubleArea(1, 0.5), 0, Color.new(200, 200, 255) ) end if projectile.tickTime % 8 == 0 then EffectUtils.Create( Reg.EffectID("flash2"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(0.5), projectile.speedY / 4 - Utils.RandDouble(2), 0, Utils.RandDoubleArea(1, 0.5), 0, Color.new(200, 200, 255) ) end end function AirBullet:OnKilled() local projectile = self.projectile local chipId = Reg.EffectID("chip") for _ = 1, 8 do EffectUtils.Create( chipId, projectile.centerX, projectile.centerY, -projectile.speedX / 4 + Utils.RandSym(2), -projectile.speedY / 4 - Utils.RandDouble(3), Utils.RandSym(1), Utils.RandDoubleArea(1, 0.5) ) end end function AirBullet:OnHitNpc(_, _) if self.projectile.modData.bounceTimes > 1 then self.projectile:Kill() else self:TouchBounce() end end function AirBullet:OnHitPlayer(_, _) if self.projectile.modData.bounceTimes > 1 then self.projectile:Kill() else self:TouchBounce() end end ---OnTileCollide ---@param oldSpeedX double ---@param oldSpeedY double function AirBullet:OnTileCollide(oldSpeedX, oldSpeedY) if self.projectile.modData.bounceTimes > 4 then self.projectile:Kill() else self:TileBounce(oldSpeedX, oldSpeedY) end end return AirBullet ================================================ FILE: projectile_ai/AirWave.json ================================================ { "AirWave": { "script": { "path": "AirWave.lua" } } } ================================================ FILE: projectile_ai/AirWave.lua ================================================ ---@class TC.AirWave:ModProjectile local AirWave = class("AirWave", ModProjectile) function AirWave:TouchEffect() local projectile = self.projectile for _ = 1, 4 do EffectUtils.Create( Reg.EffectID("star"), projectile.centerX, projectile.centerY, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(0.4, 0.1), Utils.RandDoubleArea(0.5, 0.5), Color.new(177, 177, 255) ) end end function AirWave:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle local effect = EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x + Utils.RandSym(10), projectile.hots[1].y + Utils.RandSym(10), projectile.speedX / 4 + Utils.RandSym(0.25), projectile.speedY / 4 + Utils.RandSym(0.25), Utils.RandSym(1), Utils.RandDoubleArea(0.15, 0.15), 1.0, Color.new(200, 255, 255) ) effect:SetDisappearTime(30) end function AirWave:OnHitNpc(_, _) self:TouchEffect() self.projectile:Kill() end function AirWave:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function AirWave:OnTileCollide(_, _) self:TouchEffect() self.projectile:Kill() end return AirWave ================================================ FILE: projectile_ai/AmethystMagic.json ================================================ { "AmethystMagic": { "script": { "path": "AmethystMagic.lua" } } } ================================================ FILE: projectile_ai/AmethystMagic.lua ================================================ ---@type ModProjectile local AmethystMagic = class("AmethystMagic", ModProjectile) function AmethystMagic:Update() local projectile = self.projectile projectile:Rotate(0.4) if projectile.tickTime % 8 == 0 then EffectUtils.Create( Reg.EffectID("star"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(1), projectile.speedY / 4 + Utils.RandSym(1), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 0.5), 1.0, Color.new(160, 100, 255) ) end if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("flash2"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(2), projectile.speedY / 4 + Utils.RandSym(2), 0, Utils.RandDoubleArea(1, 1), 1.0, Color.new(160, 100, 255) ) end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 24, 8, 0, 16) end function AmethystMagic:OnKilled() local projectile = self.projectile local flash2 = Reg.EffectID("flash2") for _ = 1, 8 do EffectUtils.Create( flash2, projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandSym(2), 0, Utils.RandDoubleArea(1, 1), 1.0, Color.new(160, 100, 255) ) end end function AmethystMagic:OnHitNpc(_, _) self.projectile:Kill() end function AmethystMagic:OnHitPlayer(_, _) self.projectile:Kill() end function AmethystMagic:OnTileCollide(_, _) self.projectile:Kill() end return AmethystMagic ================================================ FILE: projectile_ai/Arrow.json ================================================ { "Arrow": { "script": { "path": "Arrow.lua" }, "modData": [ [ "int", "attachItemID" ], [ "int", "flameLevel" ], [ "int", "piercingCount" ] ] } } ================================================ FILE: projectile_ai/Arrow.lua ================================================ ---@type ModProjectile local Arrow = class("AmethystMagic", ModProjectile) function Arrow:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle if projectile.modData.flameLevel > 0 then if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(2), Utils.RandSym(2), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 0.5) ) end end end function Arrow:PostUpdate() local projectile = self.projectile if projectile.modData.flameLevel == 0 then if projectile.tickTime % 2 == 0 then EffectUtils.Create( Reg.EffectID("arrow_paticular"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(0.5), Utils.RandSym(0.5), Utils.RandSym(0.25) ) end end end function Arrow:OnKilled() local projectile = self.projectile if projectile.modData.flameLevel > 0 then local effectId = Reg.EffectID("fire_flame") for _ = 1, 4 do EffectUtils.Create( effectId, projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandDoubleArea(-2, 3), Utils.RandSym(1), Utils.RandDoubleArea(1, 0.5), 1.0, Color.new(200, 200, 200) ) end else local effectId = Reg.EffectID("chip") for _ = 1, 4 do EffectUtils.Create( effectId, projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandDoubleArea(-2, 3), Utils.RandSym(1), Utils.RandDoubleArea(1, 0.5), 1.0, Color.new(200, 200, 200) ) end end SoundUtils.PlaySound(Reg.SoundID("bowhit"), projectile.centerXi, projectile.centerYi) --EffectUtils.CreateExplosion(projectile.centerX, projectile.centerY) end function Arrow:OnHitNpc(npc, _) local projectile = self.projectile if projectile.modData.flameLevel > 0 then npc:AddBuff(Reg.BuffID("fire"), 60 * (projectile.modData.flameLevel + 1)) end if projectile.modData.piercingCount > 0 then projectile.modData.piercingCount = projectile.modData.piercingCount - 1 else projectile:Kill() end end function Arrow:OnHitPlayer(player, _) local projectile = self.projectile if projectile.modData.flameLevel > 0 then player:AddBuff(Reg.BuffID("fire"), 60 * (projectile.modData.flameLevel + 1)) end projectile:Kill() end function Arrow:OnTileCollide(_, _) local projectile = self.projectile if self.attachItemID ~= nil and self.attachItemID > 0 then ItemUtils.CreateDrop(self.attachItemID, 1, projectile.centerX, projectile.centerY, -1.5 * math.cos(projectile.rotateAngle), -4 * math.sin(projectile.rotateAngle)) end projectile:Kill() end return Arrow ================================================ FILE: projectile_ai/BlackHole.json ================================================ { "BlackHole": { "script": { "path": "BlackHole.lua" } } } ================================================ FILE: projectile_ai/BlackHole.lua ================================================ ---@class TC.BlackHole:ModProjectile local BlackHole = class("BlackHole", ModProjectile) function BlackHole:Update() local projectile = self.projectile local angle = projectile.speedAngle local speed = Vector2.new(projectile.speedX, projectile.speedY).length if speed < 0.2 then projectile:Kill() return end speed = speed * 0.98 projectile.speedX = speed * math.cos(angle) projectile.speedY = speed * math.sin(angle) if projectile.isCheckNpc then local npcTarget = NpcUtils.SearchNearestEnemy(projectile.centerX, projectile.centerY, 128) if npcTarget ~= nil then npcTarget.speedX, npcTarget.speedY = Utils.ForceSpeed2D(npcTarget.speedX, npcTarget.speedY, 0.5, npcTarget:GetAngleTo(projectile.centerX, projectile.centerY), 4.0) if npcTarget.stand then npcTarget.speedY = -6 end end end if projectile.tickTime % 1 == 0 then local effectAngle = Utils.RandSym(math.pi) local d = 96 local effectX = projectile.centerX + math.cos(effectAngle) * d local effectY = projectile.centerY + math.sin(effectAngle) * d local effectSpeed = 6 local effectSpeedAngle = Utils.FixAngle(effectAngle + math.pi) local spx = projectile.speedX + math.cos(effectSpeedAngle) * effectSpeed local spy = projectile.speedY + math.sin(effectSpeedAngle) * effectSpeed local colorChannel = Utils.RandIntArea(64, 140) EffectUtils.Create( Reg.EffectID("flash2"), effectX, effectY, spx, spy, Utils.RandSym(0.5), Utils.RandDoubleArea(0.5,0.7), 1, Color.new(colorChannel, colorChannel, colorChannel) ) end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 30) end function BlackHole:OnKilled() local projectile = self.projectile local flash2 = Reg.EffectID("flash2") for _ = 1, 12 do local colorChannel = Utils.RandIntArea(100, 140) EffectUtils.Create(flash2, projectile.centerX, projectile.centerY, Utils.RandSym(6), Utils.RandSym(6), 0, Utils.RandDoubleArea(1, 1), 1.0, Color.new(colorChannel, colorChannel, colorChannel) ) end end function BlackHole:OnHitNpc(npc, hitAttack) --self.projectile:Kill() end function BlackHole:OnHitPlayer(player, hitAttack) --self.projectile:Kill() end function BlackHole:OnTileCollide(oldSpeedX, oldSpeedY) --self.projectile:Kill() end return BlackHole ================================================ FILE: projectile_ai/BlazeRod.json ================================================ { "BlazeRod": { "script": { "path": "BlazeRod.lua" }, "modData": [ [ "int", "beginDir" ] ] } } ================================================ FILE: projectile_ai/BlazeRod.lua ================================================ ---@type ModProjectile local BlazeRod = class("BlazeRod", ModProjectile) function BlazeRod:Update() local projectile = self.projectile local ownerNpc = NpcUtils.Get(projectile.npcOwnerIndex) if ownerNpc ~= nil then local angle = projectile.modData.beginDir * math.pi / 2 + projectile.tickTime / 32 local d = Utils.SinValue(projectile.tickTime, 128) * 8 + 56 projectile.x = ownerNpc.centerX + math.cos(angle) * d - projectile.width / 2 projectile.y = ownerNpc.centerY + math.sin(angle) * d - projectile.height / 2 projectile.rotateAngle = angle + math.pi / 2 if projectile.tickTime % 8 == 0 then EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.centerX, projectile.centerY, 0, 0, Utils.RandSym(1), Utils.RandDoubleArea(0.5, 0.5), 1 ) end else projectile:Kill() end end return BlazeRod ================================================ FILE: projectile_ai/BloodArrow.json ================================================ { "BloodArrow": { "defaultAI": "Arrow", "script": { "path": "BloodArrow.lua" } } } ================================================ FILE: projectile_ai/BloodArrow.lua ================================================ ---@type ModProjectile local BloodArrow = class("BloodArrow", require("Arrow")) function BloodArrow:PostUpdate() local projectile = self.projectile if projectile.modData.flameLevel == 0 then if projectile.tickTime % 2 == 0 then EffectUtils.Create( Reg.EffectID("arrow_paticular"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 8 + Utils.RandSym(2), projectile.speedY / 8 + Utils.RandSym(2), 0, Utils.RandDoubleArea(1, 1), 0, Color.Red ) end end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 16, 20, 12) end ---OnHitNpc ---@param npc Npc ---@param hitAttack Attack function BloodArrow:OnHitNpc(npc, hitAttack) local projectile = self.projectile npc:AddBuff(Reg.BuffID("hurt"), 120) if projectile.modData.flameLevel > 0 then npc:AddBuff(Reg.BuffID("fire"), 60 * (projectile.modData.flameLevel + 1)) end if projectile.modData.piercingCount > 0 then projectile.modData.piercingCount = projectile.modData.piercingCount - 1 else projectile:Kill() end end ---OnHitPlayer ---@param player Player ---@param hitAttack Attack function BloodArrow:OnHitPlayer(player, hitAttack) local projectile = self.projectile player:AddBuff(Reg.BuffID("hurt"), 120) if projectile.modData.flameLevel > 0 then player:AddBuff(Reg.BuffID("fire"), 60 * (projectile.modData.flameLevel + 1)) end projectile:Kill() end return BloodArrow ================================================ FILE: projectile_ai/BlueArrow.json ================================================ { "BlueArrow": { "script": { "path": "BlueArrow.lua" } } } ================================================ FILE: projectile_ai/BlueArrow.lua ================================================ ---@class TC.BlueArrow:ModProjectile local BlueArrow = class("BlueArrow", ModProjectile) function BlueArrow:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle if projectile.tickTime % 2 == 0 then local spx = projectile.speedX / 4 + Utils.RandSym(1) local spy = projectile.speedY / 4 + Utils.RandSym(1) local effect = EffectUtils.Create( Reg.EffectID("chip_fast"), projectile.hots[1].x, projectile.hots[1].y, spx, spy, Utils.RandSym(0.1), Utils.RandDoubleArea(1.0, 1.0) ) effect.lightAlpha = 24 effect.color = Color.new(255, 100, 255) effect.gravity = false end projectile.gravity = 0 end function BlueArrow:OnKilled() local projectile = self.projectile local effectId = Reg.EffectID("chip_fast") for _ = 1, 8 do local spx = -projectile.speedX / 8 + Utils.RandSym(1) local spy = -projectile.speedY / 8 + Utils.RandSym(1) local effect = EffectUtils.Create( effectId, projectile.centerX, projectile.centerY, spx, spy, Utils.RandSym(1), Utils.RandDoubleArea(1, 1.0), 1.0, Color.new(255, 100, 255) ) effect.lightAlpha = 24 effect.gravity = false end SoundUtils.PlaySound(Reg.SoundID("bowhit"), projectile.centerXi, projectile.centerYi) end function BlueArrow:OnHitNpc(npc, _) self.projectile:Kill() end function BlueArrow:OnHitPlayer(player, _) self.projectile:Kill() end function BlueArrow:OnTileCollide(_, _) self.projectile:Kill() end return BlueArrow ================================================ FILE: projectile_ai/BlueBullet.json ================================================ { "BlueBullet": { "script": { "path": "BlueBullet.lua" } } } ================================================ FILE: projectile_ai/BlueBullet.lua ================================================ ---@class TC.BlueBullet:ModProjectile local BlueBullet = class("BlueBullet", ModProjectile) function BlueBullet:TouchEffect() local projectile = self.projectile for _ = 1, 12 do EffectUtils.Create( Reg.EffectID("circle"), projectile.centerX, projectile.centerY, Utils.RandSym(3), Utils.RandSym(3), 0, Utils.RandDoubleArea(0.25, 0.25), Utils.RandDoubleArea(0.5, 0.5), Color.new(200, 200, 255) ) end end function BlueBullet:Update() local projectile = self.projectile local effect = EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x + Utils.RandSym(10), projectile.hots[1].y + Utils.RandSym(10), projectile.speedX / 4 + Utils.RandSym(0.25), projectile.speedY / 4 + Utils.RandSym(0.25), Utils.RandSym(1), Utils.RandDoubleArea(0.15, 0.35), 1.0, Color.new(200, 200, 255) ) effect:SetDisappearTime(30) end function BlueBullet:OnHitNpc(_, _) self:TouchEffect() self.projectile:Kill() end function BlueBullet:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function BlueBullet:OnTileCollide(_, _) self:TouchEffect() self.projectile:Kill() end return BlueBullet ================================================ FILE: projectile_ai/BlueWave.json ================================================ { "BlueWave": { "script": { "path": "BlueWave.lua" } } } ================================================ FILE: projectile_ai/BlueWave.lua ================================================ ---@class TC.BlueWave:ModProjectile local BlueWave = class("BlueWave", ModProjectile) function BlueWave:TouchEffect() local projectile = self.projectile for _ = 1, 4 do EffectUtils.Create( Reg.EffectID("circle"), projectile.centerX, projectile.centerY, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1), Utils.RandDoubleArea(0.5, 0.5), Color.new(177, 177, 255) ) end end function BlueWave:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle local effect = EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x + Utils.RandSym(10), projectile.hots[1].y + Utils.RandSym(10), projectile.speedX / 4 + Utils.RandSym(0.25), projectile.speedY / 4 + Utils.RandSym(0.25), Utils.RandSym(1), Utils.RandDoubleArea(0.15, 0.35), 1.0, Color.new(177, 177, 255) ) effect:SetDisappearTime(30) end function BlueWave:OnHitNpc(_, _) self:TouchEffect() self.projectile:Kill() end function BlueWave:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function BlueWave:OnTileCollide(_, _) self:TouchEffect() self.projectile:Kill() end return BlueWave ================================================ FILE: projectile_ai/Bomb.json ================================================ { "Bomb": { "script": { "path": "Bomb.lua" } } } ================================================ FILE: projectile_ai/Bomb.lua ================================================ ---@type ModProjectile local Bomb = class("Bomb", ModProjectile) function Bomb:Update() local projectile = self.projectile -- slow speed if projectile.stand then projectile.speedX = Utils.SlowSpeed1D(projectile.speedX, 0.025) end -- rotate if projectile.speedX ~= 0 then projectile:Rotate(projectile.speedX / (projectile.height / 2)) end -- make fire effect every 4 ticks if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("flame_star"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(0.3), Utils.RandSym(0.2), 0, Utils.RandDoubleArea(1, 1) ) end -- make explosion after the bomb survives target time if projectile.tickTime > projectile.targetTime then projectile:Kill() end end function Bomb:OnKilled() local projectile = self.projectile EffectUtils.CreateExplosion(projectile.centerX, projectile.centerY) MiscUtils.CreateExplosion(projectile.centerXi, projectile.centerYi, projectile.baseAttack.attack, true, true, -- hurt npc / player true, true, -- kill tiles / walls true) -- play explosion sound end function Bomb:OnHitNpc(npc, hitAttack) self.projectile:Kill() end function Bomb:OnHitPlayer(player, hitAttack) self.projectile:Kill() end function Bomb:OnTileCollide(oldSpeedX, oldSpeedY) local projectile = self.projectile --bounce if projectile.stand then if oldSpeedY > 0.5 then projectile.speedY = -oldSpeedY / 3 end end end return Bomb ================================================ FILE: projectile_ai/Boomerang.json ================================================ { "Boomerang": { "script": { "path": "Boomerang.lua" }, "netUpdate": false } } ================================================ FILE: projectile_ai/Boomerang.lua ================================================ ---@class Boomerang:ModProjectile local Boomerang = class("Boomerang", ModProjectile) local GPlayer = require("player.GPlayer") local STATE_NORMAL = 0 local STATE_FLYING_BACK = 1 function Boomerang:Update() local alive = false local proj = self.projectile local slot = self:TryGetHookSlot() if slot ~= nil then alive = true end if alive then if proj.state == STATE_NORMAL then if proj.tickTime > proj.targetTime then proj.state = STATE_FLYING_BACK end elseif proj.state == STATE_FLYING_BACK then local player = self:TryGetHookPlayer() if player then local backX = player.centerX local backY = player.centerY if Utils.GetDistance(proj.centerX - backX, proj.centerY - backY) < 32 then proj:Kill() return end proj.speedX, proj.speedY = Utils.ForceSpeed2D( proj.speedX, proj.speedY, 0.5, Utils.GetAngle(backX - proj.centerX, backY - proj.centerY), 8) end end end proj.rotateAngle = proj.rotateAngle + 0.4 if proj.special == 1 and proj.tickTime % 4 == 0 then EffectUtils.Create(Reg.EffectID("flame_star"), proj.randX, proj.randY, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1) ) end end function Boomerang:TryGetHookPlayer() if self.playerOwnerIndex ~= nil then if PlayerUtils.IsAlive(self.playerOwnerIndex) then local player = PlayerUtils.Get(self.playerOwnerIndex) return player end end return nil end function Boomerang:TryGetHookSlot() local player = self:TryGetHookPlayer() if player == nil then return end local gp = GPlayer.GetInstance(player) local slot = gp:GetHeldSlot() if slot.hasStack then local stack = slot:GetStack() local item = stack:GetItem() if item.projectileID == self.projectile.id then return slot end end return nil end function Boomerang:TryReleasePlayerHook() local player = self:TryGetHookPlayer() if player ~= nil then local gp = GPlayer.GetInstance(player) gp.throwingBoomerang = false gp.throwingBoomerangTime = 0 end end function Boomerang:TryLossDurable() local slot = self:TryGetHookSlot() if slot == nil then return end slot:GetStack():LoseDurable(1) if slot:GetStack().durable == 0 then slot:DecrStackSize(1) end end function Boomerang:PostUpdate() end function Boomerang:OnKilled() self:TryReleasePlayerHook() end function Boomerang:DoFlyBack() local proj = self.projectile if proj.state == STATE_NORMAL then proj.speedX = -proj.speedX proj.speedY = -proj.speedY proj.state = STATE_FLYING_BACK end end ---OnHitNpc ---@param npc Npc function Boomerang:OnHitNpc(npc, _) self:TryLossDurable() self:DoFlyBack() if self.projectile.special == 1 then npc:AddBuff(Reg.BuffID("fire"), 180) end end ---@param player Player function Boomerang:OnHitPlayer(player, _) self:TryLossDurable() self:DoFlyBack() end function Boomerang:OnTileCollide(_, _) local proj = self.projectile if proj.state == STATE_NORMAL then self:DoFlyBack() else proj.speedX = -proj.speedX proj.speedY = -proj.speedY end end return Boomerang ================================================ FILE: projectile_ai/Bullet.json ================================================ { "Bullet": { "script": { "path": "Bullet.lua" } } } ================================================ FILE: projectile_ai/Bullet.lua ================================================ ---@type ModProjectile local Bullet = class("Bullet", ModProjectile) function Bullet:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 8, 24) end function Bullet:OnKilled() local projectile = self.projectile local spx = math.min(math.max(projectile.speedX, -24), 24) local spy = math.min(math.max(projectile.speedY, -24), 24) EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, -spx / 16 + Utils.RandSym(1), -spy / 16 - Utils.RandDouble(2), 0, 0.5, 0, Color.Yellow ) end function Bullet:OnHitNpc(_, _) self.projectile:Kill() end function Bullet:OnHitPlayer(_, _) self.projectile:Kill() end function Bullet:OnTileCollide(_, _) self.projectile:Kill() end return Bullet ================================================ FILE: projectile_ai/CrystalMagic.json ================================================ { "CrystalMagic": { "script": { "path": "CrystalMagic.lua" } } } ================================================ FILE: projectile_ai/CrystalMagic.lua ================================================ ---@type ModProjectile local CrystalMagic = class("CrystalMagic", ModProjectile) function CrystalMagic:Update() local projectile = self.projectile local chasing = false if projectile.isCheckNpc then local npcTarget = NpcUtils.SearchNearestEnemy(projectile.centerX, projectile.centerY, 300) if npcTarget ~= nil then projectile.speedX, projectile.speedY = Utils.ForceSpeed2D(projectile.speedX, projectile.speedY, 0.1, projectile:GetAngleTo(npcTarget.centerX, npcTarget.centerY), projectile.maxSpeed) chasing = true end end if not chasing then -- random move projectile.speedX = projectile.speedX + Utils.RandSym(0.2) projectile.speedY = projectile.speedY + Utils.RandSym(0.2) if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("flash2"), projectile.randX, projectile.randY, Utils.RandSym(1), Utils.RandSym(1), 0, 1, 1 ) end else if projectile.tickTime % 2 == 0 then EffectUtils.Create( Reg.EffectID("flash2"), projectile.randX, projectile.randY, -projectile.speedX / 4 + Utils.RandSym(2), -projectile.speedY / 4 + Utils.RandSym(2), 0, 1, 1 ) end end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 30) end function CrystalMagic:OnKilled() local projectile = self.projectile local flash2 = Reg.EffectID("flash2") for _ = 1, 12 do EffectUtils.Create(flash2, projectile.centerX, projectile.centerY, Utils.RandSym(6), Utils.RandSym(6), 0, Utils.RandDoubleArea(1, 1) ) end end function CrystalMagic:OnHitNpc(npc, hitAttack) self.projectile:Kill() end function CrystalMagic:OnHitPlayer(player, hitAttack) self.projectile:Kill() end function CrystalMagic:OnTileCollide(oldSpeedX, oldSpeedY) self.projectile:Kill() end return CrystalMagic ================================================ FILE: projectile_ai/CursedArrow.json ================================================ { "CursedArrow": { "script": { "path": "CursedArrow.lua" } } } ================================================ FILE: projectile_ai/CursedArrow.lua ================================================ ---@class TC.CursedArrow:ModProjectile local CursedArrow = class("CursedArrow", ModProjectile) function CursedArrow:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle if projectile.tickTime % 1 == 0 then local spx = projectile.speedX / 4 + Utils.RandSym(1) local spy = projectile.speedY / 4 + Utils.RandSym(1) local effect = EffectUtils.Create( Reg.EffectID("chip_fast"), projectile.hots[1].x, projectile.hots[1].y, spx, spy, Utils.RandSym(0.1), Utils.RandDoubleArea(0.7, 0.4) ) effect.lightAlpha = 24 effect.color = Color.new(255, 100, 255) effect.gravity = false effect:SetDisappearTime(20) end projectile.gravity = 0 projectile.speedX, projectile.speedY = Utils.ForceSpeed2D(projectile.speedX, projectile.speedY, 0.4, projectile.speedAngle, 24) end function CursedArrow:OnKilled() local projectile = self.projectile local effectId = Reg.EffectID("chip_fast") for _ = 1, 8 do local spx = projectile.speedX / 8 + Utils.RandSym(1) local spy = projectile.speedY / 8 + Utils.RandSym(1) local effect = EffectUtils.Create( effectId, projectile.centerX, projectile.centerY, spx, spy, Utils.RandSym(1), Utils.RandDoubleArea(1.0, 2.0), 1.0, Color.new(255, 100, 255) ) effect.lightAlpha = 24 effect.gravity = false end SoundUtils.PlaySound(Reg.SoundID("bowhit"), projectile.centerXi, projectile.centerYi) end function CursedArrow:OnHitNpc(npc, _) self.projectile:Kill() end function CursedArrow:OnHitPlayer(player, _) self.projectile:Kill() end function CursedArrow:OnTileCollide(_, _) self.projectile:Kill() end return CursedArrow ================================================ FILE: projectile_ai/Fire.json ================================================ { "Fire": { "script": { "path": "Fire.lua" } } } ================================================ FILE: projectile_ai/Fire.lua ================================================ ---@type ModProjectile local Fire = class("Fire", ModProjectile) function Fire:GetFireScale() local projectile = self.projectile local scale = 1.0 if projectile.tickTime < 30 then scale = 0.25 + 1.75 * projectile.tickTime / 30 elseif projectile.tickTime < 60 then scale = 2 - (projectile.tickTime - 30) / 10 end scale = scale * 1.25 return scale end function Fire:Update() local projectile = self.projectile projectile.speedX, projectile.speedY = Utils.SlowSpeed2D(projectile.speedX, projectile.speedY, 0.14) projectile:Rotate(0.2) local scale = self:GetFireScale() if scale <= 0 or scale >= 60 then projectile:Kill() else local lighting = math.floor((1 - projectile.tickTime / 60) * 32) LightingUtils.Add(projectile.centerXi, projectile.centerYi, lighting, 8, 6, 0) if Utils.RandTry(32) then EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, projectile.speedX / 2 + Utils.RandSym(0.25), projectile.speedY - Utils.RandDouble(0.75), Utils.RandSym(0.05), 0.5, 0, Color.new(255, 128, 0) ) end end end function Fire:OnDraw() local projectile = self.projectile projectile.color = Color.new(255, 255, 255, math.floor((1 - projectile.tickTime / 60) * 255)) local scale = math.max(self:GetFireScale(), 0.1) projectile.spriteEx.angle = projectile.rotateAngle projectile.spriteEx.scaleRateX = scale projectile.spriteEx.scaleRateY = scale projectile.spriteOffsetX = math.floor((1 - projectile.spriteEx.scaleRateX) * projectile.spriteDefaultWidth / 2); projectile.spriteOffsetY = math.floor((1 - projectile.spriteEx.scaleRateY) * projectile.spriteDefaultHeight / 2); end ---OnHitNpc ---@param npc Npc ---@param _ Attack function Fire:OnHitNpc(npc, _) npc:AddBuff(Reg.BuffID("fire"), 100) end ---OnHitPlayer ---@param player Player ---@param _ Attack function Fire:OnHitPlayer(player, _) player:AddBuff(Reg.BuffID("fire"), 100) end function Fire:OnTileCollide(oldSpeedX, oldSpeedY) local projectile = self.projectile for _ = 1, 4 do local effect = EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, -oldSpeedX / 4 + Utils.RandSym(1), -oldSpeedY / 4 - Utils.RandDouble(2), Utils.RandSym(0.05), 0.5, 0, Color.new(255, 128, 0) ) end projectile:Kill() end return Fire ================================================ FILE: projectile_ai/FireArrow.json ================================================ { "FireArrow": { "script": { "path": "FireArrow.lua" }, "modData": [ [ "int", "attachItemID" ], [ "int", "flameLevel" ], [ "int", "piercingCount" ] ] } } ================================================ FILE: projectile_ai/FireArrow.lua ================================================ ---@class TC.FireArrow:ModProjectile local FireArrow = class("AmethystMagic", ModProjectile) function FireArrow:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle if projectile.tickTime % 2 == 0 then EffectUtils.Create( Reg.EffectID("smoke"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(2), Utils.RandSym(2), Utils.RandSym(0.1), Utils.RandDoubleArea(0.25, 0.5), 0.6, Color.new(64, 64, 64) ) end if projectile.tickTime % 1 == 0 then local effect = EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(0.3), Utils.RandSym(0.3), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 1.0) ) effect:SetDisappearTime(20) end end function FireArrow:OnKilled() local projectile = self.projectile local effectId = Reg.EffectID("fire_flame") for _ = 1, 8 do EffectUtils.Create( effectId, projectile.centerX, projectile.centerY, Utils.RandSym(2) + projectile.speedX / 4, Utils.RandDoubleArea(-2, 3) + projectile.speedY / 4, Utils.RandSym(1), Utils.RandDoubleArea(1, 0.5), 1.0, Color.new(200, 200, 200) ) EffectUtils.Create( Reg.EffectID("smoke"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(2) + projectile.speedX / 3, Utils.RandSym(2) + projectile.speedY / 3, Utils.RandSym(0.1), Utils.RandDoubleArea(0.25, 0.5), 0.9, Color.new(200, 200, 100) ) end local explosionEffect = EffectUtils.Create( Reg.EffectID("explosion"), projectile.centerX, projectile.centerY, 0, 0, 0, 1, 1.0, Color.new(200, 200, 0) ) end function FireArrow:OnHitNpc(npc, _) local projectile = self.projectile projectile:Kill() end function FireArrow:OnHitPlayer(player, _) local projectile = self.projectile projectile:Kill() end function FireArrow:OnTileCollide(_, _) local projectile = self.projectile projectile:Kill() end return FireArrow ================================================ FILE: projectile_ai/FireElement.json ================================================ { "FireElement": { "script": { "path": "FireElement.lua" }, "modData": [ [ "int", "bounceTimes" ] ] } } ================================================ FILE: projectile_ai/FireElement.lua ================================================ ---@type ModProjectile local FireElement = class("FireElement", ModProjectile) function FireElement:Update() local projectile = self.projectile projectile.speedY = projectile.speedY + 0.1 projectile.rotateAngle = projectile.speedAngle if projectile.tickTime % 2 == 0 then local effect = EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(1), projectile.speedY / 4 + Utils.RandSym(1), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 0.55), 1.0 ) effect:SetDisappearTime(30) end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 24, 0, 0, 16) end function FireElement:OnKilled() local projectile = self.projectile local flash2 = Reg.EffectID("fire_flame") for _ = 1, 8 do EffectUtils.Create( flash2, projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandSym(2), 0, 1.0, 1.0 ) end end function FireElement:OnHitNpc(_, _) local projectile = self.projectile SoundUtils.PlaySoundGroup(Reg.SoundGroupID("glass"), projectile.centerXi, projectile.centerYi) projectile:Kill() end function FireElement:OnHitPlayer(_, _) local projectile = self.projectile SoundUtils.PlaySoundGroup(Reg.SoundGroupID("glass"), projectile.centerXi, projectile.centerYi) projectile:Kill() end function FireElement:OnTileCollide(oldSpeedX, oldSpeedY) local projectile = self.projectile if projectile.modData.bounceTimes >= 2 then projectile:Kill() else local star = Reg.EffectID("star") for _ = 1, 3 do EffectUtils.Create( star, projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandSym(2), 0, 1.0, 1.0, Color.new(255, 220, 0) ) end end if projectile.stand or projectile.isCollisionTop then projectile.speedY = -oldSpeedY * 0.8 elseif projectile.isCollisionLeft or projectile.isCollisionRight then projectile.speedX = -oldSpeedX * 0.8 end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("glass"), projectile.centerXi, projectile.centerYi) projectile.modData.bounceTimes = projectile.modData.bounceTimes + 1 end return FireElement ================================================ FILE: projectile_ai/FireFlow.json ================================================ { "FireFlow": { "script": { "path": "FireFlow.lua" } } } ================================================ FILE: projectile_ai/FireFlow.lua ================================================ ---@class TC.FireFlow:ModProjectile local FireFlow = class("FireFlow", ModProjectile) function FireFlow:TouchEffect() local projectile = self.projectile for _ = 1, 4 do EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.centerX, projectile.centerY, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1), Utils.RandDoubleArea(0.5, 0.5), Color.new(150, 150, 40) ) end end function FireFlow:Update() local projectile = self.projectile projectile.color = Color.new(0, 0, 0, 0) if projectile.tickTime == 0 then for _ = 1, 8 do EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.centerX, projectile.centerY, projectile.speedX / 6 + Utils.RandSym(1), projectile.speedY / 6 + Utils.RandSym(1), 0, Utils.RandDoubleArea(0.5, 0.5), Utils.RandDoubleArea(0.5, 0.5), Color.new(150, 150, 40) ) end end local effect = EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(0.25), projectile.speedY / 4 + Utils.RandSym(0.25), Utils.RandSym(1), Utils.RandDoubleArea(0.5, 0.5), 1.0, Color.new(255, 180, 130) ) effect:SetDisappearTime(30) if projectile.tickTime > 32 then projectile:Kill() end end function FireFlow:OnHitNpc(_, _) self:TouchEffect() self.projectile:Kill() end function FireFlow:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function FireFlow:OnTileCollide(_, _) self:TouchEffect() self.projectile:Kill() end return FireFlow ================================================ FILE: projectile_ai/FireFlowLarge.json ================================================ { "FireFlowLarge": { "script": { "path": "FireFlowLarge.lua" } } } ================================================ FILE: projectile_ai/FireFlowLarge.lua ================================================ ---@class TC.FireFlowLarge:ModProjectile local FireFlowLarge = class("FireFlowLarge", ModProjectile) function FireFlowLarge:TouchEffect() local projectile = self.projectile for _ = 1, 8 do EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.centerX, projectile.centerY, -projectile.speedX / 4 + Utils.RandSym(3), -projectile.speedY / 4 + Utils.RandSym(3), 0, Utils.RandDoubleArea(1, 1), 1.0, Color.new(255, 200, 0) ) end end function FireFlowLarge:Update() local projectile = self.projectile projectile.color = Color.new(0, 0, 0, 0) projectile.speedY = projectile.speedY + 0.2 if projectile.tickTime == 0 then for _ = 1, 2 do EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.centerX, projectile.centerY, projectile.speedX / 6 + Utils.RandSym(1), projectile.speedY / 6 + Utils.RandSym(1), 0, 1.0, Utils.RandDoubleArea(0.5, 0.5), Color.new(255, 200, 0) ) end end local effect = EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(0.25), projectile.speedY / 4 + Utils.RandSym(0.25), Utils.RandSym(1), Utils.RandDoubleArea(1.5, 0.5), 1.0, Color.new(255, 180, 130) ) effect:SetDisappearTime(60) if projectile.tickTime > 100 then projectile:Kill() end local npcTarget = NpcUtils.SearchNearestEnemy(projectile.centerX, projectile.centerY, 30) if npcTarget ~= nil then npcTarget:AddBuff(Reg.BuffID("fire"), 100) end end function FireFlowLarge:OnHitNpc(npc, _) self:TouchEffect() self.projectile:Kill() end function FireFlowLarge:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function FireFlowLarge:OnTileCollide(_, _) self:TouchEffect() self.projectile:Kill() end return FireFlowLarge ================================================ FILE: projectile_ai/FireMagic.json ================================================ { "FireMagic": { "script": { "path": "FireMagic.lua" } } } ================================================ FILE: projectile_ai/FireMagic.lua ================================================ ---@type ModProjectile local FireMagic = class("FireMagic", ModProjectile) function FireMagic:Update() local projectile = self.projectile if projectile.isCheckNpc then local npcTarget = NpcUtils.SearchNearestEnemy(projectile.centerX, projectile.centerY, 120) if npcTarget ~= nil then projectile.speedX, projectile.speedY = Utils.ForceSpeed2D(projectile.speedX, projectile.speedY, 0.4, projectile:GetAngleTo(npcTarget.centerX, npcTarget.centerY), projectile.maxSpeed) end end EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x, projectile.hots[1].y, 0, 0, 0, 0.75, 0.8, Color.Yellow ) LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 30) end function FireMagic:OnKilled() local projectile = self.projectile local flash2 = Reg.EffectID("flash2") for _ = 1, 8 do EffectUtils.Create(flash2, projectile.centerX, projectile.centerY, -projectile.speedX / 8 + Utils.RandSym(2), -projectile.speedY / 8 - Utils.RandSym(2), 0, Utils.RandDoubleArea(1, 1), 0, Color.Yellow ) end end ---OnHitNpc ---@param npc Npc ---@param _ Attack function FireMagic:OnHitNpc(npc, _) npc:AddBuff(Reg.BuffID("fire"), 240) self.projectile:Kill() end ---OnHitPlayer ---@param player Player ---@param _ Attack function FireMagic:OnHitPlayer(player, _) player:AddBuff(Reg.BuffID("fire"), 240) self.projectile:Kill() end function FireMagic:OnTileCollide(_, _) self.projectile:Kill() end return FireMagic ================================================ FILE: projectile_ai/Fireball.json ================================================ { "Fireball": { "script": { "path": "Fireball.lua" }, "modData": [ [ "bool", "boom" ] ] } } ================================================ FILE: projectile_ai/Fireball.lua ================================================ ---@type ModProjectile local Fireball = class("Fireball", ModProjectile) function Fireball:Update() local projectile = self.projectile projectile:Rotate(0.1) if projectile.tickTime % 8 == 0 then local fire_flame = Reg.EffectID("fire_flame") local flame_star = Reg.EffectID("flame_star") EffectUtils.Create( fire_flame, projectile.randX, projectile.randY, Utils.RandSym(4), Utils.RandSym(4), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 0.5) ) EffectUtils.Create( flame_star, projectile.randX, projectile.randY, Utils.RandSym(3), Utils.RandSym(3), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 0.5) ) end end function Fireball:OnKilled() local projectile = self.projectile -- explode if projectile.modData.boom then MiscUtils.CreateExplosion(projectile.centerXi, projectile.centerYi, 5, -- attack projectile.isCheckNpc, projectile.isCheckPlayer, -- hurt npc / player true, false, -- kill tiles but not walls true, -- play sound 100) -- max hardness EffectUtils.CreateExplosion(projectile.centerX, projectile.centerY) else local fire_flame = Reg.EffectID("fire_flame") local flame_star = Reg.EffectID("flame_star") for _ = 1, 8 do EffectUtils.Create( fire_flame, projectile.randX, projectile.randY, Utils.RandSym(3), Utils.RandSym(3), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 0.5) ) EffectUtils.Create( flame_star, projectile.randX, projectile.randY, Utils.RandSym(5), Utils.RandSym(5), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 0.5) ) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("explode"), projectile.centerXi, projectile.centerYi) end end function Fireball:OnHitNpc(npc, hitAttack) self.projectile:Kill() end function Fireball:OnHitPlayer(player, hitAttack) self.projectile:Kill() end function Fireball:OnTileCollide(oldSpeedX, oldSpeedY) self.projectile:Kill() end return Fireball ================================================ FILE: projectile_ai/GlowBomb.json ================================================ { "GlowBomb": { "defaultAI": "Bomb", "script": { "path": "GlowBomb.lua", "requires": [ [ "mycode", "modules\\mycode.lua" ] ] } } } ================================================ FILE: projectile_ai/GlowBomb.lua ================================================ ---@type ModProjectile local GlowBomb = class("GlowBomb", require("Bomb")) ---MakeGlowingBombEffect ---@param centerX double ---@param centerY double function MakeGlowingBombEffect(centerX, centerY) local loops = 32 local flowEffectID = Reg.EffectID("flow_particular") for i = 1, loops do local rate = Utils.RandSym(1) local speed = 1 + 20 * math.abs(rate) local spx = speed * math.cos(i / loops * 2 * math.pi) local spy = speed * math.sin(i / loops * 2 * math.pi) local rotateSpeed = 0.1 * (1 - math.abs(rate)) if rate < 0 then rotateSpeed = -rotateSpeed end EffectUtils.Create( flowEffectID, centerX, centerY, spx, spy, rotateSpeed, 0, 0, Color.Yellow ) end end function GlowBomb:PostUpdate() local projectile = self.projectile LightingUtils.Add(projectile.centerXi, projectile.centerYi, 30) end function GlowBomb:OnKilled() local projectile = self.projectile MakeGlowingBombEffect(projectile.centerX, projectile.centerY) EffectUtils.CreateExplosion(projectile.centerX, projectile.centerY) MiscUtils.CreateExplosion(projectile.centerXi, projectile.centerYi, projectile.baseAttack.attack, true, true, -- hurt npc / player true, true, -- kill tiles / walls true) -- play explosion sound end return GlowBomb ================================================ FILE: projectile_ai/Glowball.json ================================================ { "Glowball": { "script": { "path": "Glowball.lua" } } } ================================================ FILE: projectile_ai/Glowball.lua ================================================ ---@type ModProjectile local Glowball = class("Glowball", ModProjectile) function Glowball:Update() local projectile = self.projectile -- slow speed if projectile.stand then projectile.speedX = Utils.SlowSpeed1D(projectile.speedX, 0.025) end -- rotate if projectile.speedX ~= 0 then projectile:Rotate(projectile.speedX / (projectile.height / 2)) end LightingUtils.Add(projectile.centerXi, projectile.centerYi, 28) -- make fire effect every 4 ticks if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("flame_star"), projectile.randX, projectile.randY, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1) ) end -- make explosion after the bomb survives target time if projectile.tickTime > projectile.targetTime then projectile:Kill() end end function Glowball:OnKilled() local projectile = self.projectile local flame_star = Reg.EffectID("flame_star") for i = 1, 32 do EffectUtils.Create( flame_star, projectile.randX, projectile.randY, Utils.RandSym(3), Utils.RandSym(3), 0, Utils.RandDoubleArea(1, 1) ) end end ---OnHitNpc ---@param npc Npc ---@param hitAttack Attack function Glowball:OnHitNpc(npc, hitAttack) npc:AddBuff(Reg.BuffID("glowing"), 120) end function Glowball:OnTileCollide(oldSpeedX, oldSpeedY) local projectile = self.projectile -- bounce if projectile.stand then if oldSpeedY > 0.5 then projectile.speedY = -oldSpeedY / 1.5 end end end return Glowball ================================================ FILE: projectile_ai/Grenade.json ================================================ { "Grenade": { "defaultAI": "Bomb", "script": { "path": "Grenade.lua" } } } ================================================ FILE: projectile_ai/Grenade.lua ================================================ ---@type ModProjectile local Grenade = class("Grenade", require("Bomb")) function Grenade:OnKilled() local projectile = self.projectile EffectUtils.CreateExplosion(projectile.centerX, projectile.centerY) MiscUtils.CreateExplosion(projectile.centerXi, projectile.centerYi, projectile.baseAttack.attack, true, false, -- hurt npc / player false, false, -- kill tiles / walls false) -- play explosion sound SoundUtils.PlaySound(Reg.SoundID("grenade_fire"), projectile.centerXi, projectile.centerYi) end return Grenade ================================================ FILE: projectile_ai/IceArrow.json ================================================ { "IceArrow": { "defaultAI": "Arrow", "script": { "path": "IceArrow.lua" }, "modData": [ [ "bool", "bounceOnce" ] ] } } ================================================ FILE: projectile_ai/IceArrow.lua ================================================ ---@type ModProjectile local IceArrow = class("Grenade", require("Arrow")) function IceArrow:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle if projectile.modData.flameLevel == 0 then if projectile.tickTime % 2 == 0 then EffectUtils.Create( Reg.EffectID("arrow_paticular"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(2), Utils.RandSym(2), Utils.RandSym(0.25), 0, 0, Color.new(0, 200, 255) ) end end end function IceArrow:OnKilled() local projectile = self.projectile local flash2 = Reg.EffectID("flash2") for _ = 1, 8 do EffectUtils.Create( flash2, projectile.centerX, projectile.centerY, Utils.RandSym(4), Utils.RandSym(4) ) end SoundUtils.PlaySound(Reg.SoundID("bowhit"), projectile.centerXi, projectile.centerYi) end function IceArrow:OnHitNpc(_, _) local projectile = self.projectile if projectile.modData.piercingCount > 0 then projectile.modData.piercingCount = projectile.modData.piercingCount - 1 else projectile:Kill() end end function IceArrow:OnHitPlayer(_, _) self.projectile:Kill() end ---OnTileCollide ---@param oldSpeedX double ---@param oldSpeedY double function IceArrow:OnTileCollide(oldSpeedX, oldSpeedY) local projectile = self.projectile if not projectile.modData.bounceOnce then if projectile.stand or projectile.isCollisionTop then projectile.speedY = -oldSpeedY / 2 projectile.speedX = oldSpeedX / 2 elseif projectile.isCollisionLeft or projectile.isCollisionRight then projectile.speedX = -oldSpeedX / 2 end projectile.modData.bounceOnce = true SoundUtils.PlaySound(Reg.SoundID("bowhit"), projectile.centerXi, projectile.centerYi) else if projectile.modData.attachItemID > 0 then ItemUtils.CreateDrop(projectile.modData.attachItemID, 1, projectile.centerX, projectile.centerY, -1.5 * math.cos(projectile.rotateAngle), -4 * math.sin(projectile.rotateAngle)) end projectile:Kill() end end return IceArrow ================================================ FILE: projectile_ai/IceBullet.json ================================================ { "IceBullet": { "script": { "path": "IceBullet.lua" } } } ================================================ FILE: projectile_ai/IceBullet.lua ================================================ ---@type ModProjectile local IceBullet = class("IceBullet", ModProjectile) function IceBullet:Update() local projectile = self.projectile if projectile.tickTime % 8 == 0 then EffectUtils.Create( Reg.EffectID("flash2"), projectile.randX, projectile.randY, Utils.RandSym(1), Utils.RandSym(1) ) end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 30) end function IceBullet:OnKilled() local projectile = self.projectile local flash2 = Reg.EffectID("flash2") for _ = 1, 8 do EffectUtils.Create( flash2, projectile.centerX, projectile.centerY, Utils.RandSym(4), Utils.RandSym(4) ) end end function IceBullet:OnHitNpc(npc, hitAttack) self.projectile:Kill() end function IceBullet:OnHitPlayer(player, hitAttack) self.projectile:Kill() end function IceBullet:OnTileCollide(oldSpeedX, oldSpeedY) self.projectile:Kill() end return IceBullet ================================================ FILE: projectile_ai/IceMagic.json ================================================ { "IceMagic": { "script": { "path": "IceMagic.lua" }, "modData": [ [ "int", "bounceTimes" ] ] } } ================================================ FILE: projectile_ai/IceMagic.lua ================================================ ---@type ModProjectile local IceMagic = class("IceMagic", ModProjectile) function IceMagic:Update() local projectile = self.projectile projectile.speedY = projectile.speedY + 0.2 projectile.rotateAngle = projectile.speedAngle if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("flash2"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(3), projectile.speedY / 4 + Utils.RandSym(3), Utils.RandSym(0.1), Utils.RandDoubleArea(1, 0.25), 1.0, Color.new(240, 160, 255) ) end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 24, 0, 0, 16) end function IceMagic:OnKilled() local projectile = self.projectile local flash2 = Reg.EffectID("flash2") for _ = 1, 8 do EffectUtils.Create( flash2, projectile.centerX, projectile.centerY, Utils.RandSym(4), Utils.RandSym(4), 0, 2.0, 1.0, Color.new(240, 160, 255) ) end end function IceMagic:OnHitNpc(_, _) local projectile = self.projectile SoundUtils.PlaySoundGroup(Reg.SoundGroupID("glass"), projectile.centerXi, projectile.centerYi) projectile:Kill() end function IceMagic:OnHitPlayer(_, _) local projectile = self.projectile SoundUtils.PlaySoundGroup(Reg.SoundGroupID("glass"), projectile.centerXi, projectile.centerYi) projectile:Kill() end function IceMagic:OnTileCollide(oldSpeedX, oldSpeedY) local projectile = self.projectile if projectile.modData.bounceTimes >= 4 then projectile:Kill() else local star = Reg.EffectID("star") for _ = 1, 3 do EffectUtils.Create( star, projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandSym(2), 0, 1.0, 1.0, Color.new(240, 160, 255) ) end end if projectile.stand or projectile.isCollisionTop then projectile.speedY = -oldSpeedY * 0.8 elseif projectile.isCollisionLeft or projectile.isCollisionRight then projectile.speedX = -oldSpeedX * 0.8 end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("glass"), projectile.centerXi, projectile.centerYi) projectile.modData.bounceTimes = projectile.modData.bounceTimes + 1 end return IceMagic ================================================ FILE: projectile_ai/LaserBullet.json ================================================ { "LaserBullet": { "defaultAI": "Bullet", "script": { "path": "LaserBullet.lua" } } } ================================================ FILE: projectile_ai/LaserBullet.lua ================================================ ---@type ModProjectile local LaserBullet = class("LaserBullet", require("Bullet")) function LaserBullet:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 24, 0, 0, 24) end function LaserBullet:OnKilled() local projectile = self.projectile EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandSym(2), 0, 0.5, 0.5, Color.new(100, 100, 255) ) end return LaserBullet ================================================ FILE: projectile_ai/LightingArrow.json ================================================ { "LightingArrow": { "defaultAI": "Arrow", "script": { "path": "LightingArrow.lua" } } } ================================================ FILE: projectile_ai/LightingArrow.lua ================================================ ---@type ModProjectile local LightingArrow = class("LightingArrow", require("Arrow")) function LightingArrow:PreUpdate() local projectile = self.projectile LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 32) end function LightingArrow:OnKilled() local projectile = self.projectile if projectile.modData.flameLevel > 0 then local fire_flame = Reg.EffectID("fire_flame") for _ = 1, 4 do EffectUtils.Create( fire_flame, projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandDoubleArea(-2, 3), Utils.RandSym(1), Utils.RandDoubleArea(1, 0.5), 1.0, Color.new(200,200,200) ) end else local flame_star = Reg.EffectID("flame_star") for _ = 1, 8 do EffectUtils.Create( flame_star, projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandDoubleArea(-2, 3), Utils.RandSym(1), Utils.RandDoubleArea(1, 0.5), 1.0, Color.new(200,200,200) ) end end EffectUtils.Create( Reg.EffectID("flame_star"), projectile.centerX, projectile.centerY, -projectile.speedX / 4 + Utils.RandSym(2), -projectile.speedY / 4 + Utils.RandSym(2), Utils.RandSym(0.25), Utils.RandDoubleArea(1, 0.5), 1.0, Color.Yellow ) SoundUtils.PlaySound(Reg.SoundID("bowhit"), projectile.centerXi, projectile.centerYi) end ---OnHitNpc ---@param npc Npc ---@param hitAttack Attack function LightingArrow:OnHitNpc(npc, hitAttack) local projectile = self.projectile npc:AddBuff(Reg.BuffID("glowing"), 300) if projectile.modData.flameLevel > 0 then npc:AddBuff(Reg.BuffID("fire"), 60 * (projectile.modData.flameLevel + 1)) end if projectile.modData.piercingCount > 0 then projectile.modData.piercingCount = projectile.modData.piercingCount - 1 else projectile:Kill() end end ---OnHitPlayer ---@param player Player ---@param hitAttack Attack function LightingArrow:OnHitPlayer(player, hitAttack) local projectile = self.projectile player:AddBuff(Reg.BuffID("glowing"), 300) if projectile.modData.flameLevel > 0 then player:AddBuff(Reg.BuffID("fire"), 60 * (projectile.modData.flameLevel + 1)) end projectile:Kill() end return LightingArrow ================================================ FILE: projectile_ai/LightingBulletYellow.json ================================================ { "LightingBulletYellow": { "script": { "path": "LightingBulletYellow.lua" } } } ================================================ FILE: projectile_ai/LightingBulletYellow.lua ================================================ ---@class TC.LightingBulletYellow:ModProjectile local LightingBulletYellow = class("LightingBulletYellow", ModProjectile) function LightingBulletYellow:TouchEffect() local projectile = self.projectile for _ = 1, 4 do EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.centerX, projectile.centerY, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1), Utils.RandDoubleArea(0.5, 0.5), Color.new(150, 150, 40) ) end end function LightingBulletYellow:Update() local projectile = self.projectile end function LightingBulletYellow:OnHitNpc(_, _) self:TouchEffect() self.projectile:Kill() end function LightingBulletYellow:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function LightingBulletYellow:OnTileCollide(_, _) self:TouchEffect() self.projectile:Kill() end return LightingBulletYellow ================================================ FILE: projectile_ai/LightingWheel.json ================================================ { "LightingWheel": { "script": { "path": "LightingWheel.lua" } } } ================================================ FILE: projectile_ai/LightingWheel.lua ================================================ ---@class TC.LightingWheel:ModProjectile local LightingWheel = class("LightingWheel", ModProjectile) function LightingWheel:TouchEffect() local projectile = self.projectile for _ = 1, 4 do EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.centerX, projectile.centerY, Utils.RandSym(1), Utils.RandSym(1), 0, Utils.RandDoubleArea(1, 1), Utils.RandDoubleArea(0.5, 0.5), Color.new(150, 150, 40) ) end end function LightingWheel:Update() local projectile = self.projectile projectile.rotateAngle = projectile.rotateAngle + 0.2 local effect = EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(0.25), projectile.speedY / 4 + Utils.RandSym(0.25), Utils.RandSym(1), Utils.RandDoubleArea(0.5, 0.5), 1.0, Color.new(255, 255, 130) ) effect:SetDisappearTime(30) if projectile.tickTime > 0 and projectile.tickTime % 32 == 0 then local angle = -projectile.tickTime / 32 - math.pi / 2 local proj = ProjectileUtils.Create(Reg.ProjectileID("lighting_bullet_yellow"), projectile.centerX, projectile.centerY, 2 * math.cos(angle), 2 * math.sin(angle), projectile.baseAttack) proj.isCheckPlayer = true end end function LightingWheel:OnHitNpc(_, _) self:TouchEffect() self.projectile:Kill() end function LightingWheel:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function LightingWheel:OnTileCollide(_, _) self:TouchEffect() self.projectile:Kill() end return LightingWheel ================================================ FILE: projectile_ai/MagicWave.json ================================================ { "MagicWave": { "script": { "path": "MagicWave.lua" } } } ================================================ FILE: projectile_ai/MagicWave.lua ================================================ ---@class TC.MagicWave:ModProjectile local MagicWave = class("MagicWave", ModProjectile) function MagicWave:TouchEffect() local projectile = self.projectile for _ = 1, 12 do EffectUtils.Create( Reg.EffectID("circle"), projectile.centerX, projectile.centerY, Utils.RandSym(3), Utils.RandSym(3), 0, Utils.RandDoubleArea(0.25, 0.25), Utils.RandDoubleArea(0.5, 0.5), Color.new(200, 200, 255) ) end end function MagicWave:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle local effect = EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x + Utils.RandSym(10), projectile.hots[1].y + Utils.RandSym(10), projectile.speedX / 4 + Utils.RandSym(0.25), projectile.speedY / 4 + Utils.RandSym(0.25), Utils.RandSym(1), Utils.RandDoubleArea(0.15, 0.35), 1.0, Color.new(200, 200, 255) ) effect:SetDisappearTime(30) end function MagicWave:OnHitNpc(_, _) self:TouchEffect() self.projectile:Kill() end function MagicWave:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function MagicWave:OnTileCollide(_, _) self:TouchEffect() self.projectile:Kill() end return MagicWave ================================================ FILE: projectile_ai/MiniRocket.json ================================================ { "MiniRocket": { "script": { "path": "MiniRocket.lua" } } } ================================================ FILE: projectile_ai/MiniRocket.lua ================================================ ---@class TC.MiniRocket:ModProjectile local MiniRocket = class("MiniRocket", ModProjectile) function MiniRocket:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle if projectile.tickTime == 0 then for i = 1, 5 do EffectUtils.Create( Reg.EffectID("smoke"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(2), projectile.speedY / 4 + Utils.RandSym(2), Utils.RandSym(0.1), Utils.RandDoubleArea(0.25, 0.75), 0.9, Color.new(255, 255, 200) ) end local s = Vector2.new(projectile.speedX, projectile.speedY).length s = s * Utils.RandDoubleArea(0.7, 0.3) local angle = projectile.speedAngle projectile.speedX = s * math.cos(angle) projectile.speedY = s * math.sin(angle) end if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("smoke"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(0.1), Utils.RandDoubleArea(0.25, 0.5), 0.9, Color.new(164, 164, 64) ) end if projectile.tickTime % 1 == 0 then EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(0.2), Utils.RandSym(0.2), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 0.25) ) end local chasing = false if projectile.isCheckNpc then local npcTarget = NpcUtils.SearchNearestEnemy(projectile.centerX, projectile.centerY, 128) if npcTarget ~= nil then projectile.speedX, projectile.speedY = Utils.ForceSpeed2D(projectile.speedX, projectile.speedY, 0.63, projectile:GetAngleTo(npcTarget.centerX, npcTarget.centerY), projectile.maxSpeed) chasing = true end end projectile.speedX = projectile.speedX + Utils.RandSym(0.52) projectile.speedY = projectile.speedY + Utils.RandSym(0.52) end function MiniRocket:OnKilled() local projectile = self.projectile --MiscUtils.CreateExplosion(projectile.centerXi, projectile.centerYi, 11, projectile.isCheckNpc, projectile.isCheckPlayer) --EffectUtils.CreateExplosion(projectile.centerX, projectile.centerY) local explosionEffect = EffectUtils.Create( Reg.EffectID("explosion"), projectile.centerX, projectile.centerY, 0, 0, 0, 1, 1.0, Color.new(255, 255, 200) ) end function MiniRocket:OnHitNpc(_, _) self.projectile:Kill() end function MiniRocket:OnHitPlayer(_, _) self.projectile:Kill() end function MiniRocket:OnTileCollide(_, _) self.projectile:Kill() end return MiniRocket ================================================ FILE: projectile_ai/RedSpeedUp.json ================================================ { "RedSpeedUp": { "script": { "path": "RedSpeedUp.lua" } } } ================================================ FILE: projectile_ai/RedSpeedUp.lua ================================================ ---@class TC.RedSpeedUp:ModProjectile local RedSpeedUp = class("RedSpeedUp", ModProjectile) function RedSpeedUp:TouchEffect() local projectile = self.projectile for _ = 1, 12 do EffectUtils.Create( Reg.EffectID("circle"), projectile.centerX, projectile.centerY, Utils.RandSym(3), Utils.RandSym(3), 0, Utils.RandDoubleArea(0.25, 0.25), Utils.RandDoubleArea(0.5, 0.5), Color.new(200, 0, 0) ) end end function RedSpeedUp:Update() local projectile = self.projectile local angle = projectile.speedAngle local speed = Vector2.new(projectile.speedX, projectile.speedY).length speed = speed + 0.1 projectile.speedX = speed * math.cos(angle) projectile.speedY = speed * math.sin(angle) local effect = EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x + Utils.RandSym(10), projectile.hots[1].y + Utils.RandSym(10), projectile.speedX / 4 + Utils.RandSym(0.25), projectile.speedY / 4 + Utils.RandSym(0.25), Utils.RandSym(1), Utils.RandDoubleArea(0.15, 0.35), 1.0, Color.new(200, 0, 0) ) effect:SetDisappearTime(30) end function RedSpeedUp:OnHitNpc(_, _) self:TouchEffect() self.projectile:Kill() end function RedSpeedUp:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function RedSpeedUp:OnTileCollide(_, _) self:TouchEffect() self.projectile:Kill() end return RedSpeedUp ================================================ FILE: projectile_ai/Rocket.json ================================================ { "Rocket": { "script": { "path": "Rocket.lua" } } } ================================================ FILE: projectile_ai/Rocket.lua ================================================ ---@type ModProjectile local Rocket = class("Rocket", ModProjectile) function Rocket:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("smoke"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(2), Utils.RandSym(2), Utils.RandSym(0.1), Utils.RandDoubleArea(0.25, 0.5), 0.6, Color.new(64, 64, 64) ) end if projectile.tickTime % 2 == 0 then EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(0.1), Utils.RandSym(0.1), Utils.RandSym(0.1), Utils.RandDoubleArea(1, 2) ) end end function Rocket:OnKilled() local projectile = self.projectile MiscUtils.CreateExplosion(projectile.centerXi, projectile.centerYi, 11, projectile.isCheckNpc, projectile.isCheckPlayer, true,true) EffectUtils.CreateExplosion(projectile.centerX, projectile.centerY) end function Rocket:OnHitNpc(_, _) self.projectile:Kill() end function Rocket:OnHitPlayer(_, _) self.projectile:Kill() end function Rocket:OnTileCollide(_, _) self.projectile:Kill() end return Rocket ================================================ FILE: projectile_ai/ShadowMagic.json ================================================ { "ShadowMagic": { "script": { "path": "ShadowMagic.lua" } } } ================================================ FILE: projectile_ai/ShadowMagic.lua ================================================ ---@type ModProjectile local ShadowMagic = class("ShadowMagic", ModProjectile) function ShadowMagic:Update() local projectile = self.projectile local chasing = false if projectile.isCheckNpc then local npcTarget = NpcUtils.SearchNearestEnemy(projectile.centerX, projectile.centerY, 120) if npcTarget ~= nil then projectile.speedX, projectile.speedY = Utils.ForceSpeed2D(projectile.speedX, projectile.speedY, 0.8, projectile:GetAngleTo(npcTarget.centerX, npcTarget.centerY), projectile.maxSpeed) chasing = true end end if not chasing then EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x, projectile.hots[1].y, 0, 0, 0, 0.75, 0.25 ) else EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(2), Utils.RandSym(2), 0, 0.75, 0.25 ) end if projectile.tickTime % 2 == 0 then if not chasing then EffectUtils.Create( Reg.EffectID("flash2"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(2), Utils.RandSym(2), Utils.RandSym(0.1), Utils.RandDoubleArea(1, 0.25) ) else EffectUtils.Create( Reg.EffectID("flash2"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(8), Utils.RandSym(8), Utils.RandSym(0.1), Utils.RandDoubleArea(1, 0.25) ) end end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 24, 0, 0, 16) end function ShadowMagic:OnKilled() local projectile = self.projectile local flash2 = Reg.EffectID("flash2") for _ = 1, 8 do EffectUtils.Create( flash2, projectile.centerX, projectile.centerY, Utils.RandSym(4), Utils.RandSym(4), 0, Utils.RandDoubleArea(1, 1) ) end end function ShadowMagic:OnHitNpc(_, _) self.projectile:Kill() end function ShadowMagic:OnHitPlayer(_, _) self.projectile:Kill() end function ShadowMagic:OnTileCollide(_, _) self.projectile:Kill() end return ShadowMagic ================================================ FILE: projectile_ai/ShulkerBullet.json ================================================ { "ShulkerBullet": { "script": { "path": "ShulkerBullet.lua" } } } ================================================ FILE: projectile_ai/ShulkerBullet.lua ================================================ ---@type ModProjectile local ShulkerBullet = class("ShulkerBullet", ModProjectile) function ShulkerBullet:Update() local projectile = self.projectile if projectile.isCheckPlayer then local playerTarget = PlayerUtils.SearchNearestPlayer(projectile.centerX, projectile.centerY, 360) if playerTarget ~= nil then projectile.speedX, projectile.speedY = Utils.ForceSpeed2D(projectile.speedX, projectile.speedY, 0.3, projectile:GetAngleTo(playerTarget.centerX, playerTarget.centerY), projectile.maxSpeed) end end projectile:Rotate(0.1) if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("laser_flash"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(1), Utils.RandSym(1), Utils.RandSym(0.1) ) end if projectile.tickTime > 200 then projectile:Kill() end end function ShulkerBullet:OnKilled() local projectile = self.projectile local laser_flash = Reg.EffectID("laser_flash") for i = 0, 15 do local angle = i * math.pi * 2 / 16 EffectUtils.Create( laser_flash, projectile.hots[1].x, projectile.hots[1].y, math.cos(angle) * 2, math.sin(angle) * 2, Utils.RandSym(0.1), 2 ) end end function ShulkerBullet:OnHitPlayer(player, _) player:AddBuff(Reg.BuffID("levitation"), 120) self.projectile:Kill() end function ShulkerBullet:OnTileCollide(_, _) self.projectile:Kill() end return ShulkerBullet ================================================ FILE: projectile_ai/SnowFlake.json ================================================ { "SnowFlake": { "script": { "path": "SnowFlake.lua" } } } ================================================ FILE: projectile_ai/SnowFlake.lua ================================================ ---@type ModProjectile local SnowFlake = class("SnowFlake", ModProjectile) function SnowFlake:Update() local projectile = self.projectile if projectile.speedX == 0 and projectile.speedY == 0 then projectile:Kill() else projectile.speedX, projectile.speedY = Utils.ForceSpeed2D(projectile.speedX, projectile.speedY, 0.05, projectile.speedAngle, 14.0) end if projectile.tickTime >= 600 then projectile:Kill() end projectile:Rotate(0.03) if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("flash2"), projectile.hots[1].x + Utils.RandSym(20), projectile.hots[1].y + Utils.RandSym(20), Utils.RandSym(2), Utils.RandSym(2), 0, Utils.RandDoubleArea(1.5, 1) ) end end function SnowFlake:OnKilled() local projectile = self.projectile local flash2 = Reg.EffectID("flash2") for _ = 1, 12 do EffectUtils.Create( flash2, projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(5), Utils.RandSym(5), 0, Utils.RandDoubleArea(1, 1) ) end end function SnowFlake:OnHitNpc(_, _) self.projectile:Kill() end function SnowFlake:OnHitPlayer(_, _) self.projectile:Kill() end function SnowFlake:OnTileCollide(_, _) self.projectile:Kill() end return SnowFlake ================================================ FILE: projectile_ai/Spike.json ================================================ { "Spike": { "script": { "path": "Spike.lua" }, "modData": [ [ "int", "crossCount" ] ] } } ================================================ FILE: projectile_ai/Spike.lua ================================================ ---@class TC.Spike:ModProjectile local Spike = class("Spike", ModProjectile) function Spike:Update() local projectile = self.projectile if projectile.modData.crossCount == 0 then projectile.rotateAngle = projectile.speedAngle local effect = EffectUtils.Create( Reg.EffectID("chip"), projectile.centerX, projectile.centerY, projectile.speedX / 2 + Utils.RandSym(2), projectile.speedY / 2 + Utils.RandSym(2), Utils.RandSym(1), Utils.RandDoubleArea(0.5, 0.5), 1.0, Color.new(200, 200, 200) ) effect.gravity = false effect:SetDisappearTime(20) else projectile.rotateAngle = projectile.rotateAngle + 0.1 end end function Spike:OnKilled() local projectile = self.projectile local effectId = Reg.EffectID("chip") for _ = 1, 8 do local effect = EffectUtils.Create( effectId, projectile.centerX, projectile.centerY, projectile.speedX + Utils.RandSym(2), -projectile.speedY + Utils.RandSym(2), Utils.RandSym(1), Utils.RandDoubleArea(1, 1.5), 1.0, Color.new(200, 200, 200) ) effect:SetDisappearTime(40) end end function Spike:OnHitNpc(npc, _) local projectile = self.projectile if projectile.modData.crossCount >= 6 then projectile:Kill() end projectile.modData.crossCount = projectile.modData.crossCount + 1 end function Spike:OnHitPlayer(player, _) local projectile = self.projectile if projectile.modData.crossCount >= 6 then projectile:Kill() end projectile.modData.crossCount = projectile.modData.crossCount + 1 end function Spike:OnTileCollide(_, _) local projectile = self.projectile if projectile.modData.crossCount >= 2 then projectile:Kill() end projectile.modData.crossCount = projectile.modData.crossCount + 1 projectile.speedX = -projectile.speedX / 2 end return Spike ================================================ FILE: projectile_ai/StarArrow.json ================================================ { "StarArrow": { "defaultAI": "Arrow", "script": { "path": "StarArrow.lua" } } } ================================================ FILE: projectile_ai/StarArrow.lua ================================================ ---@type ModProjectile local StarArrow = class("StarArrow", require("Arrow")) function StarArrow:CheckFallStarArrow() local projectile = self.projectile if projectile.modData.attachItemID > 0 then local height = 256 local width = 1024 local offsetX = 0 if projectile.speedX < 0 then offsetX = Utils.RandInt(256) else offsetX = width - Utils.RandInt(256) end local shootX = projectile.centerX - width / 2 + offsetX local shootY = projectile.centerY - height local angle = projectile:GetAngleFrom(shootX, shootY) local speed = 10 local proj = ProjectileUtils.Create( projectile.id, shootX, shootY, speed * math.cos(angle), speed * math.sin(angle), projectile.baseAttack ) proj.isCheckPlayer = projectile.isCheckPlayer proj.isCheckNpc = projectile.isCheckNpc local star = Reg.EffectID("star") for _ = 1, 12 do EffectUtils.Create( star, shootX, shootY, Utils.RandSym(4), Utils.RandSym(4), Utils.RandSym(1), Utils.RandDoubleArea(1, 0.5), 0, Color.Yellow ) end end end function StarArrow:Update() local projectile = self.projectile projectile.rotateAngle = projectile.speedAngle if projectile.tickTime % 8 == 0 then EffectUtils.Create( Reg.EffectID("star"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(2), projectile.speedY / 4 + Utils.RandSym(2), Utils.RandSym(0.25), 0, 0, Color.Yellow ) end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 32) end function StarArrow:OnKilled() local projectile = self.projectile local flame_star = Reg.EffectID("flame_star") for _ = 1, 8 do EffectUtils.Create( flame_star, projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandDoubleArea(-2, 3), Utils.RandSym(1), Utils.RandDoubleArea(1, 0.5), 0, Color.new(200,200,200) ) end EffectUtils.Create( Reg.EffectID("star"), projectile.centerX, projectile.centerY, -projectile.speedX / 4 + Utils.RandSym(2), -projectile.speedY / 4 + Utils.RandSym(2), Utils.RandSym(0.25), Utils.RandDoubleArea(1, 0.5), 0, Color.Yellow ) SoundUtils.PlaySound(Reg.SoundID("bowhit"), projectile.centerXi, projectile.centerYi) end function StarArrow:OnHitNpc(_, _) self:CheckFallStarArrow() self.projectile:Kill() end function StarArrow:OnHitPlayer(_, _) self:CheckFallStarArrow() self.projectile:Kill() end function StarArrow:OnTileCollide(_, _) local projectile = self.projectile if projectile.modData.attachItemID > 0 then ItemUtils.CreateDrop(projectile.modData.attachItemID, 1, projectile.centerX, projectile.centerY, -1.5 * math.cos(projectile.rotateAngle), -4 * math.sin(projectile.rotateAngle)) end self:CheckFallStarArrow() projectile:Kill() end return StarArrow ================================================ FILE: projectile_ai/StarMagic.json ================================================ { "StarMagic": { "script": { "path": "StarMagic.lua" }, "modData": [ [ "int", "crossCount" ] ] } } ================================================ FILE: projectile_ai/StarMagic.lua ================================================ ---@type ModProjectile local StarMagic = class("StarMagic", ModProjectile) function StarMagic:Update() local projectile = self.projectile projectile:Rotate(0.2) if projectile.tickTime % 8 == 0 then EffectUtils.Create( Reg.EffectID("star"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(2), projectile.speedY / 4 + Utils.RandSym(2), Utils.RandSym(0.1), Utils.RandDoubleArea(0.5, 0.5), 0, Color.new(255, 220, 0) ) end if projectile.tickTime % 4 == 0 then EffectUtils.Create( Reg.EffectID("flash2"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(2), projectile.speedY / 4 + Utils.RandSym(2), 0, Utils.RandDoubleArea(0.75, 0.4), 0, Color.Yellow ) end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 24, 16, 16, 0) end function StarMagic:OnKilled() local projectile = self.projectile for _ = 1, 8 do EffectUtils.Create( Reg.EffectID("star"), projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandSym(2), 0, Utils.RandDoubleArea(0.5, 0.25), 0, Color.Yellow ) end end function StarMagic:OnHitNpc(npc, _) local projectile = self.projectile if projectile.modData.crossCount >= 3 then projectile:Kill() end projectile.modData.crossCount = projectile.modData.crossCount + 1 npc:AddBuff(Reg.BuffID("glowing"), 120) end function StarMagic:OnHitPlayer(player, _) local projectile = self.projectile if projectile.modData.crossCount >= 2 then projectile:Kill() end projectile.modData.crossCount = projectile.modData.crossCount + 1 player:AddBuff(Reg.BuffID("glowing"), 120) end function StarMagic:OnTileCollide(_, _) self.projectile:Kill() end return StarMagic ================================================ FILE: projectile_ai/SuperBullet.json ================================================ { "SuperBullet": { "defaultAI": "Bullet", "script": { "path": "SuperBullet.lua" } } } ================================================ FILE: projectile_ai/SuperBullet.lua ================================================ ---@type ModProjectile local SuperBullet = class("SuperBullet", require("Bullet")) function SuperBullet:PostUpdate() local projectile = self.projectile for i = 1, 2 do EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX - projectile.speedX * i / 2, projectile.centerY - projectile.speedY * i / 2, Utils.RandSym(1), -1 - Utils.RandDouble(1), -- speed Utils.RandSym(0.05), Utils.RandDoubleArea(0.5, 0.5), 1, Color.Yellow ) -- rotate, scale, alpha end EffectUtils.Create( Reg.EffectID("fire_flame"), projectile.centerX - Utils.RandDouble(projectile.speedX), projectile.centerY - Utils.RandDouble(projectile.speedY), Utils.RandSym(0.6), -Utils.RandDouble(1), Utils.RandSym(0.05), Utils.RandDoubleArea(0.5, 0.5), Utils.RandDoubleArea(0.5, 0.5) ) end function SuperBullet:OnKilled() local projectile = self.projectile EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, projectile.speedX / 16 + Utils.RandSym(0.6), projectile.speedY / 16 - Utils.RandDouble(1), -- speed Utils.RandSym(0.05), Utils.RandDoubleArea(0.5, 0.5), 1, Color.Yellow ) -- rotate, scale, alpha end return SuperBullet ================================================ FILE: projectile_ai/SuperFire.json ================================================ { "SuperFire": { "script": { "path": "SuperFire.lua" } } } ================================================ FILE: projectile_ai/SuperFire.lua ================================================ ---@class TC.SuperFire:ModProjectile local SuperFire = class("SuperFire", ModProjectile) function SuperFire:GetFireScale() local projectile = self.projectile local scale = 1.0 if projectile.tickTime < 45 then scale = 0.25 + 1.75 * projectile.tickTime / 45 elseif projectile.tickTime < 90 then scale = 2 - (projectile.tickTime - 45) / 10 end scale = scale * 1.25 return scale end function SuperFire:Update() local projectile = self.projectile projectile.speedX, projectile.speedY = Utils.SlowSpeed2D(projectile.speedX, projectile.speedY, 0.14) projectile:Rotate(0.1) local scale = self:GetFireScale() if scale <= 0 or scale >= 90 then projectile:Kill() else local lighting = math.floor((1 - projectile.tickTime / 90) * 32) LightingUtils.Add(projectile.centerXi, projectile.centerYi, 32, 8, 6, 0) if Utils.RandTry(32) then EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, projectile.speedX / 2 + Utils.RandSym(0.25), projectile.speedY - Utils.RandDouble(0.75), Utils.RandSym(0.05), 0.5, 0, Color.new(255, 128, 0) ) end if Utils.RandTry(8) then local effect = EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, projectile.speedX / 4 + Utils.RandSym(1), projectile.speedY / 4 + Utils.RandSym(1), Utils.RandSym(0.05), 0.5, 1.0, Color.new(255, 128, 0) ) effect.gravity = false effect:SetDisappearTime(40) end if projectile.tickTime == 0 then local effect = EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, projectile.speedX / 8 + Utils.RandSym(1), projectile.speedY / 8 + Utils.RandSym(1), Utils.RandSym(0.05), 1.0, 1.0, Color.new(255, 128, 0) ) effect.gravity = false effect:SetDisappearTime(60) end end end function SuperFire:OnDraw() local projectile = self.projectile projectile.color = Color.new(255, 255, 255, math.floor((1 - projectile.tickTime / 60) * 255)) local scale = math.max(self:GetFireScale(), 0.1) projectile.spriteEx.angle = projectile.rotateAngle projectile.spriteEx.scaleRateX = scale projectile.spriteEx.scaleRateY = scale projectile.spriteOffsetX = math.floor((1 - projectile.spriteEx.scaleRateX) * projectile.spriteDefaultWidth / 2); projectile.spriteOffsetY = math.floor((1 - projectile.spriteEx.scaleRateY) * projectile.spriteDefaultHeight / 2); end ---OnHitNpc ---@param npc Npc ---@param _ Attack function SuperFire:OnHitNpc(npc, _) npc:AddBuff(Reg.BuffID("fire"), 100) end ---OnHitPlayer ---@param player Player ---@param _ Attack function SuperFire:OnHitPlayer(player, _) player:AddBuff(Reg.BuffID("fire"), 100) end function SuperFire:OnTileCollide(oldSpeedX, oldSpeedY) local projectile = self.projectile for _ = 1, 4 do local effect = EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, -oldSpeedX / 4 + Utils.RandSym(2), -oldSpeedY / 4 + Utils.RandSym(2), Utils.RandSym(0.05), 0.85, 1.0, Color.new(255, 128, 0) ) effect:SetDisappearTime(20) end projectile:Kill() end return SuperFire ================================================ FILE: projectile_ai/SwordArrow.json ================================================ { "SwordArrow": { "defaultAI": "Arrow", "script": { "path": "SwordArrow.lua" } } } ================================================ FILE: projectile_ai/SwordArrow.lua ================================================ ---@type ModProjectile local SwordArrow = class("SwordArrow", require("Arrow")) function SwordArrow:Update() local projectile = self.projectile local chasing = false if projectile.isCheckNpc then local npcTarget = NpcUtils.SearchNearestEnemy(projectile.centerX, projectile.centerY, 120) if npcTarget ~= nil then projectile.speedX, projectile.speedY = Utils.ForceSpeed2D(projectile.speedX, projectile.speedY, 1.0, projectile:GetAngleTo(npcTarget.centerX, npcTarget.centerY), projectile.maxSpeed) chasing = true end end if not chasing then projectile.gravity = 0.2 EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x, projectile.hots[1].y, 0, 0, 0, 0.5 ) else projectile.gravity = 0.0 EffectUtils.Create( Reg.EffectID("circle"), projectile.hots[1].x, projectile.hots[1].y, Utils.RandSym(2), Utils.RandSym(2), 0, 0.75, 0.25 ) end projectile.rotateAngle = projectile.speedAngle LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 24, 24) end function SwordArrow:OnKilled() local projectile = self.projectile local circle = Reg.EffectID("circle") for _ = 1, 8 do EffectUtils.Create( circle, projectile.centerX, projectile.centerY, Utils.RandSym(4), Utils.RandSym(4) ) end SoundUtils.PlaySound(Reg.SoundID("bowhit"), projectile.centerXi, projectile.centerYi) end function SwordArrow:OnHitNpc(npc, hitAttack) self.projectile:Kill() end function SwordArrow:OnHitPlayer(player, hitAttack) self.projectile:Kill() end return SwordArrow ================================================ FILE: projectile_ai/WaterFlow.json ================================================ { "WaterFlow": { "script": { "path": "WaterFlow.lua" } } } ================================================ FILE: projectile_ai/WaterFlow.lua ================================================ ---@class TC.WaterFlow:ModProjectile local WaterFlow = class("WaterFlow", ModProjectile) function WaterFlow:TouchEffect() local projectile = self.projectile for _ = 1, 4 do EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, Utils.RandSym(1), Utils.RandSym(1) - 2, 0, Utils.RandDoubleArea(1, 1), Utils.RandDoubleArea(1.5, 1.5), Color.new(30, 80, 255) ) end end function WaterFlow:Update() local projectile = self.projectile projectile.color = Color.new(0, 0, 0, 0) projectile.gravity = 0 if projectile.tickTime == 0 then for _ = 1, 2 do local effect = EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.centerX, projectile.centerY, projectile.speedX / 12 + Utils.RandSym(1), projectile.speedY / 12 + Utils.RandSym(1), 0, Utils.RandDoubleArea(1.0, 1.5), 1.0, Color.new(30, 80, 255) ) effect.gravity = false end end local effect = EffectUtils.Create( Reg.EffectID("liquid_paticular"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(0.25), projectile.speedY / 4 + Utils.RandSym(0.25), Utils.RandSym(1), Utils.RandDoubleArea(1.0, 1.5), 1.0, Color.new(30, 80, 255) ) effect.gravity = false effect:SetDisappearTime(50) LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 32) if projectile.tickTime > 160 then projectile:Kill() end end function WaterFlow:OnHitNpc(_, _) self:TouchEffect() self.projectile:Kill() end function WaterFlow:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function WaterFlow:OnTileCollide(_, _) self:TouchEffect() local projectile = self.projectile if projectile.stand then projectile.speedY = -math.abs(projectile.speedY) elseif projectile.isCollisionTop then projectile.speedY = math.abs(projectile.speedY) end if projectile.isCollisionLeft then projectile.speedX = math.abs(projectile.speedX) elseif projectile.isCollisionRight then projectile.speedX = -math.abs(projectile.speedX) end end return WaterFlow ================================================ FILE: projectile_ai/WaterMagic.json ================================================ { "WaterMagic": { "script": { "path": "WaterMagic.lua" } } } ================================================ FILE: projectile_ai/WaterMagic.lua ================================================ ---@type ModProjectile local WaterMagic = class("WaterMagic", ModProjectile) function WaterMagic:TouchEffect() local projectile = self.projectile for _ = 1, 2 do EffectUtils.Create( Reg.EffectID("flash2"), projectile.centerX, projectile.centerY, Utils.RandSym(2), Utils.RandSym(2), 0, Utils.RandDoubleArea(1, 1), 0, Color.new(66, 66, 255) ) end end function WaterMagic:Update() local projectile = self.projectile if projectile.tickTime % 2 == 0 then EffectUtils.Create( Reg.EffectID("chip"), projectile.hots[1].x, projectile.hots[1].y, projectile.speedX / 4 + Utils.RandSym(0.25), projectile.speedY / 4 + Utils.RandSym(0.25), Utils.RandSym(1), Utils.RandDoubleArea(1, 1), 0.5, Color.new(66, 66, 255) ) end LightingUtils.AddDelay(projectile.centerXi, projectile.centerYi, 32, 24, 0, 0, 16) if projectile.tickTime > 32 then projectile:Kill() end end function WaterMagic:OnHitNpc(_, _) self:TouchEffect() self.projectile:Kill() end function WaterMagic:OnHitPlayer(_, _) self:TouchEffect() self.projectile:Kill() end function WaterMagic:OnTileCollide(_, _) self:TouchEffect() self.projectile:Kill() end return WaterMagic ================================================ FILE: projectile_ai_global/GProjectile.lua ================================================ ---@type GlobalProjectile local GProjectile = class("GProjectile", GlobalProjectile) function GProjectile:Update() end return GProjectile ================================================ FILE: projectile_ai_global/GlobalProjectile.json ================================================ { "GlobalClass": [ "GProjectile" ] } ================================================ FILE: projectiles/air_bullet.json ================================================ { "air_bullet": { "ai": "AirBullet", "textureData": "air_bullet.png", "width": 28, "height": 20, "gfxWidth": 28, "gfxHeight": 20, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 10]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 12.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/air_wave.json ================================================ { "air_wave": { "ai": "AirWave", "textureData": "air_wave.png", "width": 48, "height": 16, "gfxWidth": 48, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 8]], "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "ROTATED_BOX", "maxSpeed": 12.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/amethyst_magic.json ================================================ { "amethyst_magic": { "ai": "AmethystMagic", "textureData": "amethyst_magic.png", "width": 20, "height": 24, "gfxWidth": 20, "gfxHeight": 24, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[10, 12]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 8.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/black_hole.json ================================================ { "black_hole": { "ai": "BlackHole", "textureData": "black_hole.png", "width": 64, "height": 64, "gfxWidth": 64, "gfxHeight": 64, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[16, 16]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 6.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/blaze_rod.json ================================================ { "blaze_rod": { "ai": "BlazeRod", "textureData": "blaze_rod.png", "width": 48, "height": 16, "gfxWidth": 48, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[24, 8]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": true, "keepStrick": false } } ================================================ FILE: projectiles/blood_arrow.json ================================================ { "blood_arrow": { "ai": "BloodArrow", "textureData": "blood_arrow.png", "width": 32, "height": 14, "gfxWidth": 32, "gfxHeight": 14, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 7]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/blue_arrow.json ================================================ { "blue_arrow": { "ai": "BlueArrow", "textureData": "blue_arrow.png", "width": 32, "height": 14, "gfxWidth": 32, "gfxHeight": 14, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 7]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": false } } ================================================ FILE: projectiles/bomb.json ================================================ { "bomb": { "ai": "Bomb", "textureData": "bomb.png", "width": 20, "height": 20, "gfxWidth": 36, "gfxHeight": 36, "gfxOffsetX": -8, "gfxOffsetY": -8, "hots": [[18, 4]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 8.0, "gravity": true, "foreground": false, "fixByBlocks": true, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/bone.json ================================================ { "bone": { "ai": "Spike", "textureData": "bone.png", "width": 24, "height": 20, "gfxWidth": 24, "gfxHeight": 20, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 10]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": false } } ================================================ FILE: projectiles/boomerang.json ================================================ { "boomerang": { "ai": "Boomerang", "textureData": "boomerang.png", "width": 18, "height": 32, "gfxWidth": 18, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[8, 16]], "frameStyle": 1, "frames": 1, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 8.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "special": 0, "keepStrick": false, "trajectoryPrediction": false, "killWhenHitTile": false } } ================================================ FILE: projectiles/bullet.json ================================================ { "bullet": { "ai": "Bullet", "textureData": "bullet.png", "width": 24, "height": 2, "gfxWidth": 24, "gfxHeight": 2, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 0]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 32.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/bullet_laser.json ================================================ { "bullet_laser": { "ai": "LaserBullet", "textureData": "bullet_laser.png", "width": 64, "height": 2, "gfxWidth": 64, "gfxHeight": 2, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 0]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 32.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/bullet_super.json ================================================ { "bullet_super": { "ai": "SuperBullet", "textureData": "bullet_super.png", "width": 64, "height": 2, "gfxWidth": 64, "gfxHeight": 2, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [ [ 0, 0 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 32.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/crystal_magic.json ================================================ { "crystal_magic": { "ai": "CrystalMagic", "textureData": "crystal_magic.png", "width": 32, "height": 32, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[16, 16]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 6.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/cursed_arrow.json ================================================ { "cursed_arrow": { "ai": "CursedArrow", "textureData": "cursed_arrow.png", "width": 32, "height": 14, "gfxWidth": 32, "gfxHeight": 14, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 7]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": false } } ================================================ FILE: projectiles/fire_arrow.json ================================================ { "fire_arrow": { "ai": "FireArrow", "textureData": "fire_arrow.png", "width": 32, "height": 14, "gfxWidth": 32, "gfxHeight": 14, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 7]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/fire_boomerang.json ================================================ { "fire_boomerang": { "ai": "Boomerang", "textureData": "fire_boomerang.png", "width": 18, "height": 32, "gfxWidth": 18, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[8, 16]], "frameStyle": 1, "frames": 1, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 16.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "special": 1, "keepStrick": false, "trajectoryPrediction": false, "killWhenHitTile": false } } ================================================ FILE: projectiles/fire_charge.json ================================================ { "fire_charge": { "ai": "Fireball", "textureData": "fire_charge.png", "width": 24, "height": 24, "gfxWidth": 24, "gfxHeight": 24, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [ [ 12, 12 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 6.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/fire_element.json ================================================ { "fire_element": { "ai": "FireElement", "textureData": "fire_element.png", "width": 24, "height": 16, "gfxWidth": 24, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 8]], "frameStyle": 1, "frames": 2, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 12.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/fire_flow.json ================================================ { "fire_flow": { "ai": "FireFlow", "textureData": "super_fire.png", "width": 16, "height": 16, "gfxWidth": 16, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [ [ 8, 8 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 14.0, "gravity": true, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/fire_flow_large.json ================================================ { "fire_flow_large": { "ai": "FireFlowLarge", "textureData": "super_fire.png", "width": 24, "height": 24, "gfxWidth": 16, "gfxHeight": 16, "gfxOffsetX": 4, "gfxOffsetY": 4, "hots": [ [ 8, 8 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 14.0, "gravity": true, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/fire_magic.json ================================================ { "fire_magic": { "ai": "FireMagic", "textureData": "fire_magic.png", "width": 20, "height": 20, "gfxWidth": 20, "gfxHeight": 20, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [ [ 10, 10 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 8.0, "gravity": true, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/fire_wave.json ================================================ { "fire_wave": { "ai": "FireElement", "textureData": "fire_wave.png", "width": 48, "height": 32, "gfxWidth": 48, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 16]], "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "ROTATED_BOX", "maxSpeed": 12.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/glow_ball.json ================================================ { "glow_ball": { "ai": "Glowball", "textureData": "glow_ball.png", "width": 16, "height": 16, "gfxWidth": 16, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[8, 8]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 8.0, "gravity": true, "foreground": false, "fixByBlocks": true, "througthBlock": false, "keepStrick": false } } ================================================ FILE: projectiles/glow_bomb.json ================================================ { "glow_bomb": { "ai": "GlowBomb", "textureData": "glow_bomb.png", "width": 20, "height": 20, "gfxWidth": 36, "gfxHeight": 36, "gfxOffsetX": -4, "gfxOffsetY": -4, "hots": [[14, 4]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 8.0, "gravity": true, "foreground": false, "fixByBlocks": true, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/grenade.json ================================================ { "grenade": { "ai": "Grenade", "textureData": "grenade.png", "width": 20, "height": 20, "gfxWidth": 28, "gfxHeight": 28, "gfxOffsetX": -4, "gfxOffsetY": -4, "hots": [[14, 4]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 8.0, "gravity": true, "foreground": false, "fixByBlocks": true, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/gun_fire.json ================================================ { "gun_fire": { "ai": "Fire", "textureData": "gun_fire.png", "width": 16, "height": 16, "gfxWidth": 16, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[8, 8]], "frameStyle": 1, "frames": 3, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 32.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": false } } ================================================ FILE: projectiles/ice_arrow.json ================================================ { "ice_arrow": { "ai": "IceArrow", "textureData": "ice_arrow.png", "width": 32, "height": 14, "gfxWidth": 32, "gfxHeight": 14, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 7]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": true, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/ice_bullet.json ================================================ { "ice_bullet": { "ai": "IceBullet", "textureData": "ice_bullet.png", "width": 12, "height": 12, "gfxWidth": 24, "gfxHeight": 24, "gfxOffsetX": -6, "gfxOffsetY": -6, "hots": [[12, 12]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 12.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/ice_magic.json ================================================ { "ice_magic": { "ai": "IceMagic", "textureData": "ice_magic.png", "width": 12, "height": 12, "gfxWidth": 24, "gfxHeight": 12, "gfxOffsetX": -6, "gfxOffsetY": 0, "hots": [ [ 6, 6 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 12.0, "gravity": false, "foreground": true, "fixByBlocks": true, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/light_bullet_laser.json ================================================ { "light_bullet_laser": { "ai": "LaserBullet", "textureData": "light_bullet_laser.png", "width": 64, "height": 2, "gfxWidth": 64, "gfxHeight": 2, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 0]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 32.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/lighting_arrow.json ================================================ { "lighting_arrow": { "ai": "LightingArrow", "textureData": "lighting_arrow.png", "width": 32, "height": 14, "gfxWidth": 32, "gfxHeight": 14, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 7]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/lighting_bullet_blue.json ================================================ { "lighting_bullet_blue": { "ai": "BlueBullet", "textureData": "lighting_bullet_blue.png", "width": 32, "height": 32, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[16, 16]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 6.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/lighting_bullet_red_invert2.json ================================================ { "lighting_bullet_red_invert2": { "ai": "RedSpeedUp", "textureData": "lighting_bullet_red_invert2.png", "width": 32, "height": 32, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[16, 16]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 6.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/lighting_bullet_yellow.json ================================================ { "lighting_bullet_yellow": { "ai": "LightingBulletYellow", "textureData": "lighting_bullet_yellow.png", "width": 32, "height": 32, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[16, 16]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 6.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/lighting_wheel.json ================================================ { "lighting_wheel": { "ai": "LightingWheel", "textureData": "lighting_wheel.png", "width": 32, "height": 32, "gfxWidth": 32, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[16, 16]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 6.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/magic_wave.json ================================================ { "magic_wave": { "ai": "MagicWave", "textureData": "magic_wave.png", "width": 48, "height": 32, "gfxWidth": 48, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 16]], "frameStyle": 1, "frames": 2, "frameSpeed": 4, "shape": "ROTATED_BOX", "maxSpeed": 12.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/magic_wave3.json ================================================ { "magic_wave3": { "ai": "BlueWave", "textureData": "magic_wave3.png", "width": 48, "height": 32, "gfxWidth": 48, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 16]], "frameStyle": 1, "frames": 4, "frameSpeed": 4, "shape": "ROTATED_BOX", "maxSpeed": 12.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/mini_rocket.json ================================================ { "mini_rocket": { "ai": "MiniRocket", "textureData": "mini_rocket.png", "width": 24, "height": 16, "gfxWidth": 24, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [ [ 0, 8 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/rocket.json ================================================ { "rocket": { "ai": "Rocket", "textureData": "rocket.png", "width": 28, "height": 20, "gfxWidth": 28, "gfxHeight": 20, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [ [ 0, 10 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/shadow_magic.json ================================================ { "shadow_magic": { "ai": "ShadowMagic", "textureData": "shadow_magic.png", "width": 20, "height": 20, "gfxWidth": 20, "gfxHeight": 20, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[10, 10]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 8.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/shulker_bullet.json ================================================ { "shulker_bullet": { "ai": "ShulkerBullet", "textureData": "shulker_bullet.png", "width": 16, "height": 16, "gfxWidth": 16, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[8, 8]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/small_air_bullet.json ================================================ { "small_air_bullet": { "ai": "AirBullet", "textureData": "small_air_bullet.png", "width": 28, "height": 12, "gfxWidth": 28, "gfxHeight": 12, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 6]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 12.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/snow_flake.json ================================================ { "snow_flake": { "ai": "SnowFlake", "textureData": "snow_flake.png", "width": 32, "height": 32, "gfxWidth": 40, "gfxHeight": 40, "gfxOffsetX": -4, "gfxOffsetY": -4, "hots": [[16, 16]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 3.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/spike.json ================================================ { "spike": { "ai": "Spike", "textureData": "spike.png", "width": 28, "height": 16, "gfxWidth": 28, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 7]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/star.json ================================================ { "star": { "ai": "StarMagic", "textureData": "star.png", "width": 22, "height": 24, "gfxWidth": 22, "gfxHeight": 24, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [ [ 11, 12 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 8.0, "gravity": false, "foreground": true, "fixByBlocks": false, "througthBlock": true, "keepStrick": false } } ================================================ FILE: projectiles/star_arrow.json ================================================ { "star_arrow": { "ai": "StarArrow", "textureData": "star_arrow.png", "width": 32, "height": 14, "gfxWidth": 32, "gfxHeight": 14, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 7]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/super_fire.json ================================================ { "super_fire": { "ai": "SuperFire", "textureData": "super_fire.png", "width": 16, "height": 16, "gfxWidth": 16, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[8, 8]], "frameStyle": 1, "frames": 3, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 32.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": false } } ================================================ FILE: projectiles/sword_arrow.json ================================================ { "sword_arrow": { "ai": "SwordArrow", "textureData": "sword_arrow.png", "width": 32, "height": 20, "gfxWidth": 32, "gfxHeight": 20, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 10]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 10.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/tnt.json ================================================ { "tnt": { "ai": "Bomb", "textureData": "tnt.png", "width": 16, "height": 16, "gfxWidth": 16, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[8, 0]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 8.0, "gravity": true, "foreground": false, "fixByBlocks": true, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/water_flow.json ================================================ { "water_flow": { "ai": "WaterFlow", "textureData": "super_fire.png", "width": 16, "height": 16, "gfxWidth": 16, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [ [ 8, 8 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 14.0, "gravity": true, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/water_magic.json ================================================ { "water_magic": { "ai": "WaterMagic", "textureData": "water_magic.png", "width": 16, "height": 16, "gfxWidth": 16, "gfxHeight": 16, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [ [ 8, 8 ] ], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "BOX", "maxSpeed": 14.0, "gravity": true, "foreground": true, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/wooden_arrow.json ================================================ { "wooden_arrow": { "ai": "Arrow", "textureData": "wooden_arrow.png", "width": 32, "height": 14, "gfxWidth": 32, "gfxHeight": 14, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[0, 7]], "frameStyle": 1, "frames": 1, "frameSpeed": 8, "shape": "ROTATED_BOX", "maxSpeed": 6.0, "gravity": true, "foreground": false, "fixByBlocks": false, "througthBlock": false, "keepStrick": true } } ================================================ FILE: projectiles/wooden_boomerang.json ================================================ { "wooden_boomerang": { "ai": "Boomerang", "textureData": "wooden_boomerang.png", "width": 18, "height": 32, "gfxWidth": 18, "gfxHeight": 32, "gfxOffsetX": 0, "gfxOffsetY": 0, "hots": [[8, 16]], "frameStyle": 1, "frames": 1, "frameSpeed": 16, "shape": "BOX", "maxSpeed": 8.0, "gravity": false, "foreground": false, "fixByBlocks": false, "througthBlock": false, "special": 0, "keepStrick": false, "trajectoryPrediction": false, "killWhenHitTile": false } } ================================================ FILE: recipe_config/Brew.json ================================================ { "Brew": { "iconItem": "brewing_stand", "sourceGroups": [ { "slotCount": 2, "searchAction": "SA_FIX" } ], "resultSlotCount": 1, "exData": [ ["int", "time"] ] } } ================================================ FILE: recipe_config/Craft3x.json ================================================ { "Craft3x": { "iconItem": "crafting_table", "sourceGroups": [ { "slotCount": 9, "align": true, "alignWidth": 3, "alignHeight": 3, "searchAction": "SA_NORMAL" } ], "resultSlotCount": 2, "exData": [] } } ================================================ FILE: recipe_config/Repair.json ================================================ { "Repair": { "iconItem": "anvil", "sourceGroups": [ { "slotCount": 2, "searchAction": "SA_FIX" } ], "resultSlotCount": 1, "exData": [ ["double", "repairRate"] ] } } ================================================ FILE: recipe_config/Smelt.json ================================================ { "Smelt": { "iconItem": "furnace", "sourceGroups": [ { "slotCount": 1, "searchAction": "SA_FIX" } ], "resultSlotCount": 1, "exData": [ ["int", "time"] ] } } ================================================ FILE: recipes/brew/potion_awkward.json ================================================ { "config": "Brew", "results": [ { "id": "potion_awkward", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_water" ], [ "B", "nether_wart" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_fire_resistance.json ================================================ { "config": "Brew", "results": [ { "id": "potion_fire_resistance", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "magma_cream" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_fire_resistance_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_fire_resistance_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_fire_resistance" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_glowing.json ================================================ { "config": "Brew", "results": [ { "id": "potion_glowing", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "glowing_mushroom" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_harming.json ================================================ { "config": "Brew", "results": [ { "id": "potion_harming", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_healing" ], [ "B", "fermented_spider_eye" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_harming_2.json ================================================ { "config": "Brew", "results": [ { "id": "potion_harming", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_poison" ], [ "B", "fermented_spider_eye" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_harming_super.json ================================================ { "config": "Brew", "results": [ { "id": "potion_harming_super", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_harming" ], [ "B", "glowstone_dust" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_healing.json ================================================ { "config": "Brew", "results": [ { "id": "potion_healing", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "glistering_melon_slice" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_healing_super.json ================================================ { "config": "Brew", "results": [ { "id": "potion_healing_super", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_healing" ], [ "B", "glowstone_dust" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_invisibility.json ================================================ { "config": "Brew", "results": [ { "id": "potion_invisibility", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_night_vision" ], [ "B", "fermented_spider_eye" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_invisibility_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_invisibility_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_invisibility" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_leaping.json ================================================ { "config": "Brew", "results": [ { "id": "potion_leaping", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "rabbit_foot" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_leaping_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_leaping_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_leaping" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_night_vision.json ================================================ { "config": "Brew", "results": [ { "id": "potion_night_vision", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "golden_carrot" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_night_vision_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_night_vision_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_night_vision" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_poison.json ================================================ { "config": "Brew", "results": [ { "id": "potion_poison", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "poison_mushroom" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_poison_2.json ================================================ { "config": "Brew", "results": [ { "id": "potion_poison", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "spider_eye" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_poison_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_poison_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_poison" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_regeneration.json ================================================ { "config": "Brew", "results": [ { "id": "potion_regeneration", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "ghast_tear" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_regeneration_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_regeneration_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_regeneration" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_slow_falling.json ================================================ { "config": "Brew", "results": [ { "id": "potion_slow_falling", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "phantom_membrane" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_slow_falling_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_slow_falling_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_slow_falling" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_slowness.json ================================================ { "config": "Brew", "results": [ { "id": "potion_slowness", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_swiftness" ], [ "B", "fermented_spider_eye" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_slowness_2.json ================================================ { "config": "Brew", "results": [ { "id": "potion_slowness", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_leaping" ], [ "B", "fermented_spider_eye" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_slowness_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_slowness_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_slowness" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_strength.json ================================================ { "config": "Brew", "results": [ { "id": "potion_strength", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "blaze_powder" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_strength_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_strength_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_strength" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_swiftness.json ================================================ { "config": "Brew", "results": [ { "id": "potion_swiftness", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "suger" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_swiftness_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_swiftness_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_swiftness" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_water_breathing.json ================================================ { "config": "Brew", "results": [ { "id": "potion_water_breathing", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_awkward" ], [ "B", "pufferfish" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_water_breathing_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_water_breathing_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_water_breathing" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_weakness.json ================================================ { "config": "Brew", "results": [ { "id": "potion_weakness", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_strength" ], [ "B", "fermented_spider_eye" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_weakness_2.json ================================================ { "config": "Brew", "results": [ { "id": "potion_weakness", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_regeneration" ], [ "B", "fermented_spider_eye" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/brew/potion_weakness_long.json ================================================ { "config": "Brew", "results": [ { "id": "potion_weakness_long", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "potion_weakness" ], [ "B", "redstone" ] ], "exData": { "time": 400 } } ================================================ FILE: recipes/craft3x/acacia_plank.json ================================================ { "config": "Craft3x", "results": [ { "id": "acacia_plank", "stackSize": 4 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "wood_acacia" ] ] } ================================================ FILE: recipes/craft3x/amethyst_staff.json ================================================ { "config": "Craft3x", "results": [ { "id": "amethyst_staff", "stackSize": 1 } ], "pattern": [ "OAB", "OCA", "COO" ], "elements": [ [ "A", "lapis_lazuli" ], [ "B", "gold_ingot" ], [ "C", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/amethyst_staff_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "amethyst_staff", "stackSize": 1 } ], "pattern": [ "OAB", "OCA", "COO" ], "elements": [ [ "A", "lapis_lazuli" ], [ "B", "gold_ingot" ], [ "C", "lead_ingot" ] ] } ================================================ FILE: recipes/craft3x/ancient_ingot.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "ancient_ingot", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "netherite_ingot" ], [ "B", "ancient_sample" ] ] } ================================================ FILE: recipes/craft3x/andesite.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "andesite", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "cobblestone" ], [ "B", "diorite" ] ] } ================================================ FILE: recipes/craft3x/andesite_polished.json ================================================ { "config": "Craft3x", "results": [ { "id": "andesite_polished", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "andesite" ] ] } ================================================ FILE: recipes/craft3x/anvil.json ================================================ { "config": "Craft3x", "results": [ { "id": "anvil", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "BBB" ], "elements": [ [ "A", "block_iron" ], [ "B", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/barrel.json ================================================ { "config": "Craft3x", "results": [ { "id": "barrel", "stackSize": 1 } ], "pattern": [ "BAB", "BOB", "BAB" ], "elements": [ [ "A", "OD_WOODEN_PLATFORM" ], [ "B", "OD_WOODEN_PLANK" ] ] } ================================================ FILE: recipes/craft3x/bench_acacia.json ================================================ { "config": "Craft3x", "results": [ { "id": "bench_acacia", "stackSize": 1 } ], "pattern": [ "AAA", "BOB", "OOO" ], "elements": [ [ "A", "acacia_plank" ], [ "B", "platform_acacia" ] ] } ================================================ FILE: recipes/craft3x/bench_birch.json ================================================ { "config": "Craft3x", "results": [ { "id": "bench_birch", "stackSize": 1 } ], "pattern": [ "AAA", "BOB", "OOO" ], "elements": [ [ "A", "birch_plank" ], [ "B", "platform_birch" ] ] } ================================================ FILE: recipes/craft3x/bench_dark_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "bench_dark_oak", "stackSize": 1 } ], "pattern": [ "AAA", "BOB", "OOO" ], "elements": [ [ "A", "dark_oak_plank" ], [ "B", "platform_dark_oak" ] ] } ================================================ FILE: recipes/craft3x/bench_jungle.json ================================================ { "config": "Craft3x", "results": [ { "id": "bench_jungle", "stackSize": 1 } ], "pattern": [ "AAA", "BOB", "OOO" ], "elements": [ [ "A", "jungle_plank" ], [ "B", "platform_jungle" ] ] } ================================================ FILE: recipes/craft3x/bench_nether.json ================================================ { "config": "Craft3x", "results": [ { "id": "bench_nether", "stackSize": 1 } ], "pattern": [ "AAA", "BOB", "OOO" ], "elements": [ [ "A", "nether_brick" ], [ "B", "platform_nether_brick" ] ] } ================================================ FILE: recipes/craft3x/bench_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "bench_oak", "stackSize": 1 } ], "pattern": [ "AAA", "BOB", "OOO" ], "elements": [ [ "A", "oak_plank" ], [ "B", "platform_oak" ] ] } ================================================ FILE: recipes/craft3x/bench_palm.json ================================================ { "config": "Craft3x", "results": [ { "id": "bench_palm", "stackSize": 1 } ], "pattern": [ "AAA", "BOB", "OOO" ], "elements": [ [ "A", "palm_plank" ], [ "B", "platform_palm" ] ] } ================================================ FILE: recipes/craft3x/bench_spruce.json ================================================ { "config": "Craft3x", "results": [ { "id": "bench_spruce", "stackSize": 1 } ], "pattern": [ "AAA", "BOB", "OOO" ], "elements": [ [ "A", "spruce_plank" ], [ "B", "platform_spruce" ] ] } ================================================ FILE: recipes/craft3x/bench_tainted.json ================================================ { "config": "Craft3x", "results": [ { "id": "bench_tainted", "stackSize": 1 } ], "pattern": [ "AAA", "BOB", "OOO" ], "elements": [ [ "A", "tainted_plank" ], [ "B", "platform_tainted" ] ] } ================================================ FILE: recipes/craft3x/bench_volcano.json ================================================ { "config": "Craft3x", "results": [ { "id": "bench_volcano", "stackSize": 1 } ], "pattern": [ "AAA", "BOB", "OOO" ], "elements": [ [ "A", "volcano_plank" ], [ "B", "platform_volcano" ] ] } ================================================ FILE: recipes/craft3x/birch_plank.json ================================================ { "config": "Craft3x", "results": [ { "id": "birch_plank", "stackSize": 4 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "wood_birch" ] ] } ================================================ FILE: recipes/craft3x/blaze_powder.json ================================================ { "config": "Craft3x", "results": [ { "id": "blaze_powder", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "blaze_rod" ] ] } ================================================ FILE: recipes/craft3x/block_coal.json ================================================ { "config": "Craft3x", "results": [ { "id": "block_coal", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "coal" ] ] } ================================================ FILE: recipes/craft3x/block_diamond.json ================================================ { "config": "Craft3x", "results": [ { "id": "block_diamond", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "diamond" ] ] } ================================================ FILE: recipes/craft3x/block_emerald.json ================================================ { "config": "Craft3x", "results": [ { "id": "block_emerald", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "emerald" ] ] } ================================================ FILE: recipes/craft3x/block_gold.json ================================================ { "config": "Craft3x", "results": [ { "id": "block_gold", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/block_iron.json ================================================ { "config": "Craft3x", "results": [ { "id": "block_iron", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "iron_ingot" ] ] } ================================================ FILE: recipes/craft3x/block_lapis.json ================================================ { "config": "Craft3x", "results": [ { "id": "block_lapis", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "lapis_lazuli" ] ] } ================================================ FILE: recipes/craft3x/block_netherite.json ================================================ { "config": "Craft3x", "results": [ { "id": "block_netherite", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "netherite_ingot" ] ] } ================================================ FILE: recipes/craft3x/block_quartz.json ================================================ { "config": "Craft3x", "results": [ { "id": "block_quartz", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "quartz" ] ] } ================================================ FILE: recipes/craft3x/block_redstone.json ================================================ { "config": "Craft3x", "results": [ { "id": "block_redstone", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "redstone" ] ] } ================================================ FILE: recipes/craft3x/blood_arrow.json ================================================ { "config": "Craft3x", "results": [ { "id": "blood_arrow", "stackSize": 1 } ], "pattern": [ "BOO", "AOO", "BOO" ], "elements": [ [ "A", "wooden_arrow" ], [ "B", "rotten_flesh" ] ] } ================================================ FILE: recipes/craft3x/blood_arrow_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "blood_arrow", "stackSize": 1 } ], "pattern": [ "OBO", "BAB", "OBO" ], "elements": [ [ "A", "wooden_arrow" ], [ "B", "spider_eye" ] ] } ================================================ FILE: recipes/craft3x/blood_bow.json ================================================ { "config": "Craft3x", "results": [ { "id": "blood_bow", "stackSize": 1 } ], "pattern": [ "BAC", "AOC", "BAC" ], "elements": [ [ "A", "copper_ingot" ], [ "B", "rotten_flesh" ], [ "C", "string" ] ] } ================================================ FILE: recipes/craft3x/blue_ice.json ================================================ { "config": "Craft3x", "results": [ { "id": "blue_ice", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "ice_packed" ] ] } ================================================ FILE: recipes/craft3x/blue_stone_bow.json ================================================ { "config": "Craft3x", "results": [ { "id": "blue_stone_bow", "stackSize": 1 } ], "pattern": [ "BAC", "AOC", "BAC" ], "elements": [ [ "A", "diamond" ], [ "B", "lapis_lazuli" ], [ "C", "string" ] ] } ================================================ FILE: recipes/craft3x/blue_torch.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "blue_torch", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "torch" ], [ "B", "dye_blue" ] ] } ================================================ FILE: recipes/craft3x/blue_wire.json ================================================ { "config": "Craft3x", "results": [ { "id": "blue_wire", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "red_wire" ], [ "B", "dye_blue" ] ] } ================================================ FILE: recipes/craft3x/bomb.json ================================================ { "config": "Craft3x", "results": [ { "id": "bomb", "stackSize": 1 } ], "pattern": [ "CBC", "BAB", "CBC" ], "elements": [ [ "A", "fire_charge" ], [ "B", "gunpowder" ], [ "C", "sand" ] ] } ================================================ FILE: recipes/craft3x/bomb_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "bomb", "stackSize": 1 } ], "pattern": [ "CBC", "BAB", "CBC" ], "elements": [ [ "A", "fire_charge" ], [ "B", "gunpowder" ], [ "C", "red_sand" ] ] } ================================================ FILE: recipes/craft3x/bone_block.json ================================================ { "config": "Craft3x", "results": [ { "id": "bone_block", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "bone_meal" ] ] } ================================================ FILE: recipes/craft3x/bone_meal.json ================================================ { "config": "Craft3x", "results": [ { "id": "bone_meal", "stackSize": 3 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "bone" ] ] } ================================================ FILE: recipes/craft3x/bone_meal_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "bone_meal", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "bone_block" ] ] } ================================================ FILE: recipes/craft3x/book.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "book", "stackSize": 1 } ], "pattern": [ "AAA", "BOO", "OOO" ], "elements": [ [ "A", "paper" ], [ "B", "leather" ] ] } ================================================ FILE: recipes/craft3x/book_block.json ================================================ { "config": "Craft3x", "results": [ { "id": "book_block", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "book" ] ] } ================================================ FILE: recipes/craft3x/bookcase_acacia.json ================================================ { "config": "Craft3x", "results": [ { "id": "bookcase_acacia", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "AAA" ], "elements": [ [ "A", "acacia_plank" ], [ "B", "book_block" ] ] } ================================================ FILE: recipes/craft3x/bookcase_birch.json ================================================ { "config": "Craft3x", "results": [ { "id": "bookcase_birch", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "AAA" ], "elements": [ [ "A", "birch_plank" ], [ "B", "book_block" ] ] } ================================================ FILE: recipes/craft3x/bookcase_dark_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "bookcase_dark_oak", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "AAA" ], "elements": [ [ "A", "dark_oak_plank" ], [ "B", "book_block" ] ] } ================================================ FILE: recipes/craft3x/bookcase_jungle.json ================================================ { "config": "Craft3x", "results": [ { "id": "bookcase_jungle", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "AAA" ], "elements": [ [ "A", "jungle_plank" ], [ "B", "book_block" ] ] } ================================================ FILE: recipes/craft3x/bookcase_nether.json ================================================ { "config": "Craft3x", "results": [ { "id": "bookcase_nether", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "AAA" ], "elements": [ [ "A", "nether_brick" ], [ "B", "book_block" ] ] } ================================================ FILE: recipes/craft3x/bookcase_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "bookcase_oak", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "AAA" ], "elements": [ [ "A", "oak_plank" ], [ "B", "book_block" ] ] } ================================================ FILE: recipes/craft3x/bookcase_palm.json ================================================ { "config": "Craft3x", "results": [ { "id": "bookcase_palm", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "AAA" ], "elements": [ [ "A", "palm_plank" ], [ "B", "book_block" ] ] } ================================================ FILE: recipes/craft3x/bookcase_spruce.json ================================================ { "config": "Craft3x", "results": [ { "id": "bookcase_spruce", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "AAA" ], "elements": [ [ "A", "spruce_plank" ], [ "B", "book_block" ] ] } ================================================ FILE: recipes/craft3x/bookcase_tainted.json ================================================ { "config": "Craft3x", "results": [ { "id": "bookcase_tainted", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "AAA" ], "elements": [ [ "A", "tainted_plank" ], [ "B", "book_block" ] ] } ================================================ FILE: recipes/craft3x/bookcase_volcano.json ================================================ { "config": "Craft3x", "results": [ { "id": "bookcase_volcano", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "AAA" ], "elements": [ [ "A", "volcano_plank" ], [ "B", "book_block" ] ] } ================================================ FILE: recipes/craft3x/boomerang.json ================================================ { "config": "Craft3x", "results": [ { "id": "boomerang", "stackSize": 1 } ], "pattern": [ "OAO", "AOO", "OAO" ], "elements": [ [ "A", "copper_ingot" ] ] } ================================================ FILE: recipes/craft3x/boomerang_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "boomerang", "stackSize": 1 } ], "pattern": [ "OAO", "AOO", "OAO" ], "elements": [ [ "A", "tin_ingot" ] ] } ================================================ FILE: recipes/craft3x/bowl.json ================================================ { "config": "Craft3x", "results": [ { "id": "bowl", "stackSize": 4 } ], "pattern": [ "AOA", "OAO", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ] ] } ================================================ FILE: recipes/craft3x/bread.json ================================================ { "config": "Craft3x", "results": [ { "id": "bread", "stackSize": 1 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "wheat" ] ] } ================================================ FILE: recipes/craft3x/brewing_stand.json ================================================ { "config": "Craft3x", "results": [ { "id": "brewing_stand", "stackSize": 1 } ], "pattern": [ "OAO", "BBB", "OOO" ], "elements": [ [ "A", "blaze_rod" ], [ "B", "cobblestone" ] ] } ================================================ FILE: recipes/craft3x/brick.json ================================================ { "config": "Craft3x", "results": [ { "id": "brick", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "red_brick" ] ] } ================================================ FILE: recipes/craft3x/bronze_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "bronze_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "bronze_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/bronze_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "bronze_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "bronze_ingot" ] ] } ================================================ FILE: recipes/craft3x/bronze_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "bronze_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "bronze_ingot" ] ] } ================================================ FILE: recipes/craft3x/bronze_ingot.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "bronze_ingot", "stackSize": 2 } ], "pattern": [ "ABB", "BOO", "OOO" ], "elements": [ [ "A", "tin_ingot" ], [ "B", "copper_ingot" ] ] } ================================================ FILE: recipes/craft3x/bronze_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "bronze_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "bronze_ingot" ] ] } ================================================ FILE: recipes/craft3x/bronze_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "bronze_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "bronze_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/bronze_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "bronze_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "bronze_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/brown_mushroom.json ================================================ { "config": "Craft3x", "results": [ { "id": "brown_mushroom", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "large_brown_mushroom" ] ] } ================================================ FILE: recipes/craft3x/brown_mushroom_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "brown_mushroom", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "brown_mushroom_block" ] ] } ================================================ FILE: recipes/craft3x/bucket_empty.json ================================================ { "config": "Craft3x", "results": [ { "id": "bucket_empty", "stackSize": 3 } ], "pattern": [ "AOA", "OAO", "OOO" ], "elements": [ [ "A", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/cabinet_acacia.json ================================================ { "config": "Craft3x", "results": [ { "id": "cabinet_acacia", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "acacia_plank" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/cabinet_birch.json ================================================ { "config": "Craft3x", "results": [ { "id": "cabinet_birch", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "birch_plank" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/cabinet_dark_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "cabinet_dark_oak", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "dark_oak_plank" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/cabinet_jungle.json ================================================ { "config": "Craft3x", "results": [ { "id": "cabinet_jungle", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "jungle_plank" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/cabinet_nether.json ================================================ { "config": "Craft3x", "results": [ { "id": "cabinet_nether", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "nether_brick" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/cabinet_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "cabinet_oak", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "oak_plank" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/cabinet_palm.json ================================================ { "config": "Craft3x", "results": [ { "id": "cabinet_palm", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "palm_plank" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/cabinet_spruce.json ================================================ { "config": "Craft3x", "results": [ { "id": "cabinet_spruce", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "spruce_plank" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/cabinet_tainted.json ================================================ { "config": "Craft3x", "results": [ { "id": "cabinet_tainted", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "tainted_plank" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/cabinet_volcano.json ================================================ { "config": "Craft3x", "results": [ { "id": "cabinet_volcano", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "volcano_plank" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/cake.json ================================================ { "config": "Craft3x", "results": [ { "id": "cake", "stackSize": 1 }, { "id": "bucket_empty", "stackSize": 3 } ], "pattern": [ "BBB", "CAC", "DDD" ], "elements": [ [ "A", "egg" ], [ "B", "bucket_milk" ], [ "C", "suger" ], [ "D", "wheat" ] ] } ================================================ FILE: recipes/craft3x/cake_piece.json ================================================ { "config": "Craft3x", "results": [ { "id": "cake_piece", "stackSize": 8 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "cake" ] ] } ================================================ FILE: recipes/craft3x/campfire.json ================================================ { "config": "Craft3x", "results": [ { "id": "campfire", "stackSize": 1 } ], "pattern": [ "OBO", "BAB", "CCC" ], "elements": [ [ "A", "coal" ], [ "B", "stick" ], [ "C", "OD_WOOD" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/campfire_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "campfire", "stackSize": 1 } ], "pattern": [ "OBO", "BAB", "CCC" ], "elements": [ [ "A", "charcoal" ], [ "B", "stick" ] ], "group3": "OD_WOOD", "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/campfire_3.json ================================================ { "config": "Craft3x", "results": [ { "id": "campfire", "stackSize": 1 } ], "pattern": [ "OBO", "BAB", "CCC" ], "elements": [ [ "A", "coal" ], [ "B", "stick" ] ], "group3": "OD_WOOD_STRIPPED", "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/campfire_4.json ================================================ { "config": "Craft3x", "results": [ { "id": "campfire", "stackSize": 1 } ], "pattern": [ "OBO", "BAB", "CCC" ], "elements": [ [ "A", "charcoal" ], [ "B", "stick" ] ], "group3": "OD_WOOD_STRIPPED", "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/candle.json ================================================ { "config": "Craft3x", "results": [ { "id": "candle", "stackSize": 1 } ], "pattern": [ "AOO", "BOO", "OOO" ], "elements": [ [ "A", "torch" ], [ "B", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/candle_holder.json ================================================ { "config": "Craft3x", "results": [ { "id": "candle_holder", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "BBB" ], "elements": [ [ "A", "candle" ], [ "B", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/cauldron.json ================================================ { "config": "Craft3x", "results": [ { "id": "cauldron", "stackSize": 1 } ], "pattern": [ "AOA", "AOA", "AAA" ], "elements": [ [ "A", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/chair_acacia.json ================================================ { "config": "Craft3x", "results": [ { "id": "chair_acacia", "stackSize": 2 } ], "pattern": [ "AOO", "AAA", "AOA" ], "elements": [ [ "A", "acacia_plank" ] ] } ================================================ FILE: recipes/craft3x/chair_birch.json ================================================ { "config": "Craft3x", "results": [ { "id": "chair_birch", "stackSize": 2 } ], "pattern": [ "AOO", "AAA", "AOA" ], "elements": [ [ "A", "birch_plank" ] ] } ================================================ FILE: recipes/craft3x/chair_dark_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "chair_dark_oak", "stackSize": 2 } ], "pattern": [ "AOO", "AAA", "AOA" ], "elements": [ [ "A", "dark_oak_plank" ] ] } ================================================ FILE: recipes/craft3x/chair_jungle.json ================================================ { "config": "Craft3x", "results": [ { "id": "chair_jungle", "stackSize": 2 } ], "pattern": [ "AOO", "AAA", "AOA" ], "elements": [ [ "A", "jungle_plank" ] ] } ================================================ FILE: recipes/craft3x/chair_nether.json ================================================ { "config": "Craft3x", "results": [ { "id": "chair_nether", "stackSize": 2 } ], "pattern": [ "AOO", "AAA", "AOA" ], "elements": [ [ "A", "nether_brick" ] ] } ================================================ FILE: recipes/craft3x/chair_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "chair_oak", "stackSize": 2 } ], "pattern": [ "AOO", "AAA", "AOA" ], "elements": [ [ "A", "oak_plank" ] ] } ================================================ FILE: recipes/craft3x/chair_palm.json ================================================ { "config": "Craft3x", "results": [ { "id": "chair_palm", "stackSize": 2 } ], "pattern": [ "AOO", "AAA", "AOA" ], "elements": [ [ "A", "palm_plank" ] ] } ================================================ FILE: recipes/craft3x/chair_spruce.json ================================================ { "config": "Craft3x", "results": [ { "id": "chair_spruce", "stackSize": 2 } ], "pattern": [ "AOO", "AAA", "AOA" ], "elements": [ [ "A", "spruce_plank" ] ] } ================================================ FILE: recipes/craft3x/chair_tainted.json ================================================ { "config": "Craft3x", "results": [ { "id": "chair_tainted", "stackSize": 2 } ], "pattern": [ "AOO", "AAA", "AOA" ], "elements": [ [ "A", "tainted_plank" ] ] } ================================================ FILE: recipes/craft3x/chair_volcano.json ================================================ { "config": "Craft3x", "results": [ { "id": "chair_volcano", "stackSize": 2 } ], "pattern": [ "AOO", "AAA", "AOA" ], "elements": [ [ "A", "volcano_plank" ] ] } ================================================ FILE: recipes/craft3x/chandeliers.json ================================================ { "config": "Craft3x", "results": [ { "id": "chandeliers", "stackSize": 1 } ], "pattern": [ "OCO", "BAB", "CCC" ], "elements": [ [ "A", "diamond" ], [ "B", "glowstone_dust" ], [ "C", "glass" ] ] } ================================================ FILE: recipes/craft3x/chest.json ================================================ { "config": "Craft3x", "results": [ { "id": "chest", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AAA" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ] ] } ================================================ FILE: recipes/craft3x/clay.json ================================================ { "config": "Craft3x", "results": [ { "id": "clay", "stackSize": 4 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "clay_block" ] ] } ================================================ FILE: recipes/craft3x/clay_block.json ================================================ { "config": "Craft3x", "results": [ { "id": "clay_block", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "clay" ] ] } ================================================ FILE: recipes/craft3x/coal.json ================================================ { "config": "Craft3x", "results": [ { "id": "coal", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "block_coal" ] ] } ================================================ FILE: recipes/craft3x/coarse_dirt.json ================================================ { "config": "Craft3x", "results": [ { "id": "coarse_dirt", "stackSize": 4 } ], "pattern": [ "ABO", "BAO", "OOO" ], "elements": [ [ "A", "dirt" ], [ "B", "gravel" ] ] } ================================================ FILE: recipes/craft3x/cobblestone_fence.json ================================================ { "config": "Craft3x", "results": [ { "id": "cobblestone_fence", "stackSize": 6 } ], "pattern": [ "AAA", "AAA", "OOO" ], "elements": [ [ "A", "cobblestone" ] ] } ================================================ FILE: recipes/craft3x/cobblestone_mossy.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "cobblestone_mossy", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "cobblestone" ], [ "B", "vine" ] ] } ================================================ FILE: recipes/craft3x/cobweb.json ================================================ { "config": "Craft3x", "results": [ { "id": "cobweb", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "string" ] ] } ================================================ FILE: recipes/craft3x/cookie.json ================================================ { "config": "Craft3x", "results": [ { "id": "cookie", "stackSize": 8 } ], "pattern": [ "ABA", "OOO", "OOO" ], "elements": [ [ "A", "wheat" ], [ "B", "cocoa_bean" ] ] } ================================================ FILE: recipes/craft3x/copper_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "copper_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "copper_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/copper_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "copper_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "copper_ingot" ] ] } ================================================ FILE: recipes/craft3x/copper_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "copper_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "copper_ingot" ] ] } ================================================ FILE: recipes/craft3x/copper_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "copper_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "copper_ingot" ] ] } ================================================ FILE: recipes/craft3x/copper_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "copper_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "copper_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/copper_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "copper_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "copper_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/crafting_table.json ================================================ { "config": "Craft3x", "results": [ { "id": "crafting_table", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ] ] } ================================================ FILE: recipes/craft3x/cross_bow.json ================================================ { "config": "Craft3x", "results": [ { "id": "cross_bow", "stackSize": 1 } ], "pattern": [ "BAB", "CAC", "OBO" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "stick" ], [ "C", "string" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/dark_oak_plank.json ================================================ { "config": "Craft3x", "results": [ { "id": "dark_oak_plank", "stackSize": 4 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "wood_dark_oak" ] ] } ================================================ FILE: recipes/craft3x/dark_shadow_ingot.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dark_shadow_ingot", "stackSize": 1 } ], "pattern": [ "ABC", "OOO", "OOO" ], "elements": [ [ "A", "dark_shadow_part" ], [ "B", "gold_ingot" ], [ "C", "silver_ingot" ] ] } ================================================ FILE: recipes/craft3x/daylight_sensor.json ================================================ { "config": "Craft3x", "results": [ { "id": "daylight_sensor", "stackSize": 1 } ], "pattern": [ "AAA", "BBB", "CCC" ], "elements": [ [ "A", "glass" ], [ "B", "quartz" ] ], "group3": "OD_WOODEN_PLANK" } ================================================ FILE: recipes/craft3x/daylight_sensor_inverted.json ================================================ { "config": "Craft3x", "results": [ { "id": "daylight_sensor_inverted", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "daylight_sensor" ] ] } ================================================ FILE: recipes/craft3x/diamond.json ================================================ { "config": "Craft3x", "results": [ { "id": "diamond", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "block_diamond" ] ] } ================================================ FILE: recipes/craft3x/diamond_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "diamond_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "diamond" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/diamond_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "diamond_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "diamond" ] ] } ================================================ FILE: recipes/craft3x/diamond_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "diamond_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "diamond" ] ] } ================================================ FILE: recipes/craft3x/diamond_ingot.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "diamond_ingot", "stackSize": 1 } ], "pattern": [ "ABC", "DEO", "OOO" ], "elements": [ [ "A", "diamond" ], [ "B", "blue_crystal" ], [ "C", "red_crystal" ], [ "D", "yellow_crystal" ], [ "E", "white_crystal" ] ] } ================================================ FILE: recipes/craft3x/diamond_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "diamond_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "diamond" ] ] } ================================================ FILE: recipes/craft3x/diamond_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "diamond_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "diamond" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/diamond_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "diamond_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "diamond" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/diorite.json ================================================ { "config": "Craft3x", "results": [ { "id": "diorite", "stackSize": 2 } ], "pattern": [ "ABO", "BAO", "OOO" ], "elements": [ [ "A", "cobblestone" ], [ "B", "quartz" ] ] } ================================================ FILE: recipes/craft3x/diorite_polished.json ================================================ { "config": "Craft3x", "results": [ { "id": "diorite_polished", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "diorite" ] ] } ================================================ FILE: recipes/craft3x/dirt.json ================================================ { "config": "Craft3x", "results": [ { "id": "dirt", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "flesh_dirt" ], [ "B", "bone_meal" ] ] } ================================================ FILE: recipes/craft3x/door_nether.json ================================================ { "config": "Craft3x", "results": [ { "id": "door_nether", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "nether_brick" ] ] } ================================================ FILE: recipes/craft3x/dried_kelp.json ================================================ { "config": "Craft3x", "results": [ { "id": "dried_kelp", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "dried_kelp_block" ] ] } ================================================ FILE: recipes/craft3x/dried_kelp_block.json ================================================ { "config": "Craft3x", "results": [ { "id": "dried_kelp_block", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "dried_kelp" ] ] } ================================================ FILE: recipes/craft3x/dungeon_eater.json ================================================ { "config": "Craft3x", "results": [ { "id": "dungeon_eater", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "evil_part" ], [ "B", "blood" ] ] } ================================================ FILE: recipes/craft3x/dye_black.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_black", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "ink_sac" ] ] } ================================================ FILE: recipes/craft3x/dye_blue.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_blue", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "lapis_lazuli" ] ] } ================================================ FILE: recipes/craft3x/dye_brown.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_brown", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "cocoa_bean" ] ] } ================================================ FILE: recipes/craft3x/dye_cyan.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_cyan", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_blue" ], [ "B", "dye_green" ] ] } ================================================ FILE: recipes/craft3x/dye_cyan_2.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_cyan", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "lapis_lazuli" ], [ "B", "dye_green" ] ] } ================================================ FILE: recipes/craft3x/dye_gray.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_gray", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_black" ], [ "B", "dye_white" ] ] } ================================================ FILE: recipes/craft3x/dye_light_blue.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_light_blue", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "blue_orchid" ] ] } ================================================ FILE: recipes/craft3x/dye_light_blue_2.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_light_blue", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_blue" ], [ "B", "dye_white" ] ] } ================================================ FILE: recipes/craft3x/dye_light_blue_3.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_light_blue", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "lapis_lazuli" ], [ "B", "dye_white" ] ] } ================================================ FILE: recipes/craft3x/dye_light_gray.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_light_gray", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "azure_bluet" ] ] } ================================================ FILE: recipes/craft3x/dye_light_gray_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_light_gray", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "white_tulip" ] ] } ================================================ FILE: recipes/craft3x/dye_light_gray_3.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_light_gray", "stackSize": 3 } ], "pattern": [ "ABB", "OOO", "OOO" ], "elements": [ [ "A", "dye_black" ], [ "B", "dye_white" ] ] } ================================================ FILE: recipes/craft3x/dye_light_gray_4.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_light_gray", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_gray" ], [ "B", "dye_white" ] ] } ================================================ FILE: recipes/craft3x/dye_lime.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_lime", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_green" ], [ "B", "dye_white" ] ] } ================================================ FILE: recipes/craft3x/dye_lime_2.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_lime", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_green" ], [ "B", "bone_meal" ] ] } ================================================ FILE: recipes/craft3x/dye_magenta.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_magenta", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "allium" ] ] } ================================================ FILE: recipes/craft3x/dye_magenta_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_magenta", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "lilac" ] ] } ================================================ FILE: recipes/craft3x/dye_magenta_3.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_magenta", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_purple" ], [ "B", "dye_pink" ] ] } ================================================ FILE: recipes/craft3x/dye_magenta_4.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_magenta", "stackSize": 3 } ], "pattern": [ "ABC", "OOO", "OOO" ], "elements": [ [ "A", "dye_blue" ], [ "B", "dye_red" ], [ "C", "dye_pink" ] ] } ================================================ FILE: recipes/craft3x/dye_magenta_5.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_magenta", "stackSize": 4 } ], "pattern": [ "ABB", "COO", "OOO" ], "elements": [ [ "A", "dye_blue" ], [ "B", "dye_red" ], [ "C", "dye_white" ] ] } ================================================ FILE: recipes/craft3x/dye_orange.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_orange", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "orange_tulip" ] ] } ================================================ FILE: recipes/craft3x/dye_orange_2.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_orange", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_red" ], [ "B", "dye_yellow" ] ] } ================================================ FILE: recipes/craft3x/dye_pink.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_pink", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "pink_tulip" ] ] } ================================================ FILE: recipes/craft3x/dye_pink_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_pink", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "peony" ] ] } ================================================ FILE: recipes/craft3x/dye_pink_3.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_pink", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_red" ], [ "B", "dye_white" ] ] } ================================================ FILE: recipes/craft3x/dye_pink_4.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_pink", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_red" ], [ "B", "bone_meal" ] ] } ================================================ FILE: recipes/craft3x/dye_purple.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_purple", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "dye_blue" ], [ "B", "dye_red" ] ] } ================================================ FILE: recipes/craft3x/dye_purple_2.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "dye_purple", "stackSize": 2 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "lapis_lazuli" ], [ "B", "dye_red" ] ] } ================================================ FILE: recipes/craft3x/dye_red.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_red", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "poppy" ] ] } ================================================ FILE: recipes/craft3x/dye_red_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_red", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "red_tulip" ] ] } ================================================ FILE: recipes/craft3x/dye_red_3.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_red", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "rose_bush" ] ] } ================================================ FILE: recipes/craft3x/dye_white.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_white", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "bone_meal" ] ] } ================================================ FILE: recipes/craft3x/dye_yellow.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_yellow", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "dandelion" ] ] } ================================================ FILE: recipes/craft3x/dye_yellow_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "dye_yellow", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "sunflower" ] ] } ================================================ FILE: recipes/craft3x/emerald.json ================================================ { "config": "Craft3x", "results": [ { "id": "emerald", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "block_emerald" ] ] } ================================================ FILE: recipes/craft3x/enchantment_table.json ================================================ { "config": "Craft3x", "results": [ { "id": "enchantment_table", "stackSize": 1 } ], "pattern": [ "OAO", "BCB", "CCC" ], "elements": [ [ "A", "book" ], [ "B", "diamond" ], [ "C", "obsidian" ] ] } ================================================ FILE: recipes/craft3x/end_rod.json ================================================ { "config": "Craft3x", "results": [ { "id": "end_rod", "stackSize": 4 } ], "pattern": [ "AOO", "BOO", "OOO" ], "elements": [ [ "A", "blaze_rod" ], [ "B", "popped_chorus_fruits" ] ] } ================================================ FILE: recipes/craft3x/end_stone_brick.json ================================================ { "config": "Craft3x", "results": [ { "id": "end_stone_brick", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "end_stone" ] ] } ================================================ FILE: recipes/craft3x/ender_chest.json ================================================ { "config": "Craft3x", "results": [ { "id": "ender_chest", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "obsidian" ], [ "B", "ender_eye" ] ] } ================================================ FILE: recipes/craft3x/ender_eye.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "ender_eye", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "blaze_powder" ], [ "B", "ender_pearl" ] ] } ================================================ FILE: recipes/craft3x/ender_mirror.json ================================================ { "config": "Craft3x", "results": [ { "id": "ender_mirror", "stackSize": 1 } ], "pattern": [ "OAO", "ABA", "OAO" ], "elements": [ [ "A", "glass" ], [ "B", "ender_pearl" ] ] } ================================================ FILE: recipes/craft3x/farmland.json ================================================ { "config": "Craft3x", "results": [ { "id": "farmland", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "flesh_gut" ], [ "B", "bone_meal" ] ] } ================================================ FILE: recipes/craft3x/farmland_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "farmland", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "tainted_dirt" ], [ "B", "bone_meal" ] ] } ================================================ FILE: recipes/craft3x/fence_acacia.json ================================================ { "config": "Craft3x", "results": [ { "id": "fence_acacia", "stackSize": 3 } ], "pattern": [ "ABA", "ABA", "OOO" ], "elements": [ [ "A", "acacia_plank" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/fence_birch.json ================================================ { "config": "Craft3x", "results": [ { "id": "fence_birch", "stackSize": 3 } ], "pattern": [ "ABA", "ABA", "OOO" ], "elements": [ [ "A", "birch_plank" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/fence_dark_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "fence_dark_oak", "stackSize": 3 } ], "pattern": [ "ABA", "ABA", "OOO" ], "elements": [ [ "A", "dark_oak_plank" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/fence_jungle.json ================================================ { "config": "Craft3x", "results": [ { "id": "fence_jungle", "stackSize": 3 } ], "pattern": [ "ABA", "ABA", "OOO" ], "elements": [ [ "A", "jungle_plank" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/fence_nether.json ================================================ { "config": "Craft3x", "results": [ { "id": "fence_nether", "stackSize": 6 } ], "pattern": [ "AAA", "AAA", "OOO" ], "elements": [ [ "A", "nether_brick_block" ] ] } ================================================ FILE: recipes/craft3x/fence_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "fence_oak", "stackSize": 3 } ], "pattern": [ "ABA", "ABA", "OOO" ], "elements": [ [ "A", "oak_plank" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/fence_palm.json ================================================ { "config": "Craft3x", "results": [ { "id": "fence_palm", "stackSize": 3 } ], "pattern": [ "ABA", "ABA", "OOO" ], "elements": [ [ "A", "palm_plank" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/fence_spruce.json ================================================ { "config": "Craft3x", "results": [ { "id": "fence_spruce", "stackSize": 3 } ], "pattern": [ "ABA", "ABA", "OOO" ], "elements": [ [ "A", "spruce_plank" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/fence_tainted.json ================================================ { "config": "Craft3x", "results": [ { "id": "fence_tainted", "stackSize": 3 } ], "pattern": [ "ABA", "ABA", "OOO" ], "elements": [ [ "A", "tainted_plank" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/fence_volcano.json ================================================ { "config": "Craft3x", "results": [ { "id": "fence_volcano", "stackSize": 3 } ], "pattern": [ "ABA", "ABA", "OOO" ], "elements": [ [ "A", "volcano_plank" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/fermented_spider_eye.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "fermented_spider_eye", "stackSize": 1 } ], "pattern": [ "ABC", "OOO", "OOO" ], "elements": [ [ "A", "spider_eye" ], [ "B", "brown_mushroom" ], [ "C", "suger" ] ] } ================================================ FILE: recipes/craft3x/fire_boomerang.json ================================================ { "config": "Craft3x", "results": [ { "id": "fire_boomerang", "stackSize": 1 } ], "pattern": [ "OAB", "AOO", "OAB" ], "elements": [ [ "A", "copper_ingot" ], [ "B", "blaze_rod" ] ] } ================================================ FILE: recipes/craft3x/fire_boomerang_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "fire_boomerang", "stackSize": 1 } ], "pattern": [ "OAB", "AOO", "OAB" ], "elements": [ [ "A", "tin_ingot" ], [ "B", "blaze_rod" ] ] } ================================================ FILE: recipes/craft3x/fire_bullet.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "fire_bullet", "stackSize": 16 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "fire_charge" ], [ "B", "copper_ingot" ] ] } ================================================ FILE: recipes/craft3x/fire_bullet_2.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "fire_bullet", "stackSize": 16 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "fire_charge" ], [ "B", "tin_ingot" ] ] } ================================================ FILE: recipes/craft3x/fire_charge.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "fire_charge", "stackSize": 3 } ], "pattern": [ "ABC", "OOO", "OOO" ], "elements": [ [ "A", "blaze_powder" ], [ "B", "coal" ], [ "C", "gunpowder" ] ] } ================================================ FILE: recipes/craft3x/fire_charge_2.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "fire_charge", "stackSize": 3 } ], "pattern": [ "ABC", "OOO", "OOO" ], "elements": [ [ "A", "blaze_powder" ], [ "B", "charcoal" ], [ "C", "gunpowder" ] ] } ================================================ FILE: recipes/craft3x/fire_lamp.json ================================================ { "config": "Craft3x", "results": [ { "id": "fire_lamp", "stackSize": 1 } ], "pattern": [ "OAO", "BAB", "CCC" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "torch" ] ], "group3": "OD_WOODEN_PLANK" } ================================================ FILE: recipes/craft3x/flesh_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "flesh_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "flesh_ingot" ] ] } ================================================ FILE: recipes/craft3x/flesh_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "flesh_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "flesh_ingot" ] ] } ================================================ FILE: recipes/craft3x/flesh_ingot.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "flesh_ingot", "stackSize": 1 } ], "pattern": [ "ABC", "COO", "OOO" ], "elements": [ [ "A", "gold_ingot" ], [ "B", "silver_ingot" ], [ "B", "flesh_part" ] ] } ================================================ FILE: recipes/craft3x/flesh_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "flesh_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "flesh_ingot" ] ] } ================================================ FILE: recipes/craft3x/flesh_machine_part.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "flesh_machine_part", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "machine_part" ], [ "B", "magic_cell" ] ] } ================================================ FILE: recipes/craft3x/flower_pot.json ================================================ { "config": "Craft3x", "results": [ { "id": "flower_pot", "stackSize": 1 } ], "pattern": [ "AOA", "OAO", "OOO" ], "elements": [ [ "A", "red_brick" ] ] } ================================================ FILE: recipes/craft3x/flower_pot_large.json ================================================ { "config": "Craft3x", "results": [ { "id": "flower_pot_large", "stackSize": 1 } ], "pattern": [ "AOA", "AOA", "OAO" ], "elements": [ [ "A", "red_brick" ] ] } ================================================ FILE: recipes/craft3x/furnace.json ================================================ { "config": "Craft3x", "results": [ { "id": "furnace", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AAA" ], "elements": [ [ "A", "cobblestone" ] ] } ================================================ FILE: recipes/craft3x/ghost.json ================================================ { "config": "Craft3x", "results": [ { "id": "ghost", "stackSize": 1 } ], "pattern": [ "AAA", "BAB", "AAA" ], "elements": [ [ "A", "ghost_crystal"], [ "B", "ghost_element" ] ] } ================================================ FILE: recipes/craft3x/glass_bottle.json ================================================ { "config": "Craft3x", "results": [ { "id": "glass_bottle", "stackSize": 6 } ], "pattern": [ "AOA", "OAO", "OOO" ], "elements": [ [ "A", "glass" ] ] } ================================================ FILE: recipes/craft3x/glistering_melon_slice.json ================================================ { "config": "Craft3x", "results": [ { "id": "glistering_melon_slice", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "gold_nugget" ], [ "B", "melon_slice" ] ] } ================================================ FILE: recipes/craft3x/glow_ball.json ================================================ { "config": "Craft3x", "results": [ { "id": "glow_ball", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "glowstone_dust" ], [ "B", "cobblestone" ] ] } ================================================ FILE: recipes/craft3x/glow_bomb.json ================================================ { "config": "Craft3x", "results": [ { "id": "glow_bomb", "stackSize": 2 } ], "pattern": [ "OBO", "BAB", "OBO" ], "elements": [ [ "A", "bomb" ], [ "B", "glowstone_dust" ] ] } ================================================ FILE: recipes/craft3x/glowing_mushroom.json ================================================ { "config": "Craft3x", "results": [ { "id": "glowing_mushroom", "stackSize": 1 } ], "pattern": [ "OAO", "ABA", "OAO" ], "elements": [ [ "A", "glowstone_dust" ], [ "B", "red_mushroom" ] ] } ================================================ FILE: recipes/craft3x/glowing_mushroom_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "glowing_mushroom", "stackSize": 1 } ], "pattern": [ "OAO", "ABA", "OAO" ], "elements": [ [ "A", "glowstone_dust" ], [ "B", "brown_mushroom" ] ] } ================================================ FILE: recipes/craft3x/glowstone.json ================================================ { "config": "Craft3x", "results": [ { "id": "glowstone", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "glowstone_dust" ] ] } ================================================ FILE: recipes/craft3x/gold_ingot.json ================================================ { "config": "Craft3x", "results": [ { "id": "gold_ingot", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "block_gold" ] ] } ================================================ FILE: recipes/craft3x/gold_ingot_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "gold_ingot", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "gold_nugget" ] ] } ================================================ FILE: recipes/craft3x/gold_nugget.json ================================================ { "config": "Craft3x", "results": [ { "id": "gold_nugget", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/golden_apple.json ================================================ { "config": "Craft3x", "results": [ { "id": "golden_apple", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "gold_ingot" ], [ "B", "apple" ] ] } ================================================ FILE: recipes/craft3x/golden_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "golden_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "gold_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/golden_carrot.json ================================================ { "config": "Craft3x", "results": [ { "id": "golden_carrot", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "gold_nugget" ], [ "B", "carrot" ] ] } ================================================ FILE: recipes/craft3x/golden_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "golden_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/golden_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "golden_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/golden_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "golden_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/golden_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "golden_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "gold_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/golden_pressure_plate.json ================================================ { "config": "Craft3x", "results": [ { "id": "golden_pressure_plate", "stackSize": 1 } ], "pattern": [ "AAO", "OOO", "OOO" ], "elements": [ [ "A", "gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/golden_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "golden_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "gold_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/granite.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "granite", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "diorite" ], [ "B", "quartz" ] ] } ================================================ FILE: recipes/craft3x/granite_polished.json ================================================ { "config": "Craft3x", "results": [ { "id": "granite_polished", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "granite" ] ] } ================================================ FILE: recipes/craft3x/grass_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "grass_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "grass" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/grass_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "grass_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "grass" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/grass_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "grass_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "grass" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/green_torch.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "green_torch", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "torch" ], [ "B", "dye_green" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/green_wire.json ================================================ { "config": "Craft3x", "results": [ { "id": "green_wire", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "red_wire" ], [ "B", "dye_green" ] ] } ================================================ FILE: recipes/craft3x/grenade.json ================================================ { "config": "Craft3x", "results": [ { "id": "grenade", "stackSize": 3 } ], "pattern": [ "OBO", "BAB", "OBO" ], "elements": [ [ "A", "bomb" ], [ "B", "sand" ] ] } ================================================ FILE: recipes/craft3x/grenade_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "grenade", "stackSize": 3 } ], "pattern": [ "OBO", "BAB", "OBO" ], "elements": [ [ "A", "bomb" ], [ "B", "red_sand" ] ] } ================================================ FILE: recipes/craft3x/hay_bale.json ================================================ { "config": "Craft3x", "results": [ { "id": "hay_bale", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "wheat" ] ] } ================================================ FILE: recipes/craft3x/ice_arrow.json ================================================ { "config": "Craft3x", "results": [ { "id": "ice_arrow", "stackSize": 4 } ], "pattern": [ "OAO", "ABA", "OAO" ], "elements": [ [ "A", "wooden_arrow" ], [ "B", "ice_packed" ] ] } ================================================ FILE: recipes/craft3x/ice_bow.json ================================================ { "config": "Craft3x", "results": [ { "id": "ice_bow", "stackSize": 1 } ], "pattern": [ "BDC", "AOC", "BDC" ], "elements": [ [ "A", "diamond" ], [ "B", "blue_ice" ], [ "C", "string" ], [ "D", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/ice_brick.json ================================================ { "config": "Craft3x", "results": [ { "id": "ice_brick", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "ice_cobblestone" ] ] } ================================================ FILE: recipes/craft3x/ice_element_ball.json ================================================ { "config": "Craft3x", "results": [ { "id": "ice_element_ball", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "ice_element" ] ] } ================================================ FILE: recipes/craft3x/ice_packed.json ================================================ { "config": "Craft3x", "results": [ { "id": "ice_packed", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "ice" ] ] } ================================================ FILE: recipes/craft3x/ice_staff.json ================================================ { "config": "Craft3x", "results": [ { "id": "ice_staff", "stackSize": 1 } ], "pattern": [ "OAB", "OCA", "COO" ], "elements": [ [ "A", "blue_ice" ], [ "B", "diamond" ], [ "C", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/iron_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/iron_bar.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_bar", "stackSize": 32 } ], "pattern": [ "AAA", "AAA", "OOO" ], "elements": [ [ "A", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/iron_bullet.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "iron_bullet", "stackSize": 16 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "fire_charge" ], [ "B", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/iron_bullet_2.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "iron_bullet", "stackSize": 32 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "fire_charge" ], [ "B", "steel_ingot" ] ] } ================================================ FILE: recipes/craft3x/iron_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/iron_door.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_door", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/iron_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/iron_ingot.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_ingot", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "block_iron" ] ] } ================================================ FILE: recipes/craft3x/iron_ingot_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_ingot", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "iron_nugget" ] ] } ================================================ FILE: recipes/craft3x/iron_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/iron_nugget.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_nugget", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/iron_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/iron_pressure_plate.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_pressure_plate", "stackSize": 1 } ], "pattern": [ "AAO", "OOO", "OOO" ], "elements": [ [ "A", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/iron_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "iron_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/jack_o_lantern.json ================================================ { "config": "Craft3x", "results": [ { "id": "jack_o_lantern", "stackSize": 1 } ], "pattern": [ "AOO", "BOO", "OOO" ], "elements": [ [ "A", "pumpkin_carved" ], [ "B", "torch" ] ] } ================================================ FILE: recipes/craft3x/jukebox.json ================================================ { "config": "Craft3x", "results": [ { "id": "jukebox", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "diamond" ] ] } ================================================ FILE: recipes/craft3x/jungle_plank.json ================================================ { "config": "Craft3x", "results": [ { "id": "jungle_plank", "stackSize": 4 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "wood_jungle" ] ] } ================================================ FILE: recipes/craft3x/knight_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "knight_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "knight_ingot" ] ] } ================================================ FILE: recipes/craft3x/knight_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "knight_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "knight_ingot" ] ] } ================================================ FILE: recipes/craft3x/knight_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "knight_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "knight_ingot" ] ] } ================================================ FILE: recipes/craft3x/lantern.json ================================================ { "config": "Craft3x", "results": [ { "id": "lantern", "stackSize": 1 } ], "pattern": [ "BBB", "BAB", "BBB" ], "elements": [ [ "A", "torch" ], [ "B", "iron_nugget" ] ] } ================================================ FILE: recipes/craft3x/lapis_lazuli.json ================================================ { "config": "Craft3x", "results": [ { "id": "lapis_lazuli", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "block_lapis" ] ] } ================================================ FILE: recipes/craft3x/lava_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "lava_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "magma_gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/lava_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "lava_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "magma_gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/lava_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "lava_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "magma_gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/lead_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "lead_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "lead_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/lead_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "lead_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "lead_ingot" ] ] } ================================================ FILE: recipes/craft3x/lead_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "lead_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "lead_ingot" ] ] } ================================================ FILE: recipes/craft3x/lead_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "lead_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "lead_ingot" ] ] } ================================================ FILE: recipes/craft3x/lead_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "lead_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "lead_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/lead_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "lead_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "lead_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/leather.json ================================================ { "config": "Craft3x", "results": [ { "id": "leather", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "rabbit_hide" ] ] } ================================================ FILE: recipes/craft3x/leather_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "leather_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "leather" ] ] } ================================================ FILE: recipes/craft3x/leather_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "leather_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "leather" ] ] } ================================================ FILE: recipes/craft3x/leather_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "leather_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "leather" ] ] } ================================================ FILE: recipes/craft3x/lever.json ================================================ { "config": "Craft3x", "results": [ { "id": "lever", "stackSize": 1 } ], "pattern": [ "AOO", "BOO", "OOO" ], "elements": [ [ "A", "stick" ], [ "B", "cobblestone" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/lighter.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "lighter", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "flint" ] ] } ================================================ FILE: recipes/craft3x/lighting_arrow.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "lighting_arrow", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_arrow" ], [ "B", "glowstone_dust" ] ] } ================================================ FILE: recipes/craft3x/lighting_bow.json ================================================ { "config": "Craft3x", "results": [ { "id": "lighting_bow", "stackSize": 1 } ], "pattern": [ "BDC", "AOC", "BDC" ], "elements": [ [ "A", "gold_ingot" ], [ "B", "glowstone_dust" ], [ "C", "string" ], [ "D", "blaze_rod" ] ] } ================================================ FILE: recipes/craft3x/lighting_staff.json ================================================ { "config": "Craft3x", "results": [ { "id": "lighting_staff", "stackSize": 1 } ], "pattern": [ "OAB", "OCA", "COO" ], "elements": [ [ "A", "glowstone_dust" ], [ "B", "silver_ingot" ], [ "C", "gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/machine_part.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "machine_part", "stackSize": 2 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "steel_ingot" ] ] } ================================================ FILE: recipes/craft3x/magic_cell_group.json ================================================ { "config": "Craft3x", "results": [ { "id": "magic_cell_group", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "magic_cell" ] ] } ================================================ FILE: recipes/craft3x/magic_gold_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "magic_gold_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "red_gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/magic_gold_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "magic_gold_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "red_gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/magic_gold_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "magic_gold_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "red_gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/magic_silver_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "magic_silver_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "magic_silver_ingot" ] ] } ================================================ FILE: recipes/craft3x/magic_silver_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "magic_silver_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "magic_silver_ingot" ] ] } ================================================ FILE: recipes/craft3x/magic_silver_ingot.json ================================================ { "config": "Craft3x", "results": [ { "id": "magic_silver_ingot", "stackSize": 1 } ], "pattern": [ "OBO", "BAB", "OBO" ], "elements": [ [ "A", "silver_ingot" ], [ "B", "magic_cell" ] ] } ================================================ FILE: recipes/craft3x/magic_silver_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "magic_silver_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "magic_silver_ingot" ] ] } ================================================ FILE: recipes/craft3x/magma_block.json ================================================ { "config": "Craft3x", "results": [ { "id": "magma_block", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "magma_cream" ] ] } ================================================ FILE: recipes/craft3x/magma_cream.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "magma_cream", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "blaze_powder" ], [ "B", "slimeball" ] ] } ================================================ FILE: recipes/craft3x/magma_gold_ingot.json ================================================ { "config": "Craft3x", "results": [ { "id": "magma_gold_ingot", "stackSize": 1 } ], "pattern": [ "OBO", "BAB", "OBO" ], "elements": [ [ "A", "gold_ingot" ], [ "B", "magma_cream" ] ] } ================================================ FILE: recipes/craft3x/melon_seed.json ================================================ { "config": "Craft3x", "results": [ { "id": "melon_seed", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "melon_slice" ] ] } ================================================ FILE: recipes/craft3x/mossy_cobblestone_fence.json ================================================ { "config": "Craft3x", "results": [ { "id": "mossy_cobblestone_fence", "stackSize": 6 } ], "pattern": [ "AAA", "AAA", "OOO" ], "elements": [ [ "A", "cobblestone_mossy" ] ] } ================================================ FILE: recipes/craft3x/mushroom_stew.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "mushroom_stew", "stackSize": 1 } ], "pattern": [ "ABC", "OOO", "OOO" ], "elements": [ [ "A", "bowl" ], [ "B", "brown_mushroom" ], [ "C", "red_mushroom" ] ] } ================================================ FILE: recipes/craft3x/nether_brick_block.json ================================================ { "config": "Craft3x", "results": [ { "id": "nether_brick_block", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "nether_brick" ] ] } ================================================ FILE: recipes/craft3x/nether_chest.json ================================================ { "config": "Craft3x", "results": [ { "id": "nether_chest", "stackSize": 1 } ], "pattern": [ "OAO", "ABA", "OAO" ], "elements": [ [ "A", "nether_brick" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/nether_lamp.json ================================================ { "config": "Craft3x", "results": [ { "id": "nether_lamp", "stackSize": 1 } ], "pattern": [ "OAO", "BAB", "CCC" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "red_torch" ], [ "C", "nether_brick" ] ] } ================================================ FILE: recipes/craft3x/netherite_ingot.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "netherite_ingot", "stackSize": 1 } ], "pattern": [ "AAA", "ABB", "BBO" ], "elements": [ [ "A", "netherite_scrap" ], [ "B", "gold_ingot" ] ] } ================================================ FILE: recipes/craft3x/netherite_ingot_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "netherite_ingot", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "block_netherite" ] ] } ================================================ FILE: recipes/craft3x/oak_plank.json ================================================ { "config": "Craft3x", "results": [ { "id": "oak_plank", "stackSize": 4 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "wood_oak" ] ] } ================================================ FILE: recipes/craft3x/painting_2x2.json ================================================ { "config": "Craft3x", "results": [ { "id": "painting_2x2", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "stick" ], [ "B", "OD_WOOL" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/painting_2x2_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "painting_2x2", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "painting_8x8" ] ] } ================================================ FILE: recipes/craft3x/painting_2x4.json ================================================ { "config": "Craft3x", "results": [ { "id": "painting_2x4", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "painting_4x2" ] ] } ================================================ FILE: recipes/craft3x/painting_4x2.json ================================================ { "config": "Craft3x", "results": [ { "id": "painting_4x2", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "painting_2x2" ] ] } ================================================ FILE: recipes/craft3x/painting_4x4.json ================================================ { "config": "Craft3x", "results": [ { "id": "painting_4x4", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "painting_2x4" ] ] } ================================================ FILE: recipes/craft3x/painting_8x4.json ================================================ { "config": "Craft3x", "results": [ { "id": "painting_8x4", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "painting_4x4" ] ] } ================================================ FILE: recipes/craft3x/painting_8x6.json ================================================ { "config": "Craft3x", "results": [ { "id": "painting_8x6", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "painting_8x4" ] ] } ================================================ FILE: recipes/craft3x/painting_8x8.json ================================================ { "config": "Craft3x", "results": [ { "id": "painting_8x8", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "painting_8x6" ] ] } ================================================ FILE: recipes/craft3x/palm_plank.json ================================================ { "config": "Craft3x", "results": [ { "id": "palm_plank", "stackSize": 5 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "wood_palm" ] ] } ================================================ FILE: recipes/craft3x/paper.json ================================================ { "config": "Craft3x", "results": [ { "id": "paper", "stackSize": 3 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "sugar_cane" ] ] } ================================================ FILE: recipes/craft3x/platform_acacia.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_acacia", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "acacia_plank" ] ] } ================================================ FILE: recipes/craft3x/platform_birch.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_birch", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "birch_plank" ] ] } ================================================ FILE: recipes/craft3x/platform_dark_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_dark_oak", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "dark_oak_plank" ] ] } ================================================ FILE: recipes/craft3x/platform_end_stone.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_end_stone", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "end_stone" ] ] } ================================================ FILE: recipes/craft3x/platform_jungle.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_jungle", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "jungle_plank" ] ] } ================================================ FILE: recipes/craft3x/platform_nether_brick.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_nether_brick", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "nether_brick" ] ] } ================================================ FILE: recipes/craft3x/platform_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_oak", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "oak_plank" ] ] } ================================================ FILE: recipes/craft3x/platform_palm.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_palm", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "palm_plank" ] ] } ================================================ FILE: recipes/craft3x/platform_prismarine.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_prismarine", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "prismarine_brick" ] ] } ================================================ FILE: recipes/craft3x/platform_prismarine_dark.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_prismarine_dark", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "prismarine_dark" ] ] } ================================================ FILE: recipes/craft3x/platform_purpur.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_purpur", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "purpur_block" ] ] } ================================================ FILE: recipes/craft3x/platform_quartz.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_quartz", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "block_quartz" ] ] } ================================================ FILE: recipes/craft3x/platform_red_sand_stone.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_red_sand_stone", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "red_sand_stone" ] ] } ================================================ FILE: recipes/craft3x/platform_sandstone.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_sandstone", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "sandstone" ] ] } ================================================ FILE: recipes/craft3x/platform_spruce.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_spruce", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "spruce_plank" ] ] } ================================================ FILE: recipes/craft3x/platform_stone_brick.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_stone_brick", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "stone_brick" ] ] } ================================================ FILE: recipes/craft3x/platform_tainted.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_tainted", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "tainted_plank" ] ] } ================================================ FILE: recipes/craft3x/platform_volcano.json ================================================ { "config": "Craft3x", "results": [ { "id": "platform_volcano", "stackSize": 6 } ], "pattern": [ "AAA", "OOO", "OOO" ], "elements": [ [ "A", "volcano_plank" ] ] } ================================================ FILE: recipes/craft3x/poison_mushroom.json ================================================ { "config": "Craft3x", "results": [ { "id": "poison_mushroom", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "large_poison_mushroom" ] ] } ================================================ FILE: recipes/craft3x/prismarine.json ================================================ { "config": "Craft3x", "results": [ { "id": "prismarine", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "prismarine_shard" ] ] } ================================================ FILE: recipes/craft3x/prismarine_brick.json ================================================ { "config": "Craft3x", "results": [ { "id": "prismarine_brick", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "prismarine_shard" ] ] } ================================================ FILE: recipes/craft3x/prismarine_dark.json ================================================ { "config": "Craft3x", "results": [ { "id": "prismarine_dark", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "prismarine_shard" ], [ "B", "ink_sac" ] ] } ================================================ FILE: recipes/craft3x/prismarine_dark_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "prismarine_dark", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "prismarine_shard" ], [ "B", "dye_black" ] ] } ================================================ FILE: recipes/craft3x/pumpkin_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "pumpkin_helmet", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "pumpkin_carved" ] ] } ================================================ FILE: recipes/craft3x/pumpkin_pie.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "pumpkin_pie", "stackSize": 2 } ], "pattern": [ "ABC", "OOO", "OOO" ], "elements": [ [ "A", "pumpkin" ], [ "B", "suger" ], [ "C", "egg" ] ] } ================================================ FILE: recipes/craft3x/pumpkin_seed.json ================================================ { "config": "Craft3x", "results": [ { "id": "pumpkin_seed", "stackSize": 4 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "pumpkin" ] ] } ================================================ FILE: recipes/craft3x/purpur_block.json ================================================ { "config": "Craft3x", "results": [ { "id": "purpur_block", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "popped_chorus_fruits" ] ] } ================================================ FILE: recipes/craft3x/quartz.json ================================================ { "config": "Craft3x", "results": [ { "id": "quartz", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "block_quartz" ] ] } ================================================ FILE: recipes/craft3x/red_gold_ingot.json ================================================ { "config": "Craft3x", "results": [ { "id": "red_gold_ingot", "stackSize": 2 } ], "pattern": [ "OBO", "BAB", "OBO" ], "elements": [ [ "A", "gold_ingot" ], [ "B", "red_crystal" ] ] } ================================================ FILE: recipes/craft3x/red_mushroom.json ================================================ { "config": "Craft3x", "results": [ { "id": "red_mushroom", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "large_red_mushroom" ] ] } ================================================ FILE: recipes/craft3x/red_mushroom_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "red_mushroom", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "red_mushroom_block" ] ] } ================================================ FILE: recipes/craft3x/red_nether_brick.json ================================================ { "config": "Craft3x", "results": [ { "id": "red_nether_brick", "stackSize": 1 } ], "pattern": [ "BAO", "ABO", "OOO" ], "elements": [ [ "A", "nether_brick" ], [ "B", "nether_wart" ] ] } ================================================ FILE: recipes/craft3x/red_sand_carved.json ================================================ { "config": "Craft3x", "results": [ { "id": "red_sand_carved", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "red_sand_stone" ] ] } ================================================ FILE: recipes/craft3x/red_sand_stone.json ================================================ { "config": "Craft3x", "results": [ { "id": "red_sand_stone", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "red_sand" ] ] } ================================================ FILE: recipes/craft3x/red_torch.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "red_torch", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "torch" ], [ "B", "dye_red" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/red_wire.json ================================================ { "config": "Craft3x", "results": [ { "id": "red_wire", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "redstone" ], [ "B", "string" ] ] } ================================================ FILE: recipes/craft3x/redstone.json ================================================ { "config": "Craft3x", "results": [ { "id": "redstone", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "block_redstone" ] ] } ================================================ FILE: recipes/craft3x/redstone_lamp.json ================================================ { "config": "Craft3x", "results": [ { "id": "redstone_lamp", "stackSize": 1 } ], "pattern": [ "OAO", "ABA", "OAO" ], "elements": [ [ "A", "redstone" ], [ "B", "glowstone" ] ] } ================================================ FILE: recipes/craft3x/redstone_torch.json ================================================ { "config": "Craft3x", "results": [ { "id": "redstone_torch", "stackSize": 1 } ], "pattern": [ "AOO", "BOO", "OOO" ], "elements": [ [ "A", "redstone" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/rocket.json ================================================ { "config": "Craft3x", "results": [ { "id": "rocket", "stackSize": 1 } ], "pattern": [ "OBO", "BAB", "OOO" ], "elements": [ [ "A", "tnt" ], [ "B", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/rocket_boost.json ================================================ { "config": "Craft3x", "results": [ { "id": "rocket_boost", "stackSize": 1 } ], "pattern": [ "OBB", "BAB", "OOO" ], "elements": [ [ "A", "rocket" ], [ "B", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/rotten_flesh.json ================================================ { "config": "Craft3x", "results": [ { "id": "rotten_flesh", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "flesh_stone" ] ] } ================================================ FILE: recipes/craft3x/sandstone.json ================================================ { "config": "Craft3x", "results": [ { "id": "sandstone", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "sand" ] ] } ================================================ FILE: recipes/craft3x/sandstone_carved.json ================================================ { "config": "Craft3x", "results": [ { "id": "sandstone_carved", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "sandstone" ] ] } ================================================ FILE: recipes/craft3x/sea_lantern.json ================================================ { "config": "Craft3x", "results": [ { "id": "sea_lantern", "stackSize": 1 } ], "pattern": [ "BAB", "AAA", "BAB" ], "elements": [ [ "A", "prismarine_crystals" ], [ "B", "prismarine_shard" ] ] } ================================================ FILE: recipes/craft3x/shadow_staff.json ================================================ { "config": "Craft3x", "results": [ { "id": "shadow_staff", "stackSize": 1 } ], "pattern": [ "OAB", "OCA", "COO" ], "elements": [ [ "A", "ender_pearl" ], [ "B", "diamond" ], [ "C", "silver_ingot" ] ] } ================================================ FILE: recipes/craft3x/shears.json ================================================ { "config": "Craft3x", "results": [ { "id": "shears", "stackSize": 1 } ], "pattern": [ "OAO", "AOO", "OOO" ], "elements": [ [ "A", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/shot_bow.json ================================================ { "config": "Craft3x", "results": [ { "id": "shot_bow", "stackSize": 1 } ], "pattern": [ "AAA", "CDC", "OBO" ], "elements": [ [ "A", "gold_ingot" ], [ "B", "stick" ], [ "C", "string" ], [ "D", "cross_bow" ] ], "importantElements": [ "A", "D" ] } ================================================ FILE: recipes/craft3x/shot_bow_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "shot_bow", "stackSize": 1 } ], "pattern": [ "AAA", "CDC", "OBO" ], "elements": [ [ "A", "silver_ingot" ], [ "B", "stick" ], [ "C", "string" ], [ "D", "cross_bow" ] ], "importantElements": [ "A", "B" ] } ================================================ FILE: recipes/craft3x/shulker_box.json ================================================ { "config": "Craft3x", "results": [ { "id": "shulker_box", "stackSize": 1 } ], "pattern": [ "AOO", "BOO", "AOO" ], "elements": [ [ "A", "shulker_shell" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/sign.json ================================================ { "config": "Craft3x", "results": [ { "id": "sign", "stackSize": 3 } ], "pattern": [ "AAA", "AAA", "OBO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/silver_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "silver_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "silver_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/silver_bullet.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "silver_bullet", "stackSize": 16 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "fire_charge" ], [ "B", "silver_ingot" ] ] } ================================================ FILE: recipes/craft3x/silver_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "silver_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "silver_ingot" ] ] } ================================================ FILE: recipes/craft3x/silver_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "silver_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "silver_ingot" ] ] } ================================================ FILE: recipes/craft3x/silver_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "silver_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "silver_ingot" ] ] } ================================================ FILE: recipes/craft3x/silver_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "silver_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "silver_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/silver_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "silver_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "silver_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/slime_block.json ================================================ { "config": "Craft3x", "results": [ { "id": "slime_block", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "slimeball" ] ] } ================================================ FILE: recipes/craft3x/slimeball.json ================================================ { "config": "Craft3x", "results": [ { "id": "slimeball", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "slime_block" ] ] } ================================================ FILE: recipes/craft3x/snow.json ================================================ { "config": "Craft3x", "results": [ { "id": "snow", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "snowball" ] ] } ================================================ FILE: recipes/craft3x/snow_brick.json ================================================ { "config": "Craft3x", "results": [ { "id": "snow_brick", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "snow" ] ] } ================================================ FILE: recipes/craft3x/snowball.json ================================================ { "config": "Craft3x", "results": [ { "id": "snowball", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "snow" ] ] } ================================================ FILE: recipes/craft3x/spruce_plank.json ================================================ { "config": "Craft3x", "results": [ { "id": "spruce_plank", "stackSize": 4 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "wood_spruce" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_black.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_black", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_black" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_blue.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_blue", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_blue" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_brown.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_brown", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_brown" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_cyan.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_cyan", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_cyan" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_gray.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_gray", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_gray" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_green.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_green", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_green" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_light_blue.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_light_blue", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_light_blue" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_light_gray.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_light_gray", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_light_gray" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_lime.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_lime", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_lime" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_magenta.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_magenta", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_magenta" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_orange.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_orange", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_orange" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_pink.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_pink", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_pink" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_purple.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_purple", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_purple" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_red.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_red", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_red" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_white.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_white", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_white" ] ] } ================================================ FILE: recipes/craft3x/stained_glass_yellow.json ================================================ { "config": "Craft3x", "results": [ { "id": "stained_glass_yellow", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_GLASS" ], [ "B", "dye_yellow" ] ] } ================================================ FILE: recipes/craft3x/star_arrow.json ================================================ { "config": "Craft3x", "results": [ { "id": "star_arrow", "stackSize": 4 } ], "pattern": [ "OAO", "ABA", "OAO" ], "elements": [ [ "A", "lighting_arrow" ], [ "B", "gold_nugget" ] ] } ================================================ FILE: recipes/craft3x/star_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "star_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "star_ingot" ] ] } ================================================ FILE: recipes/craft3x/star_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "star_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "star_ingot" ] ] } ================================================ FILE: recipes/craft3x/star_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "star_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "star_ingot" ] ] } ================================================ FILE: recipes/craft3x/steel_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "steel_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "steel_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/steel_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "steel_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "steel_ingot" ] ] } ================================================ FILE: recipes/craft3x/steel_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "steel_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "steel_ingot" ] ] } ================================================ FILE: recipes/craft3x/steel_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "steel_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "steel_ingot" ] ] } ================================================ FILE: recipes/craft3x/steel_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "steel_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "steel_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/steel_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "steel_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "steel_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/stick.json ================================================ { "config": "Craft3x", "results": [ { "id": "stick", "stackSize": 4 } ], "pattern": [ "AOO", "AOO", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ] ] } ================================================ FILE: recipes/craft3x/stone.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "flesh_dirt" ], [ "B", "flesh_stone" ] ] } ================================================ FILE: recipes/craft3x/stone_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "tainted_stone" ], [ "B", "bone_meal" ] ] } ================================================ FILE: recipes/craft3x/stone_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "cobblestone" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/stone_brick.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone_brick", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "stone" ] ] } ================================================ FILE: recipes/craft3x/stone_brick_carved.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone_brick_carved", "stackSize": 4 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "stone_brick" ] ] } ================================================ FILE: recipes/craft3x/stone_brick_mossy.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "stone_brick_mossy", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "stone_brick" ], [ "B", "vine" ] ] } ================================================ FILE: recipes/craft3x/stone_button.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone_button", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "stone" ] ] } ================================================ FILE: recipes/craft3x/stone_chest.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone_chest", "stackSize": 1 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "cobblestone" ], [ "B", "chest" ] ] } ================================================ FILE: recipes/craft3x/stone_hoe.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone_hoe", "stackSize": 1 } ], "pattern": [ "AAO", "OBO", "OBO" ], "elements": [ [ "A", "cobblestone" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/stone_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "cobblestone" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/stone_pressure_plate.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone_pressure_plate", "stackSize": 1 } ], "pattern": [ "AAO", "OOO", "OOO" ], "elements": [ [ "A", "stone" ] ] } ================================================ FILE: recipes/craft3x/stone_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "stone_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "cobblestone" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/strange_eye.json ================================================ { "config": "Craft3x", "results": [ { "id": "strange_eye", "stackSize": 1 } ], "pattern": [ "OAO", "AAA", "OAO" ], "elements": [ [ "A", "strange_len" ] ] } ================================================ FILE: recipes/craft3x/string.json ================================================ { "config": "Craft3x", "results": [ { "id": "string", "stackSize": 2 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "cobweb" ] ] } ================================================ FILE: recipes/craft3x/suger.json ================================================ { "config": "Craft3x", "results": [ { "id": "suger", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "sugar_cane" ] ] } ================================================ FILE: recipes/craft3x/super_bronze_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_bronze_sword", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "BBO" ], "elements": [ [ "A", "bronze_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/super_copper_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_copper_sword", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "BBO" ], "elements": [ [ "A", "copper_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/super_cross_bow.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_cross_bow", "stackSize": 1 } ], "pattern": [ "EAE", "CDC", "OBO" ], "elements": [ [ "A", "diamond" ], [ "B", "stick" ], [ "C", "string" ], [ "D", "cross_bow" ], [ "E", "OD_IRON_INGOT" ] ], "importantElements": [ "A", "D", "E" ] } ================================================ FILE: recipes/craft3x/super_diamond_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_diamond_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "diamond_ingot" ] ] } ================================================ FILE: recipes/craft3x/super_diamond_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_diamond_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "diamond_ingot" ] ] } ================================================ FILE: recipes/craft3x/super_diamond_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_diamond_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "diamond_ingot" ] ] } ================================================ FILE: recipes/craft3x/super_diamond_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_diamond_sword", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "BBO" ], "elements": [ [ "A", "diamond" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/super_golden_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_golden_sword", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "BBO" ], "elements": [ [ "A", "gold_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/super_iron_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_iron_sword", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "BBO" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/super_lead_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_lead_sword", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "BBO" ], "elements": [ [ "A", "lead_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/super_silver_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_silver_sword", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "BBO" ], "elements": [ [ "A", "silver_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/super_steel_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_steel_sword", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "BBO" ], "elements": [ [ "A", "steel_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/super_tin_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "super_tin_sword", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "BBO" ], "elements": [ [ "A", "tin_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/sword_arrow.json ================================================ { "config": "Craft3x", "results": [ { "id": "sword_arrow", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wooden_arrow" ], [ "B", "shulker_shell" ] ] } ================================================ FILE: recipes/craft3x/sword_arrow_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "sword_arrow", "stackSize": 16 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wooden_arrow" ], [ "B", "ender_pearl" ] ] } ================================================ FILE: recipes/craft3x/sword_arrow_3.json ================================================ { "config": "Craft3x", "results": [ { "id": "sword_arrow", "stackSize": 24 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wooden_arrow" ], [ "B", "ender_eye" ] ] } ================================================ FILE: recipes/craft3x/table_acacia.json ================================================ { "config": "Craft3x", "results": [ { "id": "table_acacia", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "acacia_plank" ] ] } ================================================ FILE: recipes/craft3x/table_birch.json ================================================ { "config": "Craft3x", "results": [ { "id": "table_birch", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "birch_plank" ] ] } ================================================ FILE: recipes/craft3x/table_dark_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "table_dark_oak", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "dark_oak_plank" ] ] } ================================================ FILE: recipes/craft3x/table_jungle.json ================================================ { "config": "Craft3x", "results": [ { "id": "table_jungle", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "jungle_plank" ] ] } ================================================ FILE: recipes/craft3x/table_nether.json ================================================ { "config": "Craft3x", "results": [ { "id": "table_nether", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "nether_brick" ] ] } ================================================ FILE: recipes/craft3x/table_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "table_oak", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "oak_plank" ] ] } ================================================ FILE: recipes/craft3x/table_palm.json ================================================ { "config": "Craft3x", "results": [ { "id": "table_palm", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "palm_plank" ] ] } ================================================ FILE: recipes/craft3x/table_spruce.json ================================================ { "config": "Craft3x", "results": [ { "id": "table_spruce", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "spruce_plank" ] ] } ================================================ FILE: recipes/craft3x/table_tainted.json ================================================ { "config": "Craft3x", "results": [ { "id": "table_tainted", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "tainted_plank" ] ] } ================================================ FILE: recipes/craft3x/table_volcano.json ================================================ { "config": "Craft3x", "results": [ { "id": "table_volcano", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "volcano_plank" ] ] } ================================================ FILE: recipes/craft3x/tainted_plank.json ================================================ { "config": "Craft3x", "results": [ { "id": "tainted_plank", "stackSize": 5 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "wood_tainted" ] ] } ================================================ FILE: recipes/craft3x/terracotta_black.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_black", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_black" ] ] } ================================================ FILE: recipes/craft3x/terracotta_black_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_black", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "ink_sac" ] ] } ================================================ FILE: recipes/craft3x/terracotta_blue.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_blue", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_blue" ] ] } ================================================ FILE: recipes/craft3x/terracotta_blue_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_blue", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "lapis_lazuli" ] ] } ================================================ FILE: recipes/craft3x/terracotta_brown.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_brown", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_brown" ] ] } ================================================ FILE: recipes/craft3x/terracotta_cyan.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_cyan", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_cyan" ] ] } ================================================ FILE: recipes/craft3x/terracotta_gray.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_gray", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_gray" ] ] } ================================================ FILE: recipes/craft3x/terracotta_green.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_green", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_green" ] ] } ================================================ FILE: recipes/craft3x/terracotta_light_blue.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_light_blue", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_light_blue" ] ] } ================================================ FILE: recipes/craft3x/terracotta_light_gray.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_light_gray", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_light_gray" ] ] } ================================================ FILE: recipes/craft3x/terracotta_lime.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_lime", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_lime" ] ] } ================================================ FILE: recipes/craft3x/terracotta_magenta.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_magenta", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_magenta" ] ] } ================================================ FILE: recipes/craft3x/terracotta_orange.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_orange", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_orange" ] ] } ================================================ FILE: recipes/craft3x/terracotta_pink.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_pink", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_pink" ] ] } ================================================ FILE: recipes/craft3x/terracotta_purple.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_purple", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_purple" ] ] } ================================================ FILE: recipes/craft3x/terracotta_red.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_red", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_red" ] ] } ================================================ FILE: recipes/craft3x/terracotta_white.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_white", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_white" ] ] } ================================================ FILE: recipes/craft3x/terracotta_white_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_white", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "bone_meal" ] ] } ================================================ FILE: recipes/craft3x/terracotta_yellow.json ================================================ { "config": "Craft3x", "results": [ { "id": "terracotta_yellow", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "OD_TERRACOTTA" ], [ "B", "dye_yellow" ] ] } ================================================ FILE: recipes/craft3x/tin_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "tin_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "tin_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/tin_chestplate.json ================================================ { "config": "Craft3x", "results": [ { "id": "tin_chestplate", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "AAA" ], "elements": [ [ "A", "tin_ingot" ] ] } ================================================ FILE: recipes/craft3x/tin_helmet.json ================================================ { "config": "Craft3x", "results": [ { "id": "tin_helmet", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "OOO" ], "elements": [ [ "A", "tin_ingot" ] ] } ================================================ FILE: recipes/craft3x/tin_leggings.json ================================================ { "config": "Craft3x", "results": [ { "id": "tin_leggings", "stackSize": 1 } ], "pattern": [ "AAA", "AOA", "AOA" ], "elements": [ [ "A", "tin_ingot" ] ] } ================================================ FILE: recipes/craft3x/tin_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "tin_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "tin_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/tin_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "tin_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "tin_ingot" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/tnt.json ================================================ { "config": "Craft3x", "results": [ { "id": "tnt", "stackSize": 1 } ], "pattern": [ "BAB", "ABA", "BAB" ], "elements": [ [ "A", "sand" ], [ "B", "gunpowder" ] ] } ================================================ FILE: recipes/craft3x/tnt_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "tnt", "stackSize": 1 } ], "pattern": [ "BAB", "ABA", "BAB" ], "elements": [ [ "A", "red_sand" ], [ "B", "gunpowder" ] ] } ================================================ FILE: recipes/craft3x/torch.json ================================================ { "config": "Craft3x", "results": [ { "id": "torch", "stackSize": 4 } ], "pattern": [ "AOO", "BOO", "OOO" ], "elements": [ [ "A", "slimeball" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/torch_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "torch", "stackSize": 6 } ], "pattern": [ "AOO", "BOO", "OOO" ], "elements": [ [ "A", "coal" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/torch_3.json ================================================ { "config": "Craft3x", "results": [ { "id": "torch", "stackSize": 6 } ], "pattern": [ "AOO", "BOO", "OOO" ], "elements": [ [ "A", "charcoal" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/tower_core.json ================================================ { "config": "Craft3x", "results": [ { "id": "tower_core", "stackSize": 1 } ], "pattern": [ "OBO", "BAB", "OBO" ], "elements": [ [ "A", "ice_element_ball"], [ "B", "ghost" ] ] } ================================================ FILE: recipes/craft3x/trapped_chest.json ================================================ { "config": "Craft3x", "results": [ { "id": "trapped_chest", "stackSize": 1 } ], "pattern": [ "OBO", "BAB", "OBO" ], "elements": [ [ "A", "chest" ], [ "B", "redstone" ] ] } ================================================ FILE: recipes/craft3x/volcano_plank.json ================================================ { "config": "Craft3x", "results": [ { "id": "volcano_plank", "stackSize": 6 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "wood_volcano" ] ] } ================================================ FILE: recipes/craft3x/water_staff.json ================================================ { "config": "Craft3x", "results": [ { "id": "water_staff", "stackSize": 1 } ], "pattern": [ "OAB", "OCA", "COO" ], "elements": [ [ "A", "copper_ingot" ], [ "B", "bucket_water" ], [ "C", "OD_IRON_INGOT" ] ] } ================================================ FILE: recipes/craft3x/watermelon.json ================================================ { "config": "Craft3x", "results": [ { "id": "watermelon", "stackSize": 1 } ], "pattern": [ "AAA", "AAA", "AAA" ], "elements": [ [ "A", "melon_slice" ] ] } ================================================ FILE: recipes/craft3x/wheat.json ================================================ { "config": "Craft3x", "results": [ { "id": "wheat", "stackSize": 9 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "hay_bale" ] ] } ================================================ FILE: recipes/craft3x/white_torch.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "white_torch", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "torch" ], [ "B", "dye_white" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wire_cutter.json ================================================ { "config": "Craft3x", "results": [ { "id": "wire_cutter", "stackSize": 1 } ], "pattern": [ "AOA", "AAA", "BOB" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/wooden_arrow.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_arrow", "stackSize": 6 } ], "pattern": [ "AOO", "BOO", "COO" ], "elements": [ [ "A", "flint" ], [ "B", "stick" ], [ "C", "feather" ] ], "importantElements": [ "A", "C" ] } ================================================ FILE: recipes/craft3x/wooden_arrow_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_arrow", "stackSize": 6 } ], "pattern": [ "AOO", "BOO", "COO" ], "elements": [ [ "A", "flint" ], [ "B", "stick" ], [ "C", "gray_feather" ] ], "importantElements": [ "A", "C" ] } ================================================ FILE: recipes/craft3x/wooden_arrow_3.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_arrow", "stackSize": 16 } ], "pattern": [ "AOO", "BOO", "COO" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "stick" ], [ "C", "feather" ] ], "importantElements": [ "A", "C" ] } ================================================ FILE: recipes/craft3x/wooden_arrow_4.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_arrow", "stackSize": 16 } ], "pattern": [ "AOO", "BOO", "COO" ], "elements": [ [ "A", "OD_IRON_INGOT" ], [ "B", "stick" ], [ "C", "gray_feather" ] ], "importantElements": [ "A", "C" ] } ================================================ FILE: recipes/craft3x/wooden_axe.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_axe", "stackSize": 1 } ], "pattern": [ "AAO", "ABO", "OBO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/wooden_bed_black.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_black", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_black" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_black_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_black", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_black" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_blue.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_blue", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_blue" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_blue_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_blue", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_blue" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_brown.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_brown", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_brown" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_brown_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_brown", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_brown" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_cyan.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_cyan", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_cyan" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_cyan_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_cyan", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_cyan" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_gray.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_gray", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_gray" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_gray_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_gray", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_gray" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_green.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_green", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_green" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_green_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_green", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_green" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_light_blue.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_light_blue", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_light_blue" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_light_blue_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_light_blue", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_light_blue" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_light_gray.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_light_gray", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_light_gray" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_light_gray_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_light_gray", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_light_gray" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_lime.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_lime", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_lime" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_lime_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_lime", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_lime" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_magenta.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_magenta", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_magenta" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_magenta_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_magenta", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_magenta" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_orange.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_orange", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_orange" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_orange_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_orange", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_orange" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_pink.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_pink", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_pink" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_pink_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_pink", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_pink" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_purple.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_purple", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_purple" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_purple_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_purple", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_purple" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_red.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_red", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_red" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_red_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_red", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_red" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_white.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_white", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_white" ] ] } ================================================ FILE: recipes/craft3x/wooden_bed_yellow.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "wooden_bed_yellow", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "wooden_bed_white" ], [ "B", "dye_yellow" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_bed_yellow_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bed_yellow", "stackSize": 1 } ], "pattern": [ "BBB", "AAA", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "wool_yellow" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_boomerang.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_boomerang", "stackSize": 1 } ], "pattern": [ "OAO", "AOO", "OAO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ] ] } ================================================ FILE: recipes/craft3x/wooden_bow.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_bow", "stackSize": 1 } ], "pattern": [ "OAB", "AOB", "OAB" ], "elements": [ [ "A", "stick" ], [ "B", "string" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/wooden_button.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_button", "stackSize": 1 } ], "pattern": [ "AOO", "OOO", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ] ] } ================================================ FILE: recipes/craft3x/wooden_door_acacia.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_door_acacia", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "acacia_plank" ] ] } ================================================ FILE: recipes/craft3x/wooden_door_birch.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_door_birch", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "birch_plank" ] ] } ================================================ FILE: recipes/craft3x/wooden_door_dark_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_door_dark_oak", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "dark_oak_plank" ] ] } ================================================ FILE: recipes/craft3x/wooden_door_jungle.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_door_jungle", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "jungle_plank" ] ] } ================================================ FILE: recipes/craft3x/wooden_door_oak.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_door_oak", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "oak_plank" ] ] } ================================================ FILE: recipes/craft3x/wooden_door_palm.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_door_palm", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "palm_plank" ] ] } ================================================ FILE: recipes/craft3x/wooden_door_spruce.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_door_spruce", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "spruce_plank" ] ] } ================================================ FILE: recipes/craft3x/wooden_door_tainted.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_door_tainted", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "tainted_plank" ] ] } ================================================ FILE: recipes/craft3x/wooden_door_volcano.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_door_volcano", "stackSize": 3 } ], "pattern": [ "AAO", "AAO", "AAO" ], "elements": [ [ "A", "volcano_plank" ] ] } ================================================ FILE: recipes/craft3x/wooden_hoe.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_hoe", "stackSize": 1 } ], "pattern": [ "AAO", "OBO", "OBO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/wooden_pickaxe.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_pickaxe", "stackSize": 1 } ], "pattern": [ "AAA", "OBO", "OBO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/wooden_pressure_plate.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_pressure_plate", "stackSize": 1 } ], "pattern": [ "AAO", "OOO", "OOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ] ] } ================================================ FILE: recipes/craft3x/wooden_sword.json ================================================ { "config": "Craft3x", "results": [ { "id": "wooden_sword", "stackSize": 1 } ], "pattern": [ "AOO", "AOO", "BOO" ], "elements": [ [ "A", "OD_WOODEN_PLANK" ], [ "B", "stick" ] ], "importantElements": [ "A" ] } ================================================ FILE: recipes/craft3x/wool_black.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_black", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_black" ] ] } ================================================ FILE: recipes/craft3x/wool_black_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_black", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "ink_sac" ] ] } ================================================ FILE: recipes/craft3x/wool_blue.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_blue", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_blue" ] ] } ================================================ FILE: recipes/craft3x/wool_blue_2.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_blue", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "lapis_lazuli" ] ] } ================================================ FILE: recipes/craft3x/wool_brown.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_brown", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_brown" ] ] } ================================================ FILE: recipes/craft3x/wool_cyan.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_cyan", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_cyan" ] ] } ================================================ FILE: recipes/craft3x/wool_gray.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_gray", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_gray" ] ] } ================================================ FILE: recipes/craft3x/wool_green.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_green", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_green" ] ] } ================================================ FILE: recipes/craft3x/wool_light_blue.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_light_blue", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_light_blue" ] ] } ================================================ FILE: recipes/craft3x/wool_light_gray.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_light_gray", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_light_gray" ] ] } ================================================ FILE: recipes/craft3x/wool_lime.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_lime", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_lime" ] ] } ================================================ FILE: recipes/craft3x/wool_magenta.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_magenta", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_magenta" ] ] } ================================================ FILE: recipes/craft3x/wool_orange.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_orange", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_orange" ] ] } ================================================ FILE: recipes/craft3x/wool_pink.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_pink", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_pink" ] ] } ================================================ FILE: recipes/craft3x/wool_purple.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_purple", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_purple" ] ] } ================================================ FILE: recipes/craft3x/wool_red.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_red", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_red" ] ] } ================================================ FILE: recipes/craft3x/wool_white.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_white", "stackSize": 1 } ], "pattern": [ "AAO", "AAO", "OOO" ], "elements": [ [ "A", "string" ] ] } ================================================ FILE: recipes/craft3x/wool_yellow.json ================================================ { "config": "Craft3x", "results": [ { "id": "wool_yellow", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "wool_white" ], [ "B", "dye_yellow" ] ] } ================================================ FILE: recipes/craft3x/yellow_torch.json ================================================ { "config": "Craft3x", "searchActions": [ [ 0, "SA_UNORDER" ] ], "results": [ { "id": "yellow_torch", "stackSize": 1 } ], "pattern": [ "ABO", "OOO", "OOO" ], "elements": [ [ "A", "torch" ], [ "B", "dye_yellow" ] ], "importantElements": [ "B" ] } ================================================ FILE: recipes/craft3x/yellow_wire.json ================================================ { "config": "Craft3x", "results": [ { "id": "yellow_wire", "stackSize": 8 } ], "pattern": [ "AAA", "ABA", "AAA" ], "elements": [ [ "A", "red_wire" ], [ "B", "dye_yellow" ] ] } ================================================ FILE: recipes/repair/ancient_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "ancient_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "ancient_chestplate" ], [ "B", "ancient_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/ancient_chestplate_2.json ================================================ { "config": "Repair", "results": [ { "id": "ancient_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_diamond_chestplate" ], [ "B", "ancient_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/ancient_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "ancient_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "ancient_helmet" ], [ "B", "ancient_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/ancient_helmet_2.json ================================================ { "config": "Repair", "results": [ { "id": "ancient_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_diamond_helmet" ], [ "B", "ancient_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/ancient_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "ancient_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "ancient_leggings" ], [ "B", "ancient_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/ancient_leggings_2.json ================================================ { "config": "Repair", "results": [ { "id": "ancient_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_diamond_leggings" ], [ "B", "ancient_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/bronze_axe.json ================================================ { "config": "Repair", "results": [ { "id": "bronze_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "bronze_axe" ], [ "B", "bronze_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/bronze_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "bronze_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "bronze_chestplate" ], [ "B", "bronze_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/bronze_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "bronze_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "bronze_helmet" ], [ "B", "bronze_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/bronze_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "bronze_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "bronze_leggings" ], [ "B", "bronze_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/bronze_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "bronze_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "bronze_pickaxe" ], [ "B", "bronze_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/bronze_sword.json ================================================ { "config": "Repair", "results": [ { "id": "bronze_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "bronze_sword" ], [ "B", "bronze_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/copper_axe.json ================================================ { "config": "Repair", "results": [ { "id": "copper_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "copper_axe" ], [ "B", "copper_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/copper_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "copper_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "copper_chestplate" ], [ "B", "copper_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/copper_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "copper_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "copper_helmet" ], [ "B", "copper_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/copper_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "copper_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "copper_leggings" ], [ "B", "copper_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/copper_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "copper_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "copper_pickaxe" ], [ "B", "copper_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/copper_sword.json ================================================ { "config": "Repair", "results": [ { "id": "copper_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "copper_sword" ], [ "B", "copper_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/diamond_axe.json ================================================ { "config": "Repair", "results": [ { "id": "diamond_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_axe" ], [ "B", "diamond" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/diamond_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "diamond_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_chestplate" ], [ "B", "diamond" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/diamond_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "diamond_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_helmet" ], [ "B", "diamond" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/diamond_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "diamond_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_leggings" ], [ "B", "diamond" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/diamond_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "diamond_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_pickaxe" ], [ "B", "diamond" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/diamond_sword.json ================================================ { "config": "Repair", "results": [ { "id": "diamond_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_sword" ], [ "B", "diamond" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/golden_axe.json ================================================ { "config": "Repair", "results": [ { "id": "golden_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "golden_axe" ], [ "B", "gold_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/golden_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "golden_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "golden_chestplate" ], [ "B", "gold_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/golden_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "golden_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "golden_helmet" ], [ "B", "gold_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/golden_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "golden_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "golden_leggings" ], [ "B", "gold_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/golden_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "golden_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "golden_pickaxe" ], [ "B", "gold_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/golden_sword.json ================================================ { "config": "Repair", "results": [ { "id": "golden_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "golden_sword" ], [ "B", "gold_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/iron_axe.json ================================================ { "config": "Repair", "results": [ { "id": "iron_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "iron_axe" ], [ "B", "iron_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/iron_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "iron_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "iron_chestplate" ], [ "B", "iron_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/iron_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "iron_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "iron_helmet" ], [ "B", "iron_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/iron_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "iron_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "iron_leggings" ], [ "B", "iron_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/iron_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "iron_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "iron_pickaxe" ], [ "B", "iron_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/iron_sword.json ================================================ { "config": "Repair", "results": [ { "id": "iron_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "iron_sword" ], [ "B", "iron_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/lead_axe.json ================================================ { "config": "Repair", "results": [ { "id": "lead_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "lead_axe" ], [ "B", "lead_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/lead_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "lead_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "lead_chestplate" ], [ "B", "lead_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/lead_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "lead_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "lead_helmet" ], [ "B", "lead_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/lead_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "lead_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "lead_leggings" ], [ "B", "lead_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/lead_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "lead_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "lead_pickaxe" ], [ "B", "lead_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/lead_sword.json ================================================ { "config": "Repair", "results": [ { "id": "lead_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "lead_sword" ], [ "B", "lead_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/leather_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "leather_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "leather_chestplate" ], [ "B", "leather" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/leather_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "leather_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "leather_helmet" ], [ "B", "leather" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/leather_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "leather_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "leather_leggings" ], [ "B", "leather" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_axe.json ================================================ { "config": "Repair", "results": [ { "id": "nether_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "nether_axe" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_axe_2.json ================================================ { "config": "Repair", "results": [ { "id": "nether_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_axe" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "nether_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "nether_chestplate" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_chestplate_2.json ================================================ { "config": "Repair", "results": [ { "id": "nether_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_chestplate" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "nether_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "nether_helmet" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_helmet_2.json ================================================ { "config": "Repair", "results": [ { "id": "nether_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_helmet" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_helmet_3.json ================================================ { "config": "Repair", "results": [ { "id": "nether_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_helmet" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "nether_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "nether_leggings" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_leggings_2.json ================================================ { "config": "Repair", "results": [ { "id": "nether_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_leggings" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "nether_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "nether_pickaxe" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_pickaxe_2.json ================================================ { "config": "Repair", "results": [ { "id": "nether_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_pickaxe" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_sword.json ================================================ { "config": "Repair", "results": [ { "id": "nether_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "nether_sword" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/nether_sword_2.json ================================================ { "config": "Repair", "results": [ { "id": "nether_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "diamond_sword" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/silver_axe.json ================================================ { "config": "Repair", "results": [ { "id": "silver_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "silver_axe" ], [ "B", "silver_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/silver_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "silver_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "silver_chestplate" ], [ "B", "silver_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/silver_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "silver_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "silver_helmet" ], [ "B", "silver_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/silver_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "silver_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "silver_leggings" ], [ "B", "silver_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/silver_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "silver_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "silver_pickaxe" ], [ "B", "silver_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/silver_sword.json ================================================ { "config": "Repair", "results": [ { "id": "silver_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "silver_sword" ], [ "B", "silver_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/steel_axe.json ================================================ { "config": "Repair", "results": [ { "id": "steel_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "steel_axe" ], [ "B", "steel_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/steel_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "steel_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "steel_chestplate" ], [ "B", "steel_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/steel_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "steel_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "steel_helmet" ], [ "B", "steel_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/steel_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "steel_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "steel_leggings" ], [ "B", "steel_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/steel_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "steel_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "steel_pickaxe" ], [ "B", "steel_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/steel_sword.json ================================================ { "config": "Repair", "results": [ { "id": "steel_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "steel_sword" ], [ "B", "steel_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/stone_axe.json ================================================ { "config": "Repair", "results": [ { "id": "stone_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "stone_axe" ], [ "B", "cobblestone" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/stone_hoe.json ================================================ { "config": "Repair", "results": [ { "id": "stone_hoe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "stone_hoe" ], [ "B", "cobblestone" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/stone_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "stone_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "stone_pickaxe" ], [ "B", "cobblestone" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/stone_sword.json ================================================ { "config": "Repair", "results": [ { "id": "stone_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "stone_sword" ], [ "B", "cobblestone" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_bronze_sword.json ================================================ { "config": "Repair", "results": [ { "id": "super_bronze_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_bronze_sword" ], [ "B", "bronze_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_copper_sword.json ================================================ { "config": "Repair", "results": [ { "id": "super_copper_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_copper_sword" ], [ "B", "copper_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_diamond_sword.json ================================================ { "config": "Repair", "results": [ { "id": "super_diamond_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_diamond_sword" ], [ "B", "diamond" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_golden_sword.json ================================================ { "config": "Repair", "results": [ { "id": "super_golden_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_golden_sword" ], [ "B", "gold_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_iron_sword.json ================================================ { "config": "Repair", "results": [ { "id": "super_iron_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_iron_sword" ], [ "B", "iron_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_lead_sword.json ================================================ { "config": "Repair", "results": [ { "id": "super_lead_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_lead_sword" ], [ "B", "lead_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_nether_sword.json ================================================ { "config": "Repair", "results": [ { "id": "super_nether_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_nether_sword" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_nether_sword_2.json ================================================ { "config": "Repair", "results": [ { "id": "super_nether_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_diamond_sword" ], [ "B", "netherite_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_silver_sword.json ================================================ { "config": "Repair", "results": [ { "id": "super_silver_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_silver_sword" ], [ "B", "silver_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_steel_sword.json ================================================ { "config": "Repair", "results": [ { "id": "super_steel_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_steel_sword" ], [ "B", "steel_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/super_tin_sword.json ================================================ { "config": "Repair", "results": [ { "id": "super_tin_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "super_tin_sword" ], [ "B", "tin_ingot" ] ], "exData": { "repairRate": 0.15 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/tin_axe.json ================================================ { "config": "Repair", "results": [ { "id": "tin_axe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "tin_axe" ], [ "B", "tin_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/tin_chestplate.json ================================================ { "config": "Repair", "results": [ { "id": "tin_chestplate", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "tin_chestplate" ], [ "B", "tin_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/tin_helmet.json ================================================ { "config": "Repair", "results": [ { "id": "tin_helmet", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "tin_helmet" ], [ "B", "tin_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/tin_leggings.json ================================================ { "config": "Repair", "results": [ { "id": "tin_leggings", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "tin_leggings" ], [ "B", "tin_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/tin_pickaxe.json ================================================ { "config": "Repair", "results": [ { "id": "tin_pickaxe", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "tin_pickaxe" ], [ "B", "tin_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/repair/tin_sword.json ================================================ { "config": "Repair", "results": [ { "id": "tin_sword", "stackSize": 1 } ], "pattern": [ "AB" ], "elements": [ [ "A", "tin_sword" ], [ "B", "tin_ingot" ] ], "exData": { "repairRate": 0.25 }, "importantElements": [ "A" ] } ================================================ FILE: recipes/smelt/baked_potato.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "baked_potato", "stackSize": 1 } ], "elements": [ [ "A", "potato" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_oak" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_10.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_stripped_oak" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_11.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_stripped_spruce" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_12.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_stripped_birch" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_13.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_stripped_jungle" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_14.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_stripped_acacia" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_15.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_stripped_dark_oak" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_16.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_stripped_palm" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_17.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_stripped_volcano" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_18.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_stripped_tainted" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_2.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_spruce" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_3.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_birch" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_4.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_jungle" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_5.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_acacia" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_6.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_palm" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_7.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_volcano" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_8.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_tainted" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/charcoal_9.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "charcoal", "stackSize": 1 } ], "elements": [ [ "A", "wood_dark_oak" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/coal.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "coal", "stackSize": 1 } ], "elements": [ [ "A", "ore_coal" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/cooked_chicken.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "cooked_chicken", "stackSize": 1 } ], "elements": [ [ "A", "raw_chicken" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/cooked_cod.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "cooked_cod", "stackSize": 1 } ], "elements": [ [ "A", "raw_cod" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/cooked_mutton.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "cooked_mutton", "stackSize": 1 } ], "elements": [ [ "A", "raw_mutton" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/cooked_porkchop.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "cooked_porkchop", "stackSize": 1 } ], "elements": [ [ "A", "raw_porkchop" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/cooked_rabbit.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "cooked_rabbit", "stackSize": 1 } ], "elements": [ [ "A", "raw_rabbit" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/cooked_salmon.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "cooked_salmon", "stackSize": 1 } ], "elements": [ [ "A", "raw_salmon" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/copper_ingot.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "copper_ingot", "stackSize": 1 } ], "elements": [ [ "A", "ore_copper", 3 ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/diamond.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "diamond", "stackSize": 1 } ], "elements": [ [ "A", "ore_diamond" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/dried_kelp.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "dried_kelp", "stackSize": 1 } ], "elements": [ [ "A", "kelp" ] ], "exData": { "time": 20 } } ================================================ FILE: recipes/smelt/dye_green.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "dye_green", "stackSize": 1 } ], "elements": [ [ "A", "sapling_cactus" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/emerald.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "emerald", "stackSize": 1 } ], "elements": [ [ "A", "ore_emerald" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/glass.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "glass", "stackSize": 1 } ], "elements": [ [ "A", "sand" ] ], "exData": { "time": 10 } } ================================================ FILE: recipes/smelt/glass_2.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "glass", "stackSize": 1 } ], "elements": [ [ "A", "red_sand" ] ], "exData": { "time": 10 } } ================================================ FILE: recipes/smelt/glass_3.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "glass", "stackSize": 1 } ], "elements": [ [ "A", "prismarine_mud" ] ], "exData": { "time": 160 } } ================================================ FILE: recipes/smelt/gold_ingot.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "gold_ingot", "stackSize": 1 } ], "elements": [ [ "A", "ore_gold", 3 ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/iron_ingot.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "iron_ingot", "stackSize": 1 } ], "elements": [ [ "A", "ore_iron", 3 ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/lapis_lazuli.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "lapis_lazuli", "stackSize": 1 } ], "elements": [ [ "A", "ore_lapis" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/lead_ingot.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "lead_ingot", "stackSize": 1 } ], "elements": [ [ "A", "ore_lead", 3 ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/nether_brick.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "nether_brick", "stackSize": 1 } ], "elements": [ [ "A", "netherrack" ] ], "exData": { "time": 20 } } ================================================ FILE: recipes/smelt/netherite_scrap.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "netherite_scrap", "stackSize": 1 } ], "elements": [ [ "A", "ore_ancient_debris", 3 ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/popped_chorus_fruits.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "popped_chorus_fruits", "stackSize": 1 } ], "elements": [ [ "A", "chorus_fruit" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/quartz.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "quartz", "stackSize": 1 } ], "elements": [ [ "A", "ore_nether_quartz" ] ], "exData": { "time": 20 } } ================================================ FILE: recipes/smelt/red_brick.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "red_brick", "stackSize": 1 } ], "elements": [ [ "A", "clay" ] ], "exData": { "time": 10 } } ================================================ FILE: recipes/smelt/red_sand_smooth.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "red_sand_smooth", "stackSize": 1 } ], "elements": [ [ "A", "red_sand_stone" ] ], "exData": { "time": 10 } } ================================================ FILE: recipes/smelt/redstone.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "redstone", "stackSize": 1 } ], "elements": [ [ "A", "ore_redstone" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/sandstone_smooth.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "sandstone_smooth", "stackSize": 1 } ], "elements": [ [ "A", "sandstone" ] ], "exData": { "time": 10 } } ================================================ FILE: recipes/smelt/silver_ingot.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "silver_ingot", "stackSize": 1 } ], "elements": [ [ "A", "ore_silver", 3 ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/sponge.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "sponge", "stackSize": 1 } ], "elements": [ [ "A", "wet_sponge" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/steak.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "steak", "stackSize": 1 } ], "elements": [ [ "A", "raw_beef" ] ], "exData": { "time": 40 } } ================================================ FILE: recipes/smelt/steel_ingot.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "steel_ingot", "stackSize": 1 } ], "elements": [ [ "A", "iron_ingot", 2 ] ], "exData": { "time": 80 } } ================================================ FILE: recipes/smelt/stone.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "stone", "stackSize": 1 } ], "elements": [ [ "A", "cobblestone" ] ], "exData": { "time": 10 } } ================================================ FILE: recipes/smelt/stone_brick_cracked.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "stone_brick_cracked", "stackSize": 1 } ], "elements": [ [ "A", "stone_brick" ] ], "exData": { "time": 20 } } ================================================ FILE: recipes/smelt/terracotta_pink.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "terracotta_pink", "stackSize": 1 } ], "elements": [ [ "A", "clay_block" ] ], "exData": { "time": 20 } } ================================================ FILE: recipes/smelt/tin_ingot.json ================================================ { "config": "Smelt", "pattern": [ "A" ], "results": [ { "id": "tin_ingot", "stackSize": 1 } ], "elements": [ [ "A", "ore_tin", 3 ] ], "exData": { "time": 40 } } ================================================ FILE: record/RecordData.lua ================================================ ---@class TC.RecordData local RecordData = class("RecordData") local SNOW_QUEEN_ID = Reg.NpcID("snow_queen") local HELL_DESTROYER_ID = Reg.NpcID("worm_head") local CRISON_EYE_ID = Reg.NpcID("crison_eye") local DUNGEON_EATER_ID = Reg.NpcID("dungeon_eater_head") local s_RecordData = nil ---@return TC.RecordData function RecordData.getInstance() if s_RecordData == nil then s_RecordData = RecordData.new() end return s_RecordData end function RecordData:__init() self.hasSnowQueen = false self.hasNetherDestroyer = false self.hasCrisonEye = false self.hasDungeonEater = false self.curBossID = -1 end function RecordData:_updateNpc() self.hasSnowQueen = false self.hasNetherDestroyer = false self.hasCrisonEye = false self.hasDungeonEater = false self.curBossID = -1 local npcs = NpcUtils.GetAllEntities() ---@param npc Npc for _, npc in each(npcs) do local id = npc.id if id == SNOW_QUEEN_ID then self.hasSnowQueen = true self.curBossID = id elseif id == HELL_DESTROYER_ID then self.hasNetherDestroyer = true self.curBossID = id elseif id == CRISON_EYE_ID then self.hasCrisonEye = true self.curBossID = id elseif id == DUNGEON_EATER_ID then self.hasDungeonEater = true self.curBossID = id end end end function RecordData:update() self:_updateNpc() end return RecordData ================================================ FILE: settings/Settings.lua ================================================ ---@class TC.Settings local Settings = class("Settings") local SettingsData = require("SettingsData") local SETTING_FILE = "tc_settings.json" local s_instance ---@return TC.Settings function Settings.getInstance() if s_instance == nil then s_instance = Settings.new() end return s_instance end function Settings:__init() self.uiConfig = { { name = "常规", elements = { -- TODO:有BUG,后面再搞 --{ -- name = "地图显示比例", type = "Slider", -- maxValue = 15, minValue = 0, -- valueStep = 1, -- getter = function() return (MiscUtils.GetMapDisplayScale() - 0.5) * 10 end, -- setter = function(value) MiscUtils.SetMapDisplayScale(value * 0.1 + 0.5) end, --}, { name = "音乐音量", type = "Slider", maxValue = 100, minValue = 0, getter = function() return SettingsData.musicVolume end, setter = function(value) SettingsData.musicVolume = value end, }, { name = "音效音量", type = "Slider", maxValue = 100, minValue = 0, getter = function() return SettingsData.soundVolume end, setter = function(value) SettingsData.soundVolume = value end, }, { name = "显示音乐信息", type = "Boolean", getter = function() return SettingsData.showMusicInfo end, setter = function(value) SettingsData.showMusicInfo = value end, }, } }, { name = "开发者调试", elements = { { name = "移动端操作模拟", type = "Boolean", getter = function() return SettingsData.isMobileOperation end, setter = function(value) if App.isPC then SettingsData.isMobileOperation = value end end, }, { name = "显示调试信息", type = "Boolean", getter = function() return SettingsData.isShowDebugInfo end, setter = function(value) SettingsData.isShowDebugInfo = value end, }, { name = "显示GUI布局", type = "Boolean", getter = function() return SettingsData.isShowUIDebug end, setter = function(value) SettingsData.isShowUIDebug = value end, }, --{ -- name = "TEST VALUE", type = "Slider", -- maxValue = 100, minValue = 0, -- getter = nil, -- setter = nil, --}, --{ -- name = "TEST BOOL 3", type = "Boolean", -- getter = nil, -- setter = nil, --}, --{ -- name = "TEST BOOL 4", type = "Boolean", -- getter = nil, -- setter = nil, --}, --{ -- name = "TEST VALUE 2", type = "Slider", -- maxValue = 100, minValue = 0, -- getter = nil, -- setter = nil, --}, --{ -- name = "TEST BOOL 5", type = "Boolean", -- getter = nil, -- setter = nil, --}, --{ -- name = "TEST BOOL 6", type = "Boolean", -- getter = nil, -- setter = nil, --}, --{ -- name = "TEST BOOL 7", type = "Boolean", -- getter = nil, -- setter = nil, --}, } } } end function Settings.loadData() local path = Path.join(App.persistentDataPath, SETTING_FILE) if File.isPathExist(path) then local jsonStr = File.readAsString(path) local data = JsonUtil.fromJson(jsonStr) local function _readProperty(name) if data[name] ~= nil then SettingsData[name] = data[name] end end for k, _ in pairs(SettingsData) do _readProperty(k) end else -- 默认值 SettingsData.isMobileOperation = App.isMobile and true or false end print("Current Settings Data:", SettingsData) end function Settings.saveData() local path = Path.join(App.persistentDataPath, SETTING_FILE) local jsonStr = JsonUtil.toJson(SettingsData) File.saveString(path, jsonStr) print("Save Settings Data:", SettingsData) end return Settings ================================================ FILE: settings/SettingsData.lua ================================================ local SettingsData = { isMobileOperation = false, isShowDebugInfo = false, isShowUIDebug = false, soundVolume = 100, musicVolume = 100, showMusicInfo = true, } return SettingsData ================================================ FILE: skins/skin_22.json ================================================ { "skin_22": { "isFemale": true, "name": "22", "headTexture": "base/head.png", "bodyTexture": "base/body.png", "legTexture": "base/leg.png", "hairTexture": "22/hair.png", "clothTexture": "22/cloth.png", "pantTexture": "22/pant.png", "authors": [ "BlueYoshi" ] } } ================================================ FILE: skins/skin_33.json ================================================ { "skin_33": { "isFemale": true, "name": "33", "headTexture": "base\\head.png", "bodyTexture": "base\\body.png", "legTexture": "base\\leg.png", "hairTexture": "33\\hair.png", "clothTexture": "33\\cloth.png", "pantTexture": "33\\pant.png", "authors": [ "BlueYoshi" ] } } ================================================ FILE: skins/skin_my.json ================================================ { "skin_my": { "isFemale": true, "headTexture": "base\\head.png", "bodyTexture": "base\\body.png", "legTexture": "base\\leg.png", "hairTexture": "my\\hair.png", "clothTexture": "my\\cloth.png", "pantTexture": "my\\pant.png", "authors": [ "BlueYoshi" ] } } ================================================ FILE: skins/skin_plin.json ================================================ { "skin_plin": { "isFemale": true, "name": "Piglin", "headTexture": "base\\head.png", "bodyTexture": "base\\body.png", "legTexture": "base\\leg.png", "hairTexture": "plin\\hair.png", "clothTexture": "plin\\cloth.png", "pantTexture": "plin\\pant.png", "authors": [ "BlueYoshi" ] } } ================================================ FILE: skins/skin_redust.json ================================================ { "skin_redust": { "isFemale": true, "name": "Redust", "headTexture": "base\\head.png", "bodyTexture": "base\\body.png", "legTexture": "base\\leg.png", "hairTexture": "redust\\hair.png", "clothTexture": "redust\\cloth.png", "pantTexture": "redust\\pant.png", "authors": [ "Redust" ] } } ================================================ FILE: skins/skin_steve.json ================================================ { "skin_steve": { "isFemale": false, "name": "Steve", "headTexture": "base2\\head.png", "bodyTexture": "base2\\body.png", "legTexture": "base2\\leg.png", "hairTexture": "steve\\hair.png", "clothTexture": "steve\\cloth.png", "pantTexture": "steve\\pant.png", "authors": [ "BlueYoshi" ] } } ================================================ FILE: skins/skin_ym.json ================================================ { "skin_ym": { "isFemale": true, "name": "Red Hair", "headTexture": "base\\head.png", "bodyTexture": "base\\body.png", "legTexture": "base\\leg.png", "hairTexture": "ym\\hair.png", "clothTexture": "ym\\cloth.png", "pantTexture": "ym\\pant.png", "authors": [ "BlueYoshi" ] } } ================================================ FILE: skins/skin_yy.json ================================================ { "skin_yy": { "isFemale": true, "name": "White Hair", "headTexture": "base\\head.png", "bodyTexture": "base\\body.png", "legTexture": "base\\leg.png", "hairTexture": "yy\\hair.png", "clothTexture": "yy\\cloth.png", "pantTexture": "yy\\pant.png", "authors": [ "BlueYoshi" ] } } ================================================ FILE: skins/skin_zk.json ================================================ { "skin_zk": { "isFemale": true, "headTexture": "base\\head.png", "bodyTexture": "base\\body.png", "legTexture": "base\\leg.png", "hairTexture": "zk\\hair.png", "clothTexture": "zk\\cloth.png", "pantTexture": "zk\\pant.png", "authors": [ "BlueYoshi" ] } } ================================================ FILE: skins/xqz.json ================================================ { "xqz": { "isFemale": true, "name": "Mr. Skirt", "headTexture": "xqz\\head.png", "bodyTexture": "xqz\\body.png", "legTexture": "xqz\\leg.png", "hairTexture": "xqz\\hair.png", "clothTexture": "xqz\\cloth.png", "pantTexture": "xqz\\pant.png", "authors": [ "BlueYoshi" ] } } ================================================ FILE: sounds/README.txt ================================================ All sound comes from Minecraft, RPG Maker XP and Minecraft Working Gun Mod 1.12.2. If you like Minecraft you can get more Minecraft sounds here: https://o.xbottle.top/mcsounds/ ================================================ FILE: spawns/aurora_palace.json ================================================ { "walls": [ { "id": "aurora_block" } ], "spawn": { "mobSpeed": 150, "maxMobSpawn": 6, "mobs": [ { "id": "snow_guardian", "weight": 5 }, { "id": "snow_guardian_archer", "weight": 5 } ] } } ================================================ FILE: spawns/end_outpost.json ================================================ { "walls": [ { "id": "end_stone_brick" }, { "id": "purpur_block" } ], "spawn": { "mobSpeed": 150, "maxMobSpawn": 4, "mobs": [ { "id": "shulker", "weight": 5 } ] } } ================================================ FILE: spawns/monument_ocean.json ================================================ { "walls": [ { "id": "prismarine" } ], "spawn": { "mobSpeed": 20, "maxMobSpawn": 10, "mobs": [ { "id": "guardian", "weight": 5 } ] } } ================================================ FILE: textures/backgrounds/atlas_config.json ================================================ [ { "name": "sky", "path": "sky", "size": 512 }, { "name": "backgrounds", "path": "layers", "size": 2048 }, { "name": "cave_backgrounds", "path": "walls", "size": 2048 } ] ================================================ FILE: trees/acacia/acacia.json ================================================ { "tree": { "acacia": { "length": 6, "baseTiles": [ "dirt", "coarse_dirt" ], "leafs": [ "leaf.png", "leaf_2.png", "leaf_3.png", "leaf_4.png", "leaf_5.png", "leaf_6.png" ], "branches": [ [ "branch.png", [ 68, 136 ], [ 88, 118 ], [ 211, 112 ] ], [ "branch_2.png", [ 51, 101 ], [ 104, 113 ], [ 226, 131 ], [ 180, 80 ] ], [ "branch_3.png", [ 59, 118 ], [ 84, 100 ], [ 228, 112 ], [ 206, 83 ] ] ], "crowns": [ [ "crown.png", [ 74, 146 ], [ 80, 130 ], [ 100, 100 ], [ 193, 84 ], [ 156, 146 ] ], [ "crown_2.png", [ 120, 138 ], [ 188, 116 ], [ 68, 96 ], [ 216, 80 ], [ 136, 58 ] ], [ "crown_3.png", [ 140, 140 ], [ 60, 112 ], [ 228, 113 ], [ 183, 72 ], [ 103, 40 ] ] ], "woodId": "wood_acacia", "saplingId": "sapling_acacia", "fruits": [] } }, "block": { "log_acacia": { "textureData": "stem.png", "color": [ 85, 80, 72 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 620, "treeId": "acacia", "soundGroupId": "wood", "particleColor": [ 255, 80, 76, 70 ] } } } ================================================ FILE: trees/bare_oak/bare_oak.json ================================================ { "tree": { "bare_oak": { "length": 2, "baseTiles": [ "red_sand", "red_sand_stone" ], "leafs": [], "branches": [ [ "branch.png" ], [ "branch_2.png" ], [ "branch_3.png" ] ], "crowns": [ [ "crown.png" ], [ "crown_2.png" ], [ "crown_3.png" ] ], "woodId": "wood_oak", "saplingId": "sapling_bare_oak", "fruits": [] } }, "block": { "log_bare_oak": { "textureData": "stem.png", "color": [ 98, 78, 35 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 600, "treeId": "bare_oak", "soundGroupId": "wood", "particleColor": [ 255, 98, 78, 35 ] } } } ================================================ FILE: trees/birch/birch.json ================================================ { "tree": { "birch": { "length": 7, "baseTiles": [ "dirt", "coarse_dirt" ], "leafs": [ "leaf.png", "leaf_2.png", "leaf_3.png", "leaf_4.png", "leaf_5.png", "leaf_6.png" ], "branches": [ [ "branch.png", [ 68, 136 ], [ 88, 118 ], [ 211, 112 ] ], [ "branch_2.png", [ 51, 101 ], [ 104, 113 ], [ 226, 131 ], [ 180, 80 ] ], [ "branch_3.png", [ 59, 118 ], [ 84, 100 ], [ 228, 112 ], [ 206, 83 ] ] ], "crowns": [ [ "crown.png", [ 74, 146 ], [ 80, 130 ], [ 100, 100 ], [ 193, 84 ], [ 156, 146 ] ], [ "crown_2.png", [ 120, 138 ], [ 188, 116 ], [ 68, 96 ], [ 216, 80 ], [ 136, 58 ] ], [ "crown_3.png", [ 140, 140 ], [ 60, 112 ], [ 228, 113 ], [ 183, 72 ], [ 103, 40 ] ] ], "woodId": "wood_birch", "saplingId": "sapling_birch", "fruits": [] } }, "block": { "log_birch": { "textureData": "stem.png", "color": [ 225, 225, 220 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 550, "treeId": "birch", "soundGroupId": "wood", "particleColor": [ 255, 233, 233, 233 ] } } } ================================================ FILE: trees/blue_mushroom/blue_mushroom.json ================================================ { "tree": { "blue_mushroom": { "length": 3, "baseTiles": [ "blue_mushroom_stem", "blue_mushroom_dirt" ], "leafs": [], "branches": [], "crowns": [ [ "crown.png" ], [ "crown.png" ], [ "crown.png" ] ], "saplingId": "blue_mushroom", "fruits": [ "glowstone_dust" ] } }, "block": { "log_blue_mushroom": { "textureData": "stem.png", "color": [ 150, 130, 77 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 600, "treeId": "blue_mushroom", "soundGroupId": "wood", "particleColor": [ 255, 100, 120, 40 ], "isLighting": true, "lightColor": [ 16, 0, 0, 8 ], "lightX": 0, "lightY": 0, "lightWi": 2, "lightHi": 2 } } } ================================================ FILE: trees/cactus/cactus.json ================================================ { "tree": { "cactus": { "length": 4, "baseTiles": [ "sand", "sandstone" ], "leafs": [], "branches": [ [ "branch.png" ], [ "branch_2.png" ], [ "branch_3.png" ] ], "crowns": [ [ "crown.png" ], [ "crown_2.png" ], [ "crown_3.png" ] ], "woodId": "sapling_cactus", "saplingId": "sapling_cactus", "fruits": [] } }, "block": { "log_cactus": { "textureData": "stem.png", "color": [ 150, 120, 40 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 650, "treeId": "cactus", "soundGroupId": "wood", "particleColor": [ 255, 166, 233, 166 ] } } } ================================================ FILE: trees/dark_oak/dark_oak.json ================================================ { "tree": { "dark_oak": { "length": 5, "baseTiles": [ "dirt", "coarse_dirt", "flesh_dirt" ], "leafs": [ "leaf.png", "leaf_2.png", "leaf_3.png", "leaf_4.png", "leaf_5.png", "leaf_6.png" ], "branches": [ [ "branch.png", [ 68, 136 ], [ 88, 118 ], [ 211, 112 ] ], [ "branch_2.png", [ 51, 101 ], [ 104, 113 ], [ 226, 131 ], [ 180, 80 ] ], [ "branch_3.png", [ 59, 118 ], [ 84, 100 ], [ 228, 112 ], [ 206, 83 ] ] ], "crowns": [ [ "crown.png", [ 74, 146 ], [ 80, 130 ], [ 100, 100 ], [ 193, 84 ], [ 156, 146 ] ], [ "crown_2.png", [ 120, 138 ], [ 188, 116 ], [ 68, 96 ], [ 216, 80 ], [ 136, 58 ] ], [ "crown_3.png", [ 140, 140 ], [ 60, 112 ], [ 228, 113 ], [ 183, 72 ], [ 103, 40 ] ] ], "woodId": "wood_dark_oak", "saplingId": "sapling_dark_oak", "fruits": [ "apple" ] } }, "block": { "log_dark_oak": { "textureData": "stem.png", "color": [ 78, 61, 33 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 700, "treeId": "dark_oak", "soundGroupId": "wood", "particleColor": [ 255, 50, 40, 20 ] } } } ================================================ FILE: trees/jungle/jungle.json ================================================ { "tree": { "jungle": { "length": 13, "baseTiles": [ "dirt", "coarse_dirt" ], "leafs": [ "leaf.png", "leaf_2.png", "leaf_3.png", "leaf_4.png", "leaf_5.png", "leaf_6.png" ], "branches": [ [ "branch.png", [ 68, 136 ], [ 88, 118 ], [ 211, 112 ] ], [ "branch_2.png", [ 51, 101 ], [ 104, 113 ], [ 226, 131 ], [ 180, 80 ] ], [ "branch_3.png", [ 59, 118 ], [ 84, 100 ], [ 228, 112 ], [ 206, 83 ] ] ], "crowns": [ [ "crown.png", [ 74, 146 ], [ 80, 130 ], [ 100, 100 ], [ 193, 84 ], [ 156, 146 ] ], [ "crown_2.png", [ 120, 138 ], [ 188, 116 ], [ 68, 96 ], [ 216, 80 ], [ 136, 58 ] ], [ "crown_3.png", [ 140, 140 ], [ 60, 112 ], [ 228, 113 ], [ 183, 72 ], [ 103, 40 ] ] ], "woodId": "wood_jungle", "saplingId": "sapling_jungle", "fruits": [ "cocoa_bean" ] } }, "block": { "log_jungle": { "textureData": "stem.png", "color": [ 102, 66, 55 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 660, "treeId": "jungle", "soundGroupId": "wood", "particleColor": [ 255, 130, 100, 80 ] } } } ================================================ FILE: trees/oak/oak.json ================================================ { "tree": { "oak": { "length": 7, "baseTiles": [ "dirt", "coarse_dirt" ], "leafs": [ "leaf.png", "leaf_2.png", "leaf_3.png", "leaf_4.png", "leaf_5.png", "leaf_6.png" ], "branches": [ [ "branch.png", [ 68, 136 ], [ 88, 118 ], [ 211, 112 ] ], [ "branch_2.png", [ 51, 101 ], [ 104, 113 ], [ 226, 131 ], [ 180, 80 ] ], [ "branch_3.png", [ 59, 118 ], [ 84, 100 ], [ 228, 112 ], [ 206, 83 ] ] ], "crowns": [ [ "crown.png", [ 74, 146 ], [ 80, 130 ], [ 100, 100 ], [ 193, 84 ], [ 156, 146 ] ], [ "crown_2.png", [ 120, 138 ], [ 188, 116 ], [ 68, 96 ], [ 216, 80 ], [ 136, 58 ] ], [ "crown_3.png", [ 140, 140 ], [ 60, 112 ], [ 228, 113 ], [ 183, 72 ], [ 103, 40 ] ] ], "woodId": "wood_oak", "saplingId": "sapling_oak", "fruits": [ "apple" ] } }, "block": { "log_oak": { "textureData": "stem.png", "color": [ 110, 100, 48 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 600, "treeId": "oak", "soundGroupId": "wood", "particleColor": [ 255, 100, 100, 40 ] } } } ================================================ FILE: trees/palm/palm.json ================================================ { "tree": { "palm": { "length": 10, "baseTiles": [ "sand" ], "leafs": [], "branches": [], "crowns": [ [ "crown.png" ], [ "crown_2.png" ], [ "crown_3.png" ] ], "woodId": "wood_palm", "saplingId": "sapling_palm", "fruits": [] } }, "block": { "log_palm": { "textureData": "stem.png", "color": [ 150, 130, 77 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 600, "treeId": "palm", "soundGroupId": "wood", "particleColor": [ 255, 100, 120, 40 ] } } } ================================================ FILE: trees/spruce/spruce.json ================================================ { "tree": { "spruce": { "length": 10, "baseTiles": [ "dirt", "coarse_dirt", "snow", "snow_soft" ], "leafs": [ "leaf.png", "leaf_2.png", "leaf_3.png", "leaf_4.png", "leaf_5.png", "leaf_6.png" ], "branches": [ [ "branch.png", [ 68, 136 ], [ 88, 118 ], [ 211, 112 ] ], [ "branch_2.png", [ 51, 101 ], [ 104, 113 ], [ 226, 131 ], [ 180, 80 ] ], [ "branch_3.png", [ 59, 118 ], [ 84, 100 ], [ 228, 112 ], [ 206, 83 ] ] ], "crowns": [ [ "crown.png", [ 74, 146 ], [ 80, 130 ], [ 100, 100 ], [ 193, 84 ], [ 156, 146 ] ], [ "crown_2.png", [ 120, 138 ], [ 188, 116 ], [ 68, 96 ], [ 216, 80 ], [ 136, 58 ] ], [ "crown_3.png", [ 140, 140 ], [ 60, 112 ], [ 228, 113 ], [ 183, 72 ], [ 103, 40 ] ] ], "woodId": "wood_spruce", "saplingId": "sapling_spruce", "fruits": [] } }, "block": { "log_spruce": { "textureData": "stem.png", "color": [ 80, 60, 40 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 630, "treeId": "spruce", "soundGroupId": "wood", "particleColor": [ 255, 80, 60, 40 ] } } } ================================================ FILE: trees/tainted/tainted.json ================================================ { "tree": { "tainted": { "length": 6, "baseTiles": [ "tainted_dirt" ], "leafs": [ "leaf.png", "leaf_2.png", "leaf_3.png", "leaf_4.png", "leaf_5.png", "leaf_6.png" ], "branches": [ [ "branch.png", [ 68, 136 ], [ 88, 118 ], [ 211, 112 ] ], [ "branch_2.png", [ 51, 101 ], [ 104, 113 ], [ 226, 131 ], [ 180, 80 ] ], [ "branch_3.png", [ 59, 118 ], [ 84, 100 ], [ 228, 112 ], [ 206, 83 ] ] ], "crowns": [ [ "crown.png", [ 74, 146 ], [ 80, 130 ], [ 100, 100 ], [ 193, 84 ], [ 156, 146 ] ], [ "crown_2.png", [ 120, 138 ], [ 188, 116 ], [ 68, 96 ], [ 216, 80 ], [ 136, 58 ] ], [ "crown_3.png", [ 140, 140 ], [ 60, 112 ], [ 228, 113 ], [ 183, 72 ], [ 103, 40 ] ] ], "woodId": "wood_tainted", "saplingId": "sapling_tainted", "fruits": [] } }, "block": { "log_tainted": { "textureData": "stem.png", "color": [ 74, 41, 107 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 600, "treeId": "tainted", "soundGroupId": "wood", "particleColor": [ 255, 100, 50, 130 ] } } } ================================================ FILE: trees/volcano_oak/volcano_oak.json ================================================ { "tree": { "volcano_oak": { "length": 2, "baseTiles": [ "volcano_dirt", "volcano_stone", "netherrack", "soul_sand", "volcano_burn_stone" ], "leafs": [], "branches": [ [ "branch.png" ], [ "branch_2.png" ], [ "branch_3.png" ] ], "crowns": [ [ "crown.png" ], [ "crown_2.png" ], [ "crown_3.png" ] ], "woodId": "wood_volcano", "saplingId": "sapling_volcano", "fruits": [] } }, "block": { "log_volcano_oak": { "textureData": "stem.png", "color": [ 200, 0, 0 ], "subGroup": "LOG", "placeCheck": "PLACE_TREE_CHECK", "toolType": "AXE", "mineGrade": "GRASS", "hardness": 600, "isLighting": true, "lightColor": [ 16, 12, 0, 0 ], "lightX": 0, "lightY": 0, "lightWi": 2, "lightHi": 2, "treeId": "volcano_oak", "soundGroupId": "wood", "particleColor": [ 255, 200, 0, 0 ] } } } ================================================ FILE: ui/ContainerHelper.lua ================================================ local ContainerHelper = class("ContainerHelper") ---ContainerServerAddBackpack ---@param player Player ---@param container Container function ContainerHelper.ContainerServerAddBackpack(player, container) for i = 1, 50 do -- 0-49 inventory container:AddSlotToContainer(player.backpackInventory, i - 1) end end ---InInteractDistance ---@param player Player ---@param xi int ---@param yi int function ContainerHelper.InInteractDistance(player, xi, yi) return player:GetDistance(xi * 16 + 8, yi * 16 + 8) < 200 end ---ContainerClientInitSlots ---@param container Container ---@param tempSlots Inventory function ContainerHelper.ContainerClientInitSlots(container, tempSlots) local maxSlots = tempSlots.slotCount for i = 1, maxSlots do container:AddSlotToContainer(tempSlots, i - 1, true) end end ---CloseSendBackItems ---@param playerIndex int ---@param xi int ---@param yi int ---@param tempSlots Inventory ---@param slotIndices int[] function ContainerHelper.CloseSendBackItems(playerIndex, xi, yi, tempSlots, slotIndices) if PlayerUtils.IsAlive(playerIndex) then local player = PlayerUtils.Get(playerIndex) local inventory = player.backpackInventory for _, i in ipairs(slotIndices) do local slot = tempSlots:GetSlot(i) if slot.hasStack then -- the input item is exist, send back to player's inventory local outStack = inventory:AddItemStack(slot:GetStack()) if outStack:Valid() then player:DropItem(outStack) end slot:ClearStack() end end else -- the player is offline or unavailable, drop directly for _, i in ipairs(slotIndices) do local slot = tempSlots:GetSlot(i) if slot.hasStack then ItemUtils.CreateDrop(slot:GetStack(), xi * 16 + 8, yi * 16 + 8) slot:ClearStack() end end end end return ContainerHelper ================================================ FILE: ui/DeathUI.lua ================================================ ---@class TC.DeathUI:TC.UIWindow local DeathUI = class("DeathUI", require("UIWindow")) local Locale = require("languages.Locale") function DeathUI:__init() DeathUI.super.__init(self, require("UIDesign").getDeathUI()) self:initUpdateFunc({ self._onUpdate, self }, 60) self._lbCountDown = UIText.cast(self.root:getChild("panel.lb_title_2")) self._cd = 11 self:_onUpdate() end function DeathUI:_onUpdate() if ClientState.current ~= ClientState.Gaming then self:closeWindow() -- tried fix stick DeathUI by suddenly close UIWindow end if self._cd > 1 then self._cd = self._cd - 1 end self._lbCountDown.text = string.format(Locale.RESPAWNING, self._cd) end function DeathUI:closeWindow() DeathUI.super.closeWindow(self) end return DeathUI ================================================ FILE: ui/GuiID.lua ================================================ local GuiID = { Backpack = 1, Smelt = 2, Brewing = 3, Chest30 = 4, Shooter9 = 5, Advancement = 6, Enchantment = 7, EnderChest30 = 8, Craft3x = 9, Repair = 10, } return GuiID ================================================ FILE: ui/GuiLoader.lua ================================================ local GuiLoader = class("GUILoader") local proxiesList = require("GuiLoaderProxy") local serverProxies, clientProxies = proxiesList[1], proxiesList[2] function GuiLoader:GetServerGuiElement(id, player, xi, yi) local func = serverProxies[id] if func then return func(player, xi, yi) end return nil end function GuiLoader:GetClientGuiElement(id, player, xi, yi) local func = clientProxies[id] if func then return func(player, xi, yi) end return nil end return GuiLoader ================================================ FILE: ui/GuiLoaderProxy.lua ================================================ local GuiID = require("GuiID") local serverProxies = { [GuiID.Backpack] = function(player, _, _) return require("backpack.BackpackContainerServer").new(player) end, [GuiID.Smelt] = function(player, xi, yi) return require("smelt.SmeltContainerServer").new(player, xi, yi) end, [GuiID.Brewing] = function(player, xi, yi) return require("brewing.BrewingContainerServer").new(player, xi, yi) end, [GuiID.Chest30] = function(player, xi, yi) return require("chest.Chest30ContainerServer").new(player, xi, yi) end, [GuiID.Shooter9] = function(player, xi, yi) return require("shooter.Shooter9ContainerServer").new(player, xi, yi) end, [GuiID.Enchantment] = function(player, xi, yi) return require("enchant.EnchantContainerServer").new(player, xi, yi) end, [GuiID.EnderChest30] = function(player, xi, yi) return require("chest.EnderChest30ContainerServer").new(player, xi, yi) end, [GuiID.Craft3x] = function(player, xi, yi) return require("craft3x.Craft3xContainerServer").new(player, xi, yi) end, [GuiID.Repair] = function(player, xi, yi) return require("repair.RepairContainerServer").new(player, xi, yi) end, } local clientProxies = { [GuiID.Backpack] = function(player, _, _) local BackpackContainerClient = require("backpack.BackpackContainerClient") local BackpackUI = require("backpack.BackpackUI") return BackpackUI.new(BackpackContainerClient.new(player)) end, [GuiID.Smelt] = function(player, xi, yi) local SmeltContainerClient = require("smelt.SmeltContainerClient") local SmeltUI = require("smelt.SmeltUI") return SmeltUI.new(SmeltContainerClient.new(player, xi, yi)) end, [GuiID.Brewing] = function(player, xi, yi) local BrewingContainerClient = require("brewing.BrewingContainerClient") local BrewingUI = require("brewing.BrewingUI") return BrewingUI.new(BrewingContainerClient.new(player, xi, yi)) end, [GuiID.Chest30] = function(player, xi, yi) local Chest30ContainerClient = require("chest.Chest30ContainerClient") local Chest30UI = require("chest.Chest30UI") return Chest30UI.new(Chest30ContainerClient.new(player, xi, yi)) end, [GuiID.Shooter9] = function(player, xi, yi) local Shooter9ContainerClient = require("shooter.Shooter9ContainerClient") local Shooter9UI = require("shooter.Shooter9UI") return Shooter9UI.new(Shooter9ContainerClient.new(player, xi, yi)) end, [GuiID.Advancement] = function(player, xi, yi) local AdvancementContainerClient = require("advancement.AdvancementContainerClient") local AdvancementUI = require("advancement.AdvancementUI") return AdvancementUI.new(AdvancementContainerClient.new(player)) end, [GuiID.Enchantment] = function(player, xi, yi) local EnchantContainerClient = require("enchant.EnchantContainerClient") local EnchantUI = require("enchant.EnchantUI") return EnchantUI.new(EnchantContainerClient.new(player, xi, yi)) end, [GuiID.EnderChest30] = function(player, _, _) local Chest30ContainerClient = require("chest.Chest30ContainerClient") local EnderChest30UI = require("chest.EnderChest30UI") return EnderChest30UI.new(Chest30ContainerClient.new(player)) end, [GuiID.Craft3x] = function(player, _, _) local Craft3xContainerClient = require("craft3x.Craft3xContainerClient") local Craft3xUI = require("craft3x.Craft3xUI") return Craft3xUI.new(Craft3xContainerClient.new(player)) end, [GuiID.Repair] = function(player, xi, yi) local RepairContainerClient = require("repair.RepairContainerClient") local RepairUI = require("repair.RepairUI") return RepairUI.new(RepairContainerClient.new(player, xi, yi)) end, } return { serverProxies, clientProxies } ================================================ FILE: ui/HotkeyUIHelper.lua ================================================ ---@class TC.HotkeyUIHelper local HotkeyUIHelper = class("HotkeyUIHelper") local InputControl = require("client.InputControl") function HotkeyUIHelper:__init(mod, guiID, data) self._mod = mod self._guiID = guiID self._closeHotkey = Input.keyboard:getHotKeys(Keys.Escape):addListener({ HotkeyUIHelper._closeMe, self }) self._bpCloseKey = InputControl.getInstance().keyMap.Backpack self._closeHotkeyBp = Input.keyboard:getHotKeys(self._bpCloseKey):addListener({ HotkeyUIHelper._closeMe, self }) end function HotkeyUIHelper:destroy() if self._closeHotkey then Input.keyboard:getHotKeys(Keys.Escape):removeListener(self._closeHotkey) self._closeHotkey = nil end if self._closeHotkeyBp then Input.keyboard:getHotKeys(self._bpCloseKey):removeListener(self._closeHotkeyBp) self._closeHotkeyBp = nil end end function HotkeyUIHelper:_closeMe() local player = PlayerUtils.GetCurrentClientPlayer() if player then player:CloseGui(self._mod, self._guiID) end end return HotkeyUIHelper ================================================ FILE: ui/InfoPopupUI.lua ================================================ ---@class TC.InfoPopupUI:TC.UIWindow local InfoPopupUI = class("InfoPopupUI", require("UIWindow")) function InfoPopupUI:__init(content, okCallback, cancelCallback, largeWindow) InfoPopupUI.super.__init(self, require("UIDesign").getInfoPopupUI()) self._okCallback = okCallback self._cancelCallback = cancelCallback self._content = content self._largeWindow = largeWindow self:initContent() end function InfoPopupUI:setInfo(info) UIText.cast(self.root:getChild("layer.panel_info.lb_info")).text = info end function InfoPopupUI:initContent() local layer = self.root:getChild("layer") if self._largeWindow then layer.size = Size.new(1000, 500) layer:applyMargin() end layer:getChild("btn_back"):addTouchUpListener({ self._onBackClicked, self }) layer:getChild("btn_ok"):addTouchUpListener({ self._onOkClicked, self }) self:setInfo(self._content) end function InfoPopupUI:_onBackClicked() self.manager:playClickSound() self:closeWindow() if self._cancelCallback then self._cancelCallback() end end function InfoPopupUI:_onOkClicked() if self._okCallback then self._okCallback() end self:_onBackClicked() end function InfoPopupUI:closeWindow() InfoPopupUI.super.closeWindow(self) end return InfoPopupUI ================================================ FILE: ui/LanguageUI.lua ================================================ ---@class TC.LanguageUI:TC.UIWindow local LanguageUI = class("LanguageUI", require("UIWindow")) local UIUtil = require("UIUtil") function LanguageUI:__init() LanguageUI.super.__init(self, require("UIDesign").getLanguageUI()) self.indexSelected = 1 self.itemNodes = {} self:initContent() end function LanguageUI:initContent() local panel_list = self.root:getChild("layer.panel_list") local panel_item = panel_list:getChild("panel_item") self.itemSize = Size.new(panel_item.width / 1, panel_item.height) UIUtil.setTable(panel_list, self, true, 1) self:updateSelection() self.root:getChild("layer.btn_ok"):addTouchUpListener({ function(self) local StartUI = require("StartUI") self:closeWindow() StartUI.new() end, self } ) end function LanguageUI:_getTableElementCount() return 5 end function LanguageUI:_getTableElementSize() return self.itemSize end ---_setTableElement ---@param node UINode ---@param index number function LanguageUI:_setTableElement(node, index) node.tag = index local lb_text = UIText.cast(node:getChild("lb_locale")) lb_text.text = lb_text.text .. tostring(index) node:addTouchUpListener({ self._onElementClicked, self }) if index == 1 then lb_text.text = "简体中文" end table.insert(self.itemNodes, node) end ---_onElementClicked ---@param node UINode function LanguageUI:_onElementClicked(node) local index = node.tag self.indexSelected = index self:updateSelection() end function LanguageUI:updateSelection() ---@param node UINode for _, node in pairs(self.itemNodes) do if node.tag == self.indexSelected then node:getChild("img_selected").visible = true else node:getChild("img_selected").visible = false end end end function LanguageUI:closeWindow() LanguageUI.super.closeWindow(self) end return LanguageUI ================================================ FILE: ui/ModListUI.lua ================================================ ---@class TC.ModListUI:TC.UIWindow local ModListUI = class("ModListUI", require("UIWindow")) local UIUtil = require("UIUtil") local Locale = require("languages.Locale") function ModListUI:__init() ModListUI.super.__init(self, require("UIDesign").getModListUI()) self.indexSelected = 1 self.itemNodes = {} self.modInfoList = {} self._panelList = self.root:getChild("layer.panel_list") self._panelItem = self._panelList:getChild("panel_item") self._svInfo = UIScrollView.cast(self.root:getChild("layer.info_list")) self._panelInfo1 = self._svInfo:getChild("panel_info_1") self._panelInfo2 = self._svInfo:getChild("panel_info_2") self._panelInfoWeb = self._svInfo:getChild("panel_info_web") self._btnWeb1 = self._panelInfoWeb:getChild("btn_web_1") self._btnWeb2 = self._panelInfoWeb:getChild("btn_web_2") self._lbVersion = UIText.cast(self._panelInfo1:getChild("panel_version.lb_version")) self._lbAuthors = UIText.cast(self._panelInfo1:getChild("panel_author.lb_author")) self._lbDesc = UIText.cast(self._panelInfo2:getChild("lb_des")) self._lbListTitle = UIText.cast(self.root:getChild("layer.lb_list_title")) self:initContent() end function ModListUI:initContent() self:_initInfo() self.root:getChild("layer.btn_back"):addTouchUpListener({ function(self) self.manager:playClickSound() local StartUI = require("StartUI") self:closeWindow() StartUI.new() end, self } ) self.root:getChild("layer.btn_mod_folder"):addTouchUpListener({ self._onOpenModsFolderClicked, self } ) self._btnWeb1:addTouchUpListener({ self._onURLClicked, self, 1 }) self._btnWeb2:addTouchUpListener({ self._onURLClicked, self, 2 }) self.itemSize = Size.new(self._panelItem.width, self._panelItem.height) UIUtil.setTable(self._panelList, self, true, 1) self._lbListTitle.text = string.format(Locale.ALL_MOD_LOADED, #self.modInfoList) self:postInitContent() self:updateSelection() end function ModListUI:_onOpenModsFolderClicked() self.manager:playClickSound() if App.isPC then File.openFolderWindow(Path.join(App.persistentDataPath, "mods")) else require("ui.InfoPopupUI").new(Locale.MOD_FOLDER_UNSUPPORTED) end end function ModListUI:_initInfo() -- load all mod info from package.json local UISpritePool = require("UISpritePool") ---@param mod Mod for _, mod in each(Mod.modList) do local packageJsonPath = Path.join(mod.assetRootPath, "package.json") local jsonStr = AssetManager.readAsString(packageJsonPath) local info = JsonUtil.fromJson(jsonStr) if UISpritePool.getInstance():has(mod.modId .. ":__icon") then info._texName = mod.modId .. ":__icon" end table.insert(self.modInfoList, info) end end function ModListUI:_getTableElementCount() return #self.modInfoList end function ModListUI:_getTableElementSize() return self.itemSize end ---_setTableElement ---@param node UINode ---@param index number function ModListUI:_setTableElement(node, index) node.tag = index local info = self.modInfoList[index] local lbCaption = UIText.cast(node:getChild("lb_mod_name")) local lbTips = UIText.cast(node:getChild("lb_mod_tip")) local iconImg = UIImage.cast(node:getChild("img_mod_pic")) if info.displayName then lbCaption.text = info.displayName else lbCaption.text = "Untitled" end if info.tips then lbTips.text = info.tips else lbTips.text = "" end if info._texName ~= nil then local UISpritePool = require("UISpritePool") iconImg.sprite = UISpritePool.getInstance():get(info._texName) end node:addTouchUpListener({ self._onElementClicked, self }) table.insert(self.itemNodes, node) end ---_onElementClicked ---@param node UINode ---@param _ Touch function ModListUI:_onElementClicked(node) local index = node.tag if self.indexSelected ~= index then self.indexSelected = index self:updateSelection() self.manager:playClickSound() end end function ModListUI:updateSelection() ---@param node UINode for _, node in pairs(self.itemNodes) do if node.tag == self.indexSelected then node:getChild("img_selected").visible = true else node:getChild("img_selected").visible = false end end local info = self.modInfoList[self.indexSelected] if info.version then self._lbVersion.text = info.version else self._lbVersion.text = "0.0.0.0" end if info.authors then local str = "" local flag = false for _, authorName in ipairs(info.authors) do if flag then str = str .. ", " end flag = true str = str .. authorName end self._lbAuthors.text = str else self._lbAuthors.text = "..." end self._panelInfoWeb.visible = false if info.websites then self._panelInfoWeb.visible = true self._btnWeb1.visible = false self._btnWeb2.visible = false for i, wbData in ipairs(info.websites) do local btn if i == 1 then btn = self._btnWeb1 elseif i == 2 then btn = self._btnWeb2 else break end btn.visible = true local originalText = wbData.title if originalText == "Github" then originalText = Locale.WEB_SOURCE_GITHUB elseif originalText == "Homepage" then originalText = Locale.WEB_HOME end UIText.cast(btn:getChild("lb_caption")).text = originalText end end self._lbDesc.autoAdaptSize = true self._lbDesc.preferredWidth = self._panelInfo2.width - 32 if info.description then self._lbDesc.text = info.description else self._lbDesc.text = "" end self._panelInfo2.height = self._lbDesc.positionY + self._lbDesc.height + 16 local posY = self._panelInfo1.positionY + self._panelInfo1.height + 16 if self._panelInfoWeb.visible then self._panelInfoWeb.positionY = posY posY = posY + self._panelInfoWeb.height + 16 end self._panelInfo2.positionY = posY self._svInfo:ScrollToTop() local tmpSize = Size.new(self._svInfo.viewSize.width, self._panelInfo2.positionY + self._panelInfo2.height) tmpSize.height = math.max(tmpSize.height, self._svInfo.height) self._svInfo.viewSize = tmpSize self._svInfo:ScrollToTop() end function ModListUI:_onURLClicked(index) self.manager:playClickSound() local info = self.modInfoList[self.indexSelected] if info.websites then if index <= #info.websites then local url = info.websites[index].url local MiscHelper = require("util.MiscHelper") MiscHelper.OpenURL(url) end end end function ModListUI:closeWindow() ModListUI.super.closeWindow(self) end return ModListUI ================================================ FILE: ui/MouseItemData.lua ================================================ ---@class TC.MouseItemData local MouseItemData = class("MouseItemData") local SettingsData = require("settings.SettingsData") local s_instance ---@return TC.MouseItemData function MouseItemData.getInstance() if s_instance == nil then s_instance = MouseItemData.new() end return s_instance end function MouseItemData:__init() self.inventory = Inventory.new(1) self.slot = nil ---@type Slot self.touchingPosition = Vector2.new() self.originSlot = nil ---@type Slot self.originContainer = nil ---@type Container self.originSlotIndex = -1 self.pickingOneByOne = false self.isPcCurrentPicking = false self.pcSelectingSlots = {} self.pcSelectingContainerAndSlotIndices = {} self.pcIsAverageMode = false self._pickingTicks = 0 self._pickingStep = 30 self._pickingSpeed = 4 self._firstPicking = false self._ticks = 0 self._iconScale = Vector2.new(1, 1) self._displayOffsetX = 64 self._keepingTip = false self._itemInfoTable = {} end ---showTip ---@param itemStack ItemStack ---@param touchingPosition Vector2 ---@param keepTicks function MouseItemData:showTip(itemStack, touchingPosition, keepTicks) self._itemInfoTable = {} local item = itemStack:GetItem() local showDebugTip = true local StringUtil = require("util.StringUtil") local itemName = LangUtils.ItemName(item.id) if itemName == "" then itemName = itemStack:GetItem().idName end table.insert(self._itemInfoTable, itemName) local enchantments = item.enchantments for i = 0, itemStack.enchantmentCount - 1 do local enchantment = itemStack:GetEnchantmentByIndex(i) table.insert(self._itemInfoTable, string.format("%s %s", LangUtils.EnchantmentName(enchantment.id), StringUtil.NumberToRoman(enchantment.level))) end if #enchantments > 0 then table.insert(self._itemInfoTable, " ") end local buffs = item.buffs for _, buff in ipairs(buffs) do table.insert(self._itemInfoTable, string.format("%s %s", LangUtils.BuffName(buff.id), StringUtil.TicksToTimeFormat(buff.time))) end local intro = LangUtils.ItemIntroduction(item.id) if intro ~= "" then table.insert(self._itemInfoTable, string.format("%s", intro)) end if item.maxDurable > 0 then table.insert(self._itemInfoTable, string.format("耐久 %d/%d", itemStack.durable, item.maxDurable)) end if item.baseAttack.attack > 0 then table.insert(self._itemInfoTable, string.format("攻击 +%d", item.baseAttack.attack)) end if item.baseAttack.knockBack > 0 then table.insert(self._itemInfoTable, string.format("击退 +%d", item.baseAttack.knockBack)) end if item.baseAttack.crit > 0 then table.insert(self._itemInfoTable, string.format("暴击 +%d", item.baseAttack.crit)) end if item.defense > 0 then table.insert(self._itemInfoTable, string.format("防御 +%d", item.defense)) end if item.noConsumeChance > 0 then table.insert(self._itemInfoTable, string.format("弹药节省 +%d%%", math.ceil(item.noConsumeChance * 100))) end if item.consumeMana > 0 then table.insert(self._itemInfoTable, string.format("魔耗 %d", item.consumeMana)) end if showDebugTip then table.insert(self._itemInfoTable, string.format("%s", item.idName)) end local modName = item.mod.displayName if modName ~= "" then table.insert(self._itemInfoTable, string.format("%s", modName)) end local TipUI = require("TipUI") if TipUI.isShowing() then TipUI.changeNewContent(self._itemInfoTable) TipUI.resetKeepTime() else TipUI.generate(self._itemInfoTable, keepTicks, 1) end TipUI.adaptPosition(touchingPosition) self._keepingTip = true end function MouseItemData:closeTip() local TipUI = require("TipUI") TipUI.close() self:stopKeepingTip() end function MouseItemData:stopKeepingTip() self._keepingTip = false end function MouseItemData:startDragging(originContainer, originSlotIndex) self.originSlot = originContainer:GetSlot(originSlotIndex) self.originContainer = originContainer self.originSlotIndex = originSlotIndex end function MouseItemData:stopDragging() self.originSlot = nil self.originContainer = nil self.originSlotIndex = -1 end function MouseItemData:fixDisplayOffset() if SettingsData.isMobileOperation then self._displayOffsetX = 64 * ((self.touchingPosition.x > GameWindow.width * 0.5) and -1.0 or 1.0) else self._displayOffsetX = 64 end end function MouseItemData:updateDisplayOffset() if SettingsData.isMobileOperation then local moveSpeed = 4 self._displayOffsetX = math.min(math.max( self._displayOffsetX + moveSpeed * ((self.touchingPosition.x > GameWindow.width * 0.5) and -1 or 1), -64), 64) else self:fixDisplayOffset() end end function MouseItemData:startPicking() self.pickingOneByOne = true self._pickingTicks = 0 self._pickingStep = 12 self._pickingSpeed = 2 self._firstPicking = true self:fixDisplayOffset() end function MouseItemData:stopPicking() if self.pickingOneByOne then self.pickingOneByOne = false end end function MouseItemData:update() assert(ClientState.current == ClientState.Gaming, "current client state must be Gaming!") if not SettingsData.isMobileOperation then self.touchingPosition = Input.mouse.position end local TipUI = require("TipUI") if TipUI.isShowing() and TipUI.getShowTag() == 1 then TipUI.adaptPosition(self.touchingPosition) if self._keepingTip then TipUI.resetKeepTime() end end if self.slot == nil then local player = PlayerUtils.GetCurrentClientPlayer() self.slot = player.mouseInventory:GetSlot(0) ---@type TC.GPlayer local globalPlayer = player:GetGlobalPlayer("tc:GPlayer") --print(globalPlayer.sayWord) end local mouseSlot = self.slot if mouseSlot.hasStack then if self.pickingOneByOne and self.originSlot ~= nil then if self.originSlot.hasStack then self._pickingTicks = self._pickingTicks + 1 local checkTime = self._pickingStep * (self._firstPicking and 2 or 1) if self._pickingTicks >= checkTime then self._pickingSpeed = self._pickingSpeed - 1 if self._pickingSpeed <= 0 then self._pickingSpeed = 1 self._pickingStep = math.max(self._pickingStep - 1, 1) end self._pickingTicks = 0 local pickingCount = 1 local merges = mouseSlot:GetStack():GetMergeCount(self.originSlot:GetStack()) if merges > 0 then pickingCount = math.min(merges, pickingCount) mouseSlot:GetStack():SetStackSize(mouseSlot:GetStack().stackSize + pickingCount) self.originSlot:DecrStackSize(pickingCount) SoundUtils.PlaySound(Reg.SoundID("pop")) end end end end local scaleNum = 1.5 + Utils.SinValue(self._ticks, 64) * 0.1 self._iconScale.x = scaleNum self._iconScale.y = scaleNum self:updateDisplayOffset() self._ticks = self._ticks + 1 end end function MouseItemData:render() assert(ClientState.current == ClientState.Gaming, "current client state must be Gaming!") if self.slot.hasStack then Sprite.beginBatch() local stack = self.slot:GetStack() local exData = SpriteExData.new() exData.scaleRate = self._iconScale exData.origin = Vector2.new(16, 16) local pos = self.touchingPosition + Vector2.new(self._displayOffsetX, 48) if self.slot.tag < 0 then local num = require("ui.UISlotOp").getSelectedNum(self.slot) if num > 0 then stack:Render(pos, Color.White, exData) stack:RenderCustomNum(num, pos, Color.Yellow, exData) end else stack:Render(pos, Color.White, exData) stack:RenderNum(pos, Color.Yellow, exData) end Sprite.endBatch() end end return MouseItemData ================================================ FILE: ui/NewPlayerUI.lua ================================================ ---@class TC.NewPlayerUI:TC.UIWindow local NewPlayerUI = class("NewPlayerUI", require("UIWindow")) local PlayerBoneInfo = require("bone2d.PlayerBoneInfo") local UIUtil = require("UIUtil") function NewPlayerUI:__init() NewPlayerUI.super.__init(self, require("UIDesign").getNewPlayerUI()) self._playerBone = nil self._posPanel = self.root:getChild("layer.pos_panel") self._postureIdx = 0 self._skins = {} self._itemSize = nil self._indexSelected = 0 self._accountNameExists = {} self._canGenerateAccount = false self._validName = "" self._validSkinID = 0 self:initContent() end function NewPlayerUI:initContent() local accountNames = File.getAllFiles(Path.join(App.persistentDataPath, "accounts"), ".dat", true, false, false) for _, name in pairs(accountNames) do self._accountNameExists[name] = true end self._validSkinID = 1 self._playerBone = PlayerBoneInfo.createBySkinID(self._validSkinID) self._playerBone.animator:setBool("Standard", false) self._playerBone.animator:setBool("OnGround", true) self._playerBone.joints.flip = true self._posPanel:getPostDrawLayer(0):addListener( { self._onRenderPlayerBone, self }) self:_reloadListData() UIButton.cast(self.root:getChild("layer.btn_female")).selected = true self.root:getChild("layer.btn_ok"):addTouchUpListener({ self.onOkButtonClicked, self }) self.root:getChild("layer.btn_back"):addTouchUpListener({ self.onBackButtonClicked, self }) self.root:getChild("layer.btn_animator"):addTouchUpListener({ self.onPostureButtonClicked, self }) UIInputField.cast(self.root:getChild("layer.panel_name.edit")):addTextChangedListener({ self._onNameChanged, self }) self:initUpdateFunc({ self._onPlayerBoneUpdate, self }) self:initUpdateFunc({ self._onPlayerBoneUpdateInList, self }) self:_checkNameValid("") end function NewPlayerUI:onOkButtonClicked() if self._canGenerateAccount and self._validName ~= "" and self._validSkinID > 0 then local account = Account.new() account.name = self._validName account.skinID = self._validSkinID AccountUtils.Save(account) self.manager:playClickSound() self:closeWindow() require("PlayerListUI").new() end end function NewPlayerUI:_onNameChanged(_, text) self:_checkNameValid(text) end ---_checkNameValid ---@param text string function NewPlayerUI:_checkNameValid(text) local checker = require("util.ValidChecker") local tipText = "" self._canGenerateAccount = false local len = utf8string.len(text) if len == 0 then tipText = "请输入玩家名称" elseif not (len >= 1 and len <= 20) then tipText = "玩家名称不能超过20个字符" elseif not checker.checkValidFileName(text) then tipText = "玩家名称格式不正确" elseif self._accountNameExists[text] then tipText = "名称已存在,请换一个" else tipText = "玩家名称可用!" self._canGenerateAccount = true self._validName = text end UIText.cast(self.root:getChild("layer.panel_info.lb_info")).text = tipText local btnColor = Color.Gray if self._canGenerateAccount then btnColor = Color.White end UIText.cast(self.root:getChild("layer.btn_ok.lb_caption")).color = btnColor end function NewPlayerUI:_reloadListData() self._skins = {} for skinID = 1, SkinUtils.maxID do skin = SkinUtils.GetSkin(skinID) local skinTable = { id = skinID, name = skin.name, mod = skin.mod, authors = "", playerBone = PlayerBoneInfo.createBySkinID(skinID) } for i, author in each(skin.authors) do if i == 1 then skinTable.authors = "by " .. author else skinTable.authors = skinTable.authors .. ", " .. author end end skinTable.playerBone.animator:setBool("Standard", true) table.insert(self._skins, skinTable) end self._panelList = UIScrollView.cast(self.root:getChild("layer.panel_list")) local panelItem = self._panelList:getChild("panel_item") self._itemSize = Size.new(panelItem.width, panelItem.height) UIUtil.setTable(self._panelList, self, true, 1) end function NewPlayerUI:_getTableElementCount() return #self._skins end function NewPlayerUI:_getTableElementSize() return self._itemSize end ---_setTableElement ---@param node UINode ---@param index number function NewPlayerUI:_setTableElement(node, index) node.tag = index node:getChild("img_player_icon_holder").isContainer = true node:getChild("img_player_icon_holder.bg"):getPostDrawLayer(0):addListener( { self._onRenderPlayerBoneInList, self, index }) local lbName = UIText.cast(node:getChild("lb_name")) local lbMod = UIText.cast(node:getChild("lb_mod")) local lbAuthor = UIText.cast(node:getChild("lb_author")) lbName.text = self._skins[index].name lbMod.text = self._skins[index].mod.displayName lbAuthor.text = self._skins[index].authors if lbName.text == "Unknown" then lbName.visible = false lbMod.positionY = lbMod.positionY - 8 lbAuthor.positionY = lbAuthor.positionY - 8 else lbName.visible = true end node:addTouchUpListener({ self._onElementClicked, self }) end ---_onElementClicked ---@param node UINode ---@param _ Touch function NewPlayerUI:_onElementClicked(node) local index = node.tag if self._indexSelected ~= index then self.manager:playClickSound() self._indexSelected = index self._validSkinID = self._skins[index].id PlayerBoneInfo.setSkinByID(self._playerBone, self._validSkinID) self:updateSelection() end end function NewPlayerUI:updateSelection() for index = 1, self:_getTableElementCount() do local node = self._panelList:getChildByTag(index) local show = false if node.tag == self._indexSelected then show = true end node:getChild("img_selected").visible = show end end function NewPlayerUI:_onPlayerBoneUpdate() local screenPos = self.manager:getScreenPosition(self._posPanel) self._playerBone.joints.position = screenPos + Vector2.new(100, 200) self._playerBone.joints.scale = Vector2.new(4, 4) self._playerBone:update() end function NewPlayerUI:_onRenderPlayerBoneInList(index) local playerBone = self._skins[index].playerBone playerBone.joints:render() end function NewPlayerUI:_onPlayerBoneUpdateInList() for index = 1, #self._skins do local elementNode = UIUtil.getTableElement(self._panelList, index) local screenPos = self.manager:getScreenPosition(elementNode) ---@type JointBody2D local playerBone = self._skins[index].playerBone playerBone.joints.position = screenPos + Vector2.new(40, 104) playerBone.joints.scale = Vector2.new(1.5, 1.5) playerBone:update() end end function NewPlayerUI:_onRenderPlayerBone() self._playerBone.joints:render() end function NewPlayerUI:onBackButtonClicked() local PlayerListUI = require("PlayerListUI") self.manager:playClickSound() self:closeWindow() PlayerListUI.new() end function NewPlayerUI:onPostureButtonClicked() local animator = self._playerBone.animator if self._postureIdx == 0 then animator:setFloat("Speed", 0.5) self._postureIdx = 1 elseif self._postureIdx == 1 then animator:setFloat("Speed", 1) self._postureIdx = 2 elseif self._postureIdx == 2 then animator:setBool("OnGround", false) animator:setFloat("AirSpeed", -1) self._postureIdx = 3 elseif self._postureIdx == 3 then animator:setFloat("AirSpeed", 1) self._postureIdx = 4 elseif self._postureIdx == 4 then animator:setBool("OnGround", true) animator:setFloat("Speed", 0) self._postureIdx = 0 end end function NewPlayerUI:closeWindow() NewPlayerUI.super.closeWindow(self) end return NewPlayerUI ================================================ FILE: ui/NewServerUI.lua ================================================ ---@class TC.NewServerUI:TC.UIWindow local NewServerUI = class("NewServerUI", require("UIWindow")) function NewServerUI:__init() NewServerUI.super.__init(self, require("UIDesign").getNewServerUI()) self:initContent() end function NewServerUI:initContent() self.root:getChild("layer.btn_back"):addTouchUpListener({ function(self) local ServerListUI = require("ServerListUI") self:closeWindow() ServerListUI.new() end, self } ) end function NewServerUI:closeWindow() NewServerUI.super.closeWindow(self) end return NewServerUI ================================================ FILE: ui/NewWorldUI.lua ================================================ ---@class TC.NewWorldUI:TC.UIWindow local NewWorldUI = class("NewWorldUI", require("UIWindow")) function NewWorldUI:__init() NewWorldUI.super.__init(self, require("UIDesign").getNewWorldUI()) self._worldNameExists = {} self._canGenerateWorld = false self._isSSC = false self._gameMode = 0 self._tipMode = 0 self._validName = "" self:initContent() end function NewWorldUI:initContent() local worldNames = File.getAllSubFolders(Path.join(App.persistentDataPath, "worlds")) for _, name in pairs(worldNames) do self._worldNameExists[name] = true end UIText.cast(self.root:getChild("layer.btn_gm.lb_caption")).color = Color.Gray UIInputField.cast(self.root:getChild("layer.panel_name.edit")):addTextChangedListener({ self._onNameChanged, self }) self.root:getChild("layer.btn_ok"):addTouchUpListener({ self.onOkButtonClicked, self }) self.root:getChild("layer.btn_gm"):addTouchUpListener({ self._onGameModeButtonClicked, self }) self.root:getChild("layer.btn_bp"):addTouchUpListener({ self._onSideButtonClicked, self }) self.root:getChild("layer.btn_back"):addTouchUpListener({ self.onCancelClicked, self }) self:_checkNameValid("") end function NewWorldUI:_onNameChanged(_, text) self:_checkNameValid(text) end function NewWorldUI:onCancelClicked() self.manager:playClickSound() self:closeWindow() require("WorldListUI").new() end function NewWorldUI:onOkButtonClicked() if self._canGenerateWorld and self._validName ~= "" then local worldData = WorldData.new() local seedString = UIInputField.cast(self.root:getChild("layer.panel_seed.edit")).text worldData.worldName = self._validName worldData.worldSeed = WorldDataUtils.GenerateSeed(seedString) worldData.clientSideCharacters = not self._isSSC WorldDataUtils.Save(worldData) self.manager:playClickSound() self:closeWindow() require("WorldListUI").new() end end function NewWorldUI:_onGameModeButtonClicked(node) do return end if self._tipMode == 1 then self._gameMode = self._gameMode + 1 if self._gameMode >= 3 then self._gameMode = 0 end end self._tipMode = 1 local title = "" local tipText = "" if self._gameMode == 0 then title = "生存模式" tipText = "冒险,建造,升级!" elseif self._gameMode == 1 then title = "创造模式" tipText = "(非公测内容,正在开发中)" elseif self._gameMode == 2 then title = "冒险模式" tipText = "(非公测内容,正在开发中)" end self.manager:playClickSound() UIText.cast(node:getChild("lb_caption")).text = title UIText.cast(self.root:getChild("layer.panel_info.lb_info")).text = tipText end function NewWorldUI:_onSideButtonClicked(node) if self._tipMode == 2 then self._isSSC = not self._isSSC end self._tipMode = 2 local title local tipText if self._isSSC then title = "强制开荒模式" --tipText = "[SSC Mode] Starts with new character." tipText = "[SSC] 进入世界将强制使用新角色数据." else title = "背包共享模式" tipText = "[CSC] 进入世界共享其他世界数据." end self.manager:playClickSound() UIText.cast(node:getChild("lb_caption")).text = title UIText.cast(self.root:getChild("layer.panel_info.lb_info")).text = tipText end ---_checkNameValid ---@param text string function NewWorldUI:_checkNameValid(text) local checker = require("util.ValidChecker") self._tipMode = 0 local tipText = "" self._canGenerateWorld = false local len = utf8string.len(text) if len == 0 then tipText = "请输入世界名称" elseif not (len >= 1 and len <= 20) then tipText = "世界名称不能超过20个字符" elseif not checker.checkValidFileName(text) then tipText = "世界名称格式不正确" elseif self._worldNameExists[text] then tipText = "名称已存在,请换一个" else tipText = "世界名称可用!" self._canGenerateWorld = true self._validName = text end UIText.cast(self.root:getChild("layer.panel_info.lb_info")).text = tipText local btnColor = Color.Gray if self._canGenerateWorld then btnColor = Color.White end UIText.cast(self.root:getChild("layer.btn_ok.lb_caption")).color = btnColor end function NewWorldUI:closeWindow() NewWorldUI.super.closeWindow(self) end return NewWorldUI ================================================ FILE: ui/OptionUI.lua ================================================ ---@class TC.OptionUI:TC.UIWindow local OptionUI = class("OptionUI", require("UIWindow")) local Locale = require("languages.Locale") local RawHotkeyUIHelper = require("ui.RawHotkeyUIHelper") function OptionUI:__init() OptionUI.super.__init(self, require("UIDesign").getOptionUI(), require("ui.UIDefault").GROUP_GAME_WINDOW) self._hkHelper = RawHotkeyUIHelper.new(self) self:initContent() end function OptionUI:initContent() self.root:getChild("layer.btn_back"):addTouchUpListener({ OptionUI._onBtnBackClicked, self }) self.root:getChild("layer.btn_setting"):addTouchUpListener({ OptionUI._onBtnSettingClicked, self }) self.root:getChild("layer.btn_recipe"):addTouchUpListener({ OptionUI._onBtnRecipeClicked, self }) self.root:getChild("layer.btn_advancement"):addTouchUpListener({ OptionUI._onBtnAdvancementClicked, self }) self.root:getChild("layer.btn_save_and_exit"):addTouchUpListener({ OptionUI._onBtnSaveAndExitClicked, self }) end function OptionUI:_onBtnBackClicked() self:closeWindow() self.manager:playClickSound() end function OptionUI:_onBtnSettingClicked() self:closeWindow() self.manager:playClickSound() require("SettingUI").new(function() OptionUI.new() end) end function OptionUI:_onBtnRecipeClicked() self:closeWindow() self.manager:playClickSound() require("ui.nei.NeiUI").new() end function OptionUI:_onBtnAdvancementClicked() self:closeWindow() self.manager:playClickSound() local player = PlayerUtils.GetCurrentClientPlayer() if not player then return end local GuiID = require("ui.GuiID") if player:IsGuiOpened(Mod.current, GuiID.Advancement) then return end player:OpenGui(Mod.current, GuiID.Advancement, player.centerXi, player.centerYi) end function OptionUI:_onBtnSaveAndExitClicked() self:closeWindow() self.manager:playClickSound() ClientStateManager.SaveAndExitGaming() end function OptionUI:closeWindow() self._hkHelper:destroy() OptionUI.super.closeWindow(self) end return OptionUI ================================================ FILE: ui/PendingUI.lua ================================================ ---@class TC.PendingUI:TC.UIWindow local PendingUI = class("PendingUI", require("UIWindow")) local Locale = require("languages.Locale") local UISpritePool = require("ui.UISpritePool") local ANIMATION_SCALE = 2 function PendingUI:__init() PendingUI.super.__init(self, require("UIDesign").getPendingUI()) self._closeBtn = UIButton.cast(self.root:getChild("layer.btn_back")) self._aniPanel = UIPanel.cast(self.root:getChild("layer.panel_animation")) self._lbTip = UIText.cast(self.root:getChild("layer.lb_tip")) self._aniTexture = nil self._ticks = 0 self._aniFrameIndex = 0 self:initContent() end function PendingUI:initContent() self._aniTexture = UISpritePool.getInstance():get("tc:pending_animation").textureLocation self._closeBtn:addTouchUpListener({ function(self) ClientStateManager.SaveAndExitGaming() self:_jumpTo(require("StartUI")) end, self }) self._closeBtn.visible = false self._lbTip.text = "" if ClientState.current == ClientState.Joining or ClientState.current == ClientState.LoadingWorld then local tod = require("TipsOfTheDay").new() self._lbTip.text = tod:getRandomText() elseif ClientState.current == ClientState.SavingWorld then self._lbTip.text = Locale.PENDING_SAVING elseif ClientState.current == ClientState.LosingConnection then self._lbTip.text = Locale.PENDING_NO_CONNECTION self._closeBtn.visible = true end self._aniPanel:getPostDrawLayer(0):addListener({ PendingUI._renderAnimation, self }) self:initUpdateFunc({ self._onUpdate, self }) end function PendingUI:_onUpdate() self._ticks = self._ticks + 1 self._aniFrameIndex = math.floor(self._ticks / 8) % 4 end function PendingUI:_renderAnimation(node, canvasPos) local pos = node.positionInCanvas + canvasPos + Vector2.new(node.width * 0.5, node.height * 0.5) local rectCut = Rect.new(32 * self._aniFrameIndex, 0, 32, 32) local exData = SpriteExData.new() exData.originX = 16 exData.originY = 16 exData.scaleRateX = ANIMATION_SCALE exData.scaleRateY = ANIMATION_SCALE Sprite.draw(self._aniTexture, pos, rectCut, Color.White, exData, 1.0) end function PendingUI:_jumpTo(WindowClass) self:closeWindow() self.manager:playClickSound() WindowClass.new() end function PendingUI:closeWindow() PendingUI.super.closeWindow(self) end return PendingUI ================================================ FILE: ui/PlayerListUI.lua ================================================ ---@class TC.PlayerListUI:TC.UIWindow local PlayerListUI = class("PlayerListUI", require("UIWindow")) local UIUtil = require("UIUtil") local PlayerBoneInfo = require("bone2d.PlayerBoneInfo") local MenuJoinInfo = require("client.MenuJoinInfo") local Locale = require("languages.Locale") function PlayerListUI:__init() PlayerListUI.super.__init(self, require("UIDesign").getPlayerListUI()) ---@type UIScrollView self._panelList = nil self._accounts = {} self._indexSelected = 0 self._itemSize = nil self:initContent() end function PlayerListUI:initContent() self:initAccountData() self._panelList = UIScrollView.cast(self.root:getChild("layer.panel_list")) local panelItem = self._panelList:getChild("panel_item") self._itemSize = Size.new(panelItem.width, panelItem.height) UIUtil.setTable(self._panelList, self, true, 1) self:updateSelection() self.root:getChild("layer.btn_back"):addTouchUpListener({ self._onBackButtonClicked, self }) self.root:getChild("layer.btn_ok"):addTouchUpListener({ self._onOkButtonClicked, self }) self.root:getChild("layer.btn_create"):addTouchUpListener({ self._onNewButtonClicked, self }) self:initUpdateFunc({ self._onPlayerBoneUpdate, self }) end function PlayerListUI:getAccountLastModifiedTime(name) local filePath = Path.join(App.persistentDataPath, "accounts", name .. ".dat") if File.isPathExist(filePath) then return File.getLastWriteTime(filePath) end local filePathBackup = Path.join(App.persistentDataPath, "accounts", name .. ".dat.bak") return File.getLastWriteTime(filePathBackup) end function PlayerListUI:initAccountData() local accountNames = File.getAllFiles(Path.join(App.persistentDataPath, "accounts"), ".dat", true, false, false) for _, name in pairs(accountNames) do local account = Account.new() if AccountUtils.Load(name, account) then local lastModifiedTime = self:getAccountLastModifiedTime(name) local infoTable = { name = name, skinID = account.skinID, lastModifiedTime = lastModifiedTime, playerBone = PlayerBoneInfo.createBySkinID(account.skinID) } infoTable.playerBone.animator:setBool("Standard", true) table.insert(self._accounts, infoTable) end end table.sort(self._accounts, function(element1, element2) return element1.lastModifiedTime > element2.lastModifiedTime end) end function PlayerListUI:_getTableElementCount() return #self._accounts end function PlayerListUI:_getTableElementSize() return self._itemSize end ---_setTableElement ---@param node UINode ---@param index number function PlayerListUI:_setTableElement(node, index) node.tag = index node:getChild("img_player_icon_holder").isContainer = true node:getChild("img_player_icon_holder.bg"):getPostDrawLayer(0):addListener( { self._onRenderPlayerBone, self, index }) local lbText = UIText.cast(node:getChild("lb_player_name")) lbText.text = self._accounts[index].name node.allowDoubleClick = true node:addTouchUpListener({ self._onElementClicked, self }) node:addTouchDoubleDownListener({ self._onElementDoubleClicked, self }) node:getChild("btn_cfg"):addTouchUpListener({ self._onConfigButtonClicked, self, index }) node:getChild("btn_remove"):addTouchUpListener({ self._onRemoveButtonClicked, self, index }) end function PlayerListUI:_onRenderPlayerBone(index) local playerBone = self._accounts[index].playerBone playerBone.joints:render() --playerBone.joints:renderDebug() end function PlayerListUI:_onPlayerBoneUpdate() for index = 1, #self._accounts do local elementNode = UIUtil.getTableElement(self._panelList, index) local screenPos = self.manager:getScreenPosition(elementNode) ---@type JointBody2D local playerBone = self._accounts[index].playerBone playerBone.joints.position = screenPos + Vector2.new(48, 112) playerBone.joints.scale = Vector2.new(1.5, 1.5) playerBone:update() end end ---_onElementClicked ---@param node UINode function PlayerListUI:_onElementClicked(node) local index = node.tag if self._indexSelected ~= index then self.manager:playClickSound() self._indexSelected = index self:updateSelection() end end ---_onElementClicked ---@param node UINode function PlayerListUI:_onElementDoubleClicked(node) self:_onElementClicked(node, nil) self:_onOkButtonClicked() end function PlayerListUI:_onOkButtonClicked() if self._indexSelected > 0 then MenuJoinInfo.getInstance().playerInfo.name = self._accounts[self._indexSelected].name self:closeWindow() self.manager:playClickSound() if not MenuJoinInfo.getInstance().serverInfo.isMultiplayer then require("WorldListUI").new() else require("ServerListUI").new() end end end function PlayerListUI:_onNewButtonClicked() self:closeWindow() self.manager:playClickSound() require("NewPlayerUI").new() end function PlayerListUI:_onConfigButtonClicked(index) end ---@param index number function PlayerListUI:_onRemoveButtonClicked(index) if self._indexSelected == index then local name = self._accounts[index].name self.manager:playClickSound() local InfoPopupUI = require("InfoPopupUI") local infoUI = InfoPopupUI.new( Locale.SURE_TO_DELETE_PLAYER_1 .. "\"" .. name .. "\"" .. Locale.SURE_TO_DELETE_PLAYER_2, function() if name ~= nil and name ~= "" then print("remove player", name) AccountUtils.Remove(name) end end, function() PlayerListUI.new() end ) self:closeWindow() end end function PlayerListUI:_onBackButtonClicked() MenuJoinInfo.getInstance().playerInfo.name = "" self.manager:playClickSound() self:closeWindow() require("StartUI").new() end function PlayerListUI:updateSelection() for index = 1, #self._accounts do local node = self._panelList:getChildByTag(index) local show = false if node.tag == self._indexSelected then show = true end node:getChild("img_selected").visible = show node:getChild("btn_remove").visible = show node:getChild("btn_cfg").visible = show end local btnColor = self._indexSelected and Color.White or Color.Gray UIText.cast(self.root:getChild("layer.btn_ok.lb_caption")).color = btnColor end function PlayerListUI:closeWindow() PlayerListUI.super.closeWindow(self) end return PlayerListUI ================================================ FILE: ui/RawHotkeyUIHelper.lua ================================================ local RawHotkeyUIHelper = class("HotkeyUIHelper") function RawHotkeyUIHelper:__init(uiWindow) self._uiWindow = uiWindow self._closeHotkey = Input.keyboard:getHotKeys(Keys.Escape):addListener({ RawHotkeyUIHelper._closeMe, self }) end function RawHotkeyUIHelper:destroy() if self._closeHotkey then Input.keyboard:getHotKeys(Keys.Escape):removeListener(self._closeHotkey) self._closeHotkey = nil end end function RawHotkeyUIHelper:_closeMe() self._uiWindow:closeWindow() end return RawHotkeyUIHelper ================================================ FILE: ui/ServerListUI.lua ================================================ ---@class TC.ServerListUI:TC.UIWindow local ServerListUI = class("ServerListUI", require("UIWindow")) local UIUtil = require("UIUtil") function ServerListUI:__init() ServerListUI.super.__init(self, require("UIDesign").getServerListUI()) self.indexSelected = 0 self.itemNodes = {} self:initContent() end function ServerListUI:initContent() local panelList = self.root:getChild("layer.panel_list") local panelItem = panelList:getChild("panel_item") self.itemSize = Size.new(panelItem.width / 1, panelItem.height) UIUtil.setTable(panelList, self, true, 1) self:updateSelection() self.root:getChild("layer.btn_back"):addTouchUpListener({ function(self) local PlayerListUI = require("PlayerListUI") self:closeWindow() PlayerListUI.new() end, self } ) self.root:getChild("layer.btn_create"):addTouchUpListener({ function(self) local NewServerUI = require("NewServerUI") self:closeWindow() NewServerUI.new() end, self }) end function ServerListUI:_getTableElementCount() return 5 end function ServerListUI:_getTableElementSize() return self.itemSize end ---_setTableElement ---@param node UINode ---@param index number function ServerListUI:_setTableElement(node, index) node.tag = index node:addTouchUpListener({ self._onElementClicked, self }) node:getChild("btn_remove"):addTouchUpListener({ function(self) local InfoPopupUI = require("InfoPopupUI") InfoPopupUI.new() end, self }) table.insert(self.itemNodes, node) end ---_onElementClicked ---@param node UINode ---@param _ Touch function ServerListUI:_onElementClicked(node) local index = node.tag self.indexSelected = index self:updateSelection() end function ServerListUI:updateSelection() ---@param node UINode for _, node in pairs(self.itemNodes) do local show = false if node.tag == self.indexSelected then show = true end node:getChild("img_selected").visible = show node:getChild("btn_remove").visible = show node:getChild("btn_cfg").visible = show end end function ServerListUI:closeWindow() ServerListUI.super.closeWindow(self) end return ServerListUI ================================================ FILE: ui/SettingUI.lua ================================================ ---@class TC.SettingUI:TC.UIWindow local SettingUI = class("SettingUI", require("UIWindow")) local UIUtil = require("UIUtil") local Settings = require("settings.Settings") function SettingUI:__init(closeCallback) SettingUI.super.__init(self, require("UIDesign").getSettingUI(), require("ui.UIDefault").GROUP_GAME_WINDOW) self._closeCallback = closeCallback self._settingInstance = Settings.getInstance() self._config = self._settingInstance.uiConfig self._infoList = UIScrollView.cast(self.root:getChild("layer.info_list")) self._panelSlider = self._infoList:getChild("panel_slider") self._panelBool = self._infoList:getChild("panel_bool") self._panelHold = self._infoList:getChild("panel_hold") self._indexSelected = 1 self._itemNodes = {} self._sliderSoundTicks = 0 self:initContent() end function SettingUI:initContent() local panelList = self.root:getChild("layer.panel_list") local panelItem = panelList:getChild("panel_item") self.itemSize = Size.new(panelItem.width, panelItem.height) UIUtil.setTable(panelList, self, true, 1) self.root:getChild("layer.btn_ok"):addTouchUpListener({ self._onBackClicked, self }) self:updateSelection() end function SettingUI:_getTableElementCount() return #self._config end function SettingUI:_getTableElementSize() return self.itemSize end ---_setTableElement ---@param node UINode ---@param index number function SettingUI:_setTableElement(node, index) node.tag = index local data = self._config[index] local lbName = UIText.cast(node:getChild("lb_group_name")) lbName.text = data.name node:addTouchUpListener({ self._onElementClicked, self }) table.insert(self._itemNodes, node) end ---_onElementClicked ---@param node UINode ---@param _ Touch function SettingUI:_onElementClicked(node) local index = node.tag if self._indexSelected ~= index then self.manager:playClickSound() self._indexSelected = index self:updateSelection() end end function SettingUI:updateSelection() ---@param node UINode for _, node in pairs(self._itemNodes) do local show = false if node.tag == self._indexSelected then show = true end node:getChild("img_selected").visible = show end self:updateInfoList() end function SettingUI:updateInfoList() self._panelSlider.visible = false self._panelBool.visible = false self._panelHold:removeAllChildren() local elements = self._config[self._indexSelected].elements local posY = 0 for i, element in ipairs(elements) do local node ---@type UINode if element.type == "Slider" then node = self._panelSlider:clone() local s = UISlider.cast(node:getChild("slider")) if element.maxValue ~= nil then s.maxValue = element.maxValue end if element.minValue ~= nil then s.minValue = element.minValue end if element.getter ~= nil then s.value = element.getter() end s.valueStep = 1 if element.valueStep ~= nil then s.valueStep = element.valueStep end s:addValueChangedListener({ self._onSliderChanged, self, i }) elseif element.type == "Boolean" then node = self._panelBool:clone() local s = UISwitch.cast(node:getChild("sw")) if element.getter ~= nil then s:setSelected(element.getter(), false) end s:addSelectChangedListener({ self._onSwitchChanged, self, i }) end UIText.cast(node:getChild("lb_title")).text = element.name self._panelHold:addChild(node) node.visible = true node.positionY = posY posY = posY + node.height end self._panelHold.height = posY self._infoList:ScrollToTop() local tmpSize = Size.new(self._infoList.viewSize.width, self._panelHold.height) tmpSize.height = math.max(tmpSize.height, self._infoList.height) self._infoList.viewSize = tmpSize self._infoList:ScrollToTop() end function SettingUI:_onSwitchChanged(index, _, selected) self.manager:playClickSound() local elements = self._config[self._indexSelected].elements local element = elements[index] if element.setter ~= nil then element.setter(selected) end end function SettingUI:_onSliderChanged(index, _, value) local elements = self._config[self._indexSelected].elements local element = elements[index] if element.setter ~= nil then element.setter(value) end self._sliderSoundTicks = self._sliderSoundTicks + 1 if self._sliderSoundTicks > 8 then self._sliderSoundTicks = 0 SoundUtils.PlaySoundGroup(Reg.SoundGroupID("wood")) end end function SettingUI:_onBackClicked() self.manager:playClickSound() Settings.saveData() self:closeWindow() end function SettingUI:closeWindow() if self._closeCallback ~= nil then self._closeCallback() end SettingUI.super.closeWindow(self) end return SettingUI ================================================ FILE: ui/StartUI.lua ================================================ ---@class TC.StartUI:TC.UIWindow local StartUI = class("StartUI", require("UIWindow")) local Locale = require("languages.Locale") local UISpritePool = require("ui.UISpritePool") function StartUI:__init() StartUI.super.__init(self, require("UIDesign").getStartUI()) self._logoTexture = nil self._subLogoTexture = nil self._ticks = 0 self._logoSize = 1 self._logoAngle = 0 self:initContent() end function StartUI:initContent() self._logoTexture = UISpritePool.getInstance():get("tc:logo4").textureLocation self._subLogoTexture = UISpritePool.getInstance():get("tc:sublogo").textureLocation UIText.cast(self.root:getChild("lb_mod")).text = string.format(Locale.MOD_LOADER_INFO, Mod.modList.count) print(App.engineVersion) UIText.cast(self.root:getChild("lb_engine_ver")).text = string.format(Locale.ENGINE_VERSION, App.engineVersion) UIText.cast(self.root:getChild("lb_game_ver")).text = string.format(Locale.GAME_VER, Mod.current.gameVersion .. " " .. Mod.current.version) self.root:getChild("layer.btn_single"):addTouchUpListener({ function(self) self:_jumpTo(require("PlayerListUI")) end, self }) self.root:getChild("layer.btn_mul_player"):addTouchUpListener({ function(self) require("tc.ui.InfoPopupUI").new("功能开发中,敬请期待!") --self:_jumpTo(require("ServerListUI")) end, self }) self.root:getChild("layer.btn_community"):addTouchUpListener({ function(self) require("tc.ui.InfoPopupUI").new("欢迎加入正式论坛:https://terracraft.eu.org/") --self:_jumpTo(require("ServerListUI")) end, self }) self.root:getChild("layer.btn_lang"):addTouchUpListener({ function(self) require("tc.ui.InfoPopupUI").new("功能开发中,敬请期待!") --self:_jumpTo(require("LanguageUI")) end, self }) self.root:getChild("layer.btn_mod"):addTouchUpListener({ function(self) self:_jumpTo(require("ModListUI")) end, self }) self.root:getChild("layer.btn_setting"):addTouchUpListener({ function(self) self:closeWindow() self.manager:playClickSound() require("SettingUI").new(function() StartUI.new() end) end, self }) self.root:getChild("layer.btn_exit"):addTouchUpListener({ function() ClientStateManager.QuitGame() end }) self.root:getPreDrawLayer(0):addListener({ StartUI.renderLogo, self }) self:initUpdateFunc({ self._onUpdate, self }) end function StartUI:_onUpdate() self._logoSize = 1.05 + Utils.SinValue(self._ticks, 256) * 0.05 self._logoAngle = Utils.CosValue(self._ticks, 512) * 0.05 self._ticks = self._ticks + 1 end function StartUI:renderLogo() -- render the main logo local texSize = TextureManager.getSourceRect(self._logoTexture) local pos = Vector2.new(GameWindow.displayResolution.width / 2, 60) local exLogo = SpriteExData.new() exLogo.angle = self._logoAngle exLogo.origin = Vector2.new(texSize.width / 2, texSize.height / 2) exLogo.scaleRate = Vector2.new(self._logoSize, self._logoSize) Sprite.draw(self._logoTexture, Vector2.new(GameWindow.displayResolution.width / 2, 60), texSize, Color.White, exLogo, 0) -- render the sub logo local texSubLogoSize = TextureManager.getSourceRect(self._subLogoTexture) local exSubLogo = SpriteExData.new() exSubLogo.origin = Vector2.new(texSubLogoSize.width / 2, texSubLogoSize.height / 2) exSubLogo.scaleRate = Vector2.new(1.3, 1.3) Sprite.draw(self._subLogoTexture, Vector2.new(GameWindow.displayResolution.width / 2, 100), texSubLogoSize, Color.White, exSubLogo, 0) end function StartUI:_jumpTo(WindowClass) self.manager:playClickSound() self:closeWindow() WindowClass.new() end function StartUI:closeWindow() StartUI.super.closeWindow(self) end return StartUI ================================================ FILE: ui/TipUI.lua ================================================ ---@class TC.TipUI:TC.UIWindow local TipUI = class("TipUI", require("UIWindow")) ---@type TC.TipUI local s_tipUI function TipUI.generate(contentTable, keepTicks, showTag) keepTicks = keepTicks or 128 -- TEST CODE contentTable = contentTable or { "Copper Axe", " ", "Durability: 6666/9999", "+3 Attack Damage", "+6 Crit Rate", "普通速度", "普通攻击力", "Can be placed", "Debug Only" } TipUI.close() s_tipUI = TipUI.new(keepTicks, contentTable, showTag) return s_tipUI end function TipUI.adaptPosition(pos) if s_tipUI ~= nil then s_tipUI:_adaptPosition(pos.x, pos.y) end end function TipUI.close() if s_tipUI ~= nil then s_tipUI:closeWindow() end end function TipUI.isShowing() return s_tipUI ~= nil end function TipUI.changeNewContent(contentTable) if s_tipUI ~= nil then s_tipUI:setNewContent(contentTable) end end function TipUI.getShowTag() if s_tipUI ~= nil then return s_tipUI.showTag end return 0 end function TipUI.resetKeepTime() if s_tipUI ~= nil then s_tipUI:_resetKeepTime() end end function TipUI:__init(keepTicks, contentTable, showTag) TipUI.super.__init(self, require("UIDesign").getTipUI()) if showTag == nil then showTag = 0 end self.maxKeepTicks = keepTicks self.keepTicks = keepTicks self.contentTable = clone(contentTable) self.touchingPosition = Vector2.new() self.showTag = showTag self.baseLabel = UIText.cast(self.root:getChild("lb_tip")) self._totalLabels = 0 self:_initContent() end function TipUI:_initContent() self:_setContent() self._schedule = IntegratedClient.main:createSchedule(0) IntegratedClient.main:getSchedule(self._schedule):addListener({ TipUI._onTick, self }) end function TipUI:setNewContent(contentTable) if #self.contentTable == #contentTable then local same = true for i, str in ipairs(self.contentTable) do local str2 = contentTable[i] if str ~= str2 then same = false break end end if same then return end end self.contentTable = contentTable self:_setContent() end function TipUI:_setContent() local label = self.baseLabel label.visible = false local LINE_OFFSET = 2 local maxTextWidth = 0 local offsetY = label.positionY for i = 1, self._totalLabels do local node = self.root:getChild(string.format("content_%d", i)) if node:valid() then node.visible = false self.root:removeChild(node) end end self._totalLabels = #self.contentTable -- generate all text from content table for i, str in ipairs(self.contentTable) do local currentLabel = self.root:getChild(string.format("content_%d", i)) if not currentLabel:valid() then currentLabel = label:clone() currentLabel.name = string.format("content_%d", i) self.root:addChild(currentLabel) end currentLabel.visible = true currentLabel.isRichText = true currentLabel.text = str currentLabel.position = Vector2(label.positionX, offsetY) maxTextWidth = math.max(currentLabel.width, maxTextWidth) offsetY = offsetY + currentLabel.height + LINE_OFFSET end self.root:setSize(maxTextWidth + 20, offsetY + 6) end function TipUI:_onTick() self.keepTicks = self.keepTicks - 1 if self.keepTicks <= 0 then self:closeWindow() end end function TipUI:_resetKeepTime() self.keepTicks = self.maxKeepTicks end ---adaptPosition ---@param touchX double ---@param touchY double function TipUI:_adaptPosition(touchX, touchY) if self.touchingPosition.x ~= touchX or self.touchingPosition.y ~= touchY then self.touchingPosition.x = touchX self.touchingPosition.y = touchY local size = self.root.size local globalWidth, globalHeight = GameWindow.displayResolution.width, GameWindow.displayResolution.height local uiWidth, uiHeight = size.width, size.height local newX, newY = touchX, touchY newX = touchX + 32 newY = touchY - uiHeight * 0.75 -- left boundary newX = math.max(newX, 32) -- right boundary if newX + uiWidth + 32 > globalWidth then newX = touchX - 32 - uiWidth end -- top boundary newY = math.max(newY, 32) -- bottom boundary if newY + uiHeight + 32 > globalHeight then newY = touchY - 32 - uiHeight end self.root.position = Vector2.new(newX, newY) self.root:applyMargin() end end function TipUI:closeWindow() TipUI.super.closeWindow(self) if self._schedule ~= nil then IntegratedClient.main:removeSchedule(self._schedule) self._schedule = nil end s_tipUI = nil end return TipUI ================================================ FILE: ui/TipsOfTheDay.lua ================================================ ---@class TC.TipsOfTheDay local TipsOfTheDay = class("TipsOfTheDay") function TipsOfTheDay:__init() self.texts = { "你可以点击上方的\"?\"按钮查看接下来的目标。", "使用末影传送门快速移动到世界各地。", "拥有共享背包模式的世界可以与其他世界共享玩家背包信息。", "你可以使用铁砧来恢复工具的耐久值。", "要致富,先砍树!造一个庇护所来度过你的第一个晚上!", "PC端和手机端的存档支持互通!", "你可以通过挖掘生命水晶来增加你的生命值上限。", "死亡会损失20%的经验值。", "尝试制作一个红石电路系统!", "你可以使用酿造台来制作不同的药水。", "你可以点击上方的配方按钮来查看所有物品配方。", "点击灯泡按钮,试试智能光标模式!", "食用魔法碎片可以增加你的魔力值上限。", "远程武器使用对应子弹或弓箭,将额外拥有30%伤害加成。", } end function TipsOfTheDay:getRandomText() return self.texts[math.random(1, #self.texts)] end return TipsOfTheDay ================================================ FILE: ui/UIDefault.lua ================================================ ---@class TC.UIDefault local UIDefault = { FontSize = 24, SmallFontSize = 18, ButtonHeight = 48, ButtonOffset = 60, CellSize = 46, CellLargeSize = 56, CellOffset = 48, CellHugeSize = 64, CellHugeOffset = 68, GROUP_NONE = 0, GROUP_GAME_WINDOW = 1, GROUP_GAME_HUD = 2, } return UIDefault ================================================ FILE: ui/UIDesign.lua ================================================ ---@class TC.UIDesign local UIDesign = class("UIDesign") local UIUtil = require("UIUtil") local UIDefault = require("UIDefault") local Locale = require("languages.Locale") local UISpritePool = require("UISpritePool").getInstance() function UIDesign.getStartUI() local UI_SIZE = Size.new(400, 400) local root = UIPanel.new("start_ui") root.size = GameWindow.displayResolution root:setMarginEnabled(true, true, true, true) root:setAutoStretch(true, true) local panel = UIUtil.createPanel("layer", 0, 0, UI_SIZE.width, UI_SIZE.height, { margins = { 0, 128, 0, 64, false, false } }) root:addChild(panel) local sy = 32 panel:addChild(UIUtil.createButton("btn_single", Locale.SINGLE_PLAYER, 0, sy, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 0, 0, false } })) sy = sy + UIDefault.ButtonOffset panel:addChild(UIUtil.createButton("btn_mul_player", Locale.MULTI_PLAYER, 0, sy, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 0, 0, false } })) sy = sy + UIDefault.ButtonOffset panel:addChild(UIUtil.createButton("btn_mod", Locale.MOD_LIST, 0, sy, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 0, 0, false } })) sy = sy + UIDefault.ButtonOffset panel:addChild(UIUtil.createButton("btn_community", Locale.COMMUNITY, 0, sy, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 0, 0, false } })) sy = sy + UIDefault.ButtonOffset + 16 panel:addChild(UIUtil.createButtonWithImage("btn_lang", "tc:lang", 0, sy, UIDefault.ButtonHeight, UIDefault.ButtonHeight, { marginsLR = { -UIDefault.ButtonHeight - 16, nil } })) panel:addChild(UIUtil.createButton("btn_setting", Locale.SETTING, 0, sy, UI_SIZE.width / 2 - 8, UIDefault.ButtonHeight, { marginsLR = { 0, UI_SIZE.width / 2 + 8 } })) panel:addChild(UIUtil.createButton("btn_exit", Locale.EXIT_GAME, 0, sy, UI_SIZE.width / 2 - 8, UIDefault.ButtonHeight, { marginsLR = { UI_SIZE.width / 2 + 8, 0 } })) root:addChild(UIUtil.createLabelNoPos("lb_copyright", Locale.COPYRIGHT, TextAlignment.Left, TextAlignment.Bottom, { margins = { 16, nil, nil, 0 } })) root:addChild(UIUtil.createLabelNoPos("lb_mod", Locale.MOD_LOADER_INFO, TextAlignment.Left, TextAlignment.Bottom, { margins = { 16, nil, nil, 32 } })) root:addChild(UIUtil.createLabelNoPos("lb_engine_ver", Locale.ENGINE_VERSION, TextAlignment.Right, TextAlignment.Bottom, { margins = { nil, nil, 16, 0 } })) root:addChild(UIUtil.createLabelNoPos("lb_game_ver", Locale.ENGINE_VERSION, TextAlignment.Right, TextAlignment.Bottom, { margins = { nil, nil, 16, 32 } })) return root end function UIDesign.getPendingUI() local UI_SIZE = Size.new(400, 400) local root = UIUtil.createBlackFullScreenLayer("pending_ui") root.size = GameWindow.displayResolution root:setMarginEnabled(true, true, true, true) root:setAutoStretch(true, true) local panel = UIUtil.createPanel("layer", 0, 0, UI_SIZE.width, UI_SIZE.height, { margins = { 0, 0, 0, 0, false, false } }) root:addChild(panel) panel:addChild(UIUtil.createPanel("panel_animation", 0, 170, 32, 32, { marginsLR = { 0, 0 } })) panel:addChild(UIUtil.createLabel("lb_tip", Locale.LOADING, 0, 250, UI_SIZE.width, 32, TextAlignment.HCenter, TextAlignment.VCenter, { })) panel:addChild(UIUtil.createButton("btn_back", Locale.BACK, 0, 0, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, 0, 50, false, false } })) return root end function UIDesign.getOptionUI() local UI_SIZE = Size.new(400, 400) local root = UIUtil.createBlackFullScreenLayer("option_ui") root.size = GameWindow.displayResolution root:setMarginEnabled(true, true, true, true) root:setAutoStretch(true, true) local panel = UIUtil.createPanel("layer", 0, 0, UI_SIZE.width, UI_SIZE.height, { margins = { 0, 128, 0, 64, false, false } }) root:addChild(panel) local sy = 32 panel:addChild(UIUtil.createButton("btn_back", Locale.BACK_TO_GAME, 0, sy, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 0, 0, false } })) sy = sy + UIDefault.ButtonOffset panel:addChild(UIUtil.createButton("btn_setting", Locale.SETTING, 0, sy, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 0, 0, false } })) sy = sy + UIDefault.ButtonOffset panel:addChild(UIUtil.createButton("btn_recipe", Locale.RECIPE_SEARCH .. "(R)", 0, sy, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 0, 0, false } })) sy = sy + UIDefault.ButtonOffset panel:addChild(UIUtil.createButton("btn_advancement", Locale.ADVANCEMENT .. "(F)", 0, sy, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 0, 0, false } })) sy = sy + UIDefault.ButtonOffset panel:addChild(UIUtil.createButton("btn_save_and_exit", Locale.SAVE_AND_EXIT, 0, sy, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 0, 0, false } })) panel:addChild(UIUtil.createLabelNoPos("lb_caption", Locale.GAME_MENU, TextAlignment.HCenter, TextAlignment.VCenter, { margins = { 0, -20, 0, nil } })) return root end function UIDesign.getLanguageUI() local UI_SIZE = Size.new(600, 450) local root = UIPanel.new("language_ui") root.size = GameWindow.displayResolution root:setMarginEnabled(true, true, true, true) root:setAutoStretch(true, true) root.sprite = UISpritePool:get("tc:black") root.sprite.color = Color.new(255, 255, 255, 200) local panel = UIUtil.createPanel("layer", 0, 0, UI_SIZE.width, UI_SIZE.height, { margins = { 0, 0, 0, 0, false, false } }) root:addChild(panel) panel:addChild(UIUtil.createImageNoPos("bg_frame", { margins = { 0, 0, 0, 0 }, sprite = { name = "tc:window_frame_01", color = Color.new(255, 255, 255, 240) } })) panel:addChild(UIUtil.createImageNoPos("bg", { margins = { 2, 2, 2, 2 }, sprite = { name = "tc:window_bg_01", color = Color.new(255, 255, 255, 30), style = UISpriteStyle.Filled } })) panel:addChild(UIUtil.createButton("btn_ok", Locale.OK, 0, 200, UI_SIZE.width, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 16, nil, 16, 16 }, targetSprite = { color = Color.new(110, 108, 132, 255) } })) panel:addChild(UIUtil.createLabelNoPos("lb_title", Locale.SELECT_LANGUAGE, TextAlignment.HCenter, TextAlignment.VCenter, { positionY = 12, fontSize = UIDefault.FontSize + 8, marginsLR = { 0, 0 } })) panel:addChild(UIUtil.createLabelNoPos("lb_list_title", Locale.LANGUAGE_LIST, TextAlignment.Left, TextAlignment.Top, { margins = { 16, 64, 16, nil }, color = Color.Gray })) panel:addChild(UIUtil.createImage("img_line", 0, 76, 128, 1, { marginsLR = { 100, 16 }, sprite = { name = "tc:white", color = Color.Gray } })) panel:addChild(UIUtil.createLabelNoPos("lb_tips", Locale.LANGUAGE_MAY_WRONG, TextAlignment.HCenter, TextAlignment.Top, { margins = { 16, nil, 16, 80 }, color = Color.new(128, 128, 0) })) local panelList = UIUtil.createScrollViewNoPos("panel_list", { margins = { 16, 96, 16, 128 }, }) panel:addChild(panelList) local panelItem = UIPanel.new("panel_item", 0, 0, panelList.size.width, 64) panelList:addChild(panelItem) panelItem:addChild(UIUtil.createImageNoPos("img_selected", { margins = { 0, 0, 0, 0 }, touchable = false, visible = false, sprite = { name = "tc:round_rect_white", color = Color.new(48, 48, 60, 222) } })) panelItem:addChild(UIUtil.createLabelNoPos("lb_locale", "English", TextAlignment.HCenter, TextAlignment.VCenter, { margins = { 0, 0, 0, 0 } })) return root end function UIDesign.getPlayerListUI() local UI_SIZE = Size.new(800, 450) local root = UIUtil.createBlackFullScreenLayer("player_list_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, nil) panel:addChild(UIUtil.createLabelNoPos("lb_title", Locale.SELECT_PLAYER, TextAlignment.HCenter, TextAlignment.VCenter, { positionY = 12, marginsLR = { 0, 0 }, fontSize = UIDefault.FontSize + 8 })) local panelList = UIUtil.createScrollViewNoPos("panel_list", { margins = { 16, 64, 16, 80 }, sprite = { name = "tc:round_rect_white", color = Color.new(30, 30, 45) } }) panel:addChild(panelList) local panelItem = UIPanel.new("panel_item", 0, 0, panelList.size.width, 96) panelList:addChild(panelItem) panelItem:addChild(UIUtil.createImageNoPos("img_selected", { margins = { 0, 0, 0, 0 }, touchable = false, sprite = { name = "tc:round_rect_white", color = Color.new(60, 60, 80, 222) } })) panelItem:addChild(UIUtil.createImage("img_line", 0, 96, 100, 2, { marginsLR = { 16, 16 }, sprite = { name = "tc:white", color = Color.new(60, 60, 80, 100) } })) local playerIconHolder = UIUtil.createImage("img_player_icon_holder", 16, 16, 64, 64, { touchable = false }) panelItem:addChild(playerIconHolder) playerIconHolder:addChild(UIUtil.createImageNoPos("bg", { margins = { 0, 0, 0, 0 }, touchable = false, sprite = { name = "tc:round_rect_white", color = Color.new(10, 10, 25) } })) panelItem:addChild(UIUtil.createLabel("lb_player_name", "BlueYoshiSuperLazyJuju", 96, 32, 128, 24, TextAlignment.Left, TextAlignment.VCenter)) --panelItem:addChild(UIUtil.createImage("img_hp", 96, 48, 32, 32, { -- touchable = false, -- sprite = { name = "tc:health" } --})) --panelItem:addChild(UIUtil.createLabel("lb_hp", "200/200", -- 130, 48, 96, 32, -- TextAlignment.Left, TextAlignment.VCenter, { -- color = Color.new(200, 100, 100) -- })) --panelItem:addChild(UIUtil.createImage("img_mana", 226, 48, 32, 32, { -- touchable = false, -- sprite = { name = "tc:mana" } --})) --panelItem:addChild(UIUtil.createLabel("lb_mana", "100/100", -- 260, 48, 96, 32, -- TextAlignment.Left, TextAlignment.VCenter, { -- color = Color.new(100, 100, 200) -- })) --panelItem:addChild(UIUtil.createImage("img_exp", 356, 48, 32, 32, { -- touchable = false, -- sprite = { name = "tc:exp" } --})) --panelItem:addChild(UIUtil.createLabel("lb_exp", "Lv.12", -- 384, 48, 96, 32, -- TextAlignment.Left, TextAlignment.VCenter, { -- color = Color.new(150, 150, 75) -- })) --panelItem:addChild(UIUtil.createLabel("lb_tips", "背包共享", -- 460, 48, 96, 32, -- TextAlignment.Left, TextAlignment.VCenter, { -- color = Color.FrenchGray -- })) panelItem:addChild(UIUtil.createButtonWithImage("btn_remove", "tc:delete", 700, 0, 48, 48, { marginsTB = { 16, 16, false }, targetSprite = { color = Color.new(110, 108, 132, 255) } }, { sprite = { color = Color.new(180, 168, 232, 255) } })) panelItem:addChild(UIUtil.createButtonWithImage("btn_cfg", "tc:conf", 640, 0, 48, 48, { marginsTB = { 16, 16, false }, targetSprite = { color = Color.new(110, 108, 132, 255) } }, { sprite = { color = Color.new(180, 168, 232, 255) } })) panel:addChild(UIUtil.createButton("btn_back", Locale.BACK, 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, UI_SIZE.width * 0.66, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_create", Locale.NEW_PLAYER_B, 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_ok", Locale.SELECT_PLAYER, 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { UI_SIZE.width * 0.66, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) return root end function UIDesign.getNewPlayerUI() local UI_SIZE = Size.new(800, 450) local root = UIUtil.createBlackFullScreenLayer("new_player_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, nil) panel:getChild("bg_frame"):setRightMargin(200, true) root:addChild(panel) panel:addChild(UIUtil.createLabelNoPos("lb_title", Locale.CREATE_PLAYER, TextAlignment.HCenter, TextAlignment.VCenter, { positionY = 12, marginsLR = { 0, 200 }, fontSize = UIDefault.FontSize + 8 })) panel:addChild(UIUtil.createButton("btn_back", Locale.BACK, 32, 200, 250, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { nil, nil, nil, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_ok", Locale.CREATE_PLAYER, 320, 200, 250, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { nil, nil, nil, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) local panelList = UIUtil.createScrollView("panel_list", 0, 0, 240, 100, { margins = { 16, 64, nil, 150 }, sprite = { name = "tc:round_rect_white", color = Color.new(30, 30, 45) } }) panel:addChild(panelList) local panelItem = UIPanel.new("panel_item", 0, 0, panelList.size.width, 80) panelList:addChild(panelItem) panelItem:addChild(UIUtil.createImageNoPos("img_selected", { margins = { 0, 0, 0, 0 }, touchable = false, sprite = { name = "tc:round_rect_white", color = Color.new(60, 60, 80, 222) }, visible = false })) panelItem:addChild(UIUtil.createImage("img_line", 0, 80, 100, 2, { marginsLR = { 16, 16 }, sprite = { name = "tc:white", color = Color.new(60, 60, 80, 100) } })) local playerIconHolder = UIUtil.createImage("img_player_icon_holder", 8, 8, 64, 64, { touchable = false }) panelItem:addChild(playerIconHolder) playerIconHolder:addChild(UIUtil.createImageNoPos("bg", { margins = { 0, 0, 0, 0 }, touchable = false, sprite = { name = "tc:round_rect_white", color = Color.new(10, 10, 25) } })) panelItem:addChild(UIUtil.createLabel("lb_name", "xqz", 80, 8, 128, 24, TextAlignment.Left, TextAlignment.VCenter)) panelItem:addChild(UIUtil.createLabel("lb_author", "by Blueyoshi, xxx, zzz", 80, 32, 128, 24, TextAlignment.Left, TextAlignment.VCenter, { fontSize = 18, color = Color.FrenchGray })) panelItem:addChild(UIUtil.createLabel("lb_mod", "Mod: Terraria", 80, 52, 128, 24, TextAlignment.Left, TextAlignment.VCenter, { fontSize = 18, color = Color.Gray })) panel:addChild(UIUtil.createLabel("lb_gender", "性别:", 280, 176, 100, 32, TextAlignment.Left, TextAlignment.VCenter)) panel:addChild(UIUtil.createButtonWithImage("btn_male", "tc:male", 360, 160, 56, 56, { targetSprite = { color = Color.new(80, 88, 102, 255) }, })) panel:addChild(UIUtil.createButtonWithImage("btn_female", "tc:female", 480, 160, 56, 56, { targetSprite = { color = Color.new(80, 88, 102, 255) }, })) panel:getChild("lb_gender").visible = false panel:getChild("btn_male").visible = false panel:getChild("btn_female").visible = false panel:addChild(UIUtil.createLabel("lb_name", Locale.NAME_Q, 280, 100, 100, 32, TextAlignment.Left, TextAlignment.VCenter)) local panelName = UIUtil.createPanel("panel_name", 340, 90, 200, 48, { marginsLR = { 340, 216 }, sprite = { name = "tc:round_rect_white", color = Color.new(60, 60, 85) } }) panel:addChild(panelName) panelName:addChild(UIUtil.createPanelNoPos("bg", { margins = { 2, 2, 2, 2 }, sprite = { name = "tc:round_rect_white", color = Color.new(30, 30, 45) } })) local editName = UIInputField.new("edit") UIUtil.setMargins(editName, 8, 8, 8, 8) panelName:addChild(editName) panel:addChild(UIUtil.createButton("btn_move", Locale.MORE_SETTINGS, 0, 250, 276, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 272, 216 }, targetSprite = { color = Color.new(110, 108, 132, 255) }, visible = false })) panel:addChild(UIUtil.createPanel("pos_panel", 640, 125, 200, 200)) local panelInfo = UIUtil.createPanelNoPos("panel_info", { margins = { 16, 310, 216, 80 }, sprite = { name = "tc:round_rect_white", color = Color.new(28, 28, 40, 222) }, }) panel:addChild(panelInfo) panelInfo:addChild(UIUtil.createPanelNoPos("bg", { margins = { 4, 4, 4, 4 }, sprite = { name = "tc:round_rect_white", color = Color.new(10, 10, 20, 222) } })) panelInfo:addChild(UIUtil.createLabelNoPos("lb_info", "名字不能超过1000个字符!", TextAlignment.HCenter, TextAlignment.VCenter, { margins = { 0, 0, 0, 0 }, color = Color.Yellow })) panel:addChild(UIUtil.createButton("btn_animator", Locale.CHANGE_POSTURE, 660, 350, 160, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, targetSprite = { color = Color.new(80, 88, 102, 255) }, })) return root end function UIDesign.getWorldListUI() local UI_SIZE = Size.new(800, 450) local root = UIUtil.createBlackFullScreenLayer("world_list_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, nil) panel:addChild(UIUtil.createLabelNoPos("lb_title", Locale.SELECT_WORLD, TextAlignment.HCenter, TextAlignment.VCenter, { positionY = 12, marginsLR = { 0, 0 }, fontSize = UIDefault.FontSize + 8 })) local panelList = UIUtil.createScrollViewNoPos("panel_list", { margins = { 16, 64, 16, 80 }, sprite = { name = "tc:round_rect_white", color = Color.new(30, 30, 45) } }) panel:addChild(panelList) local panelItem = UIPanel.new("panel_item", 0, 0, panelList.size.width, 128) panelList:addChild(panelItem) panelItem:addChild(UIUtil.createImageNoPos("img_selected", { margins = { 0, 0, 0, 0 }, touchable = false, visible = false, sprite = { name = "tc:round_rect_white", color = Color.new(60, 60, 80, 222) } })) panelItem:addChild(UIUtil.createImage("img_line", 0, 128, 100, 2, { marginsLR = { 16, 16 }, sprite = { name = "tc:white", color = Color.new(60, 60, 80, 100) } })) local imgWorldPic = UIUtil.createImage("img_world_pic", 16, 16, 96, 96, { touchable = false, sprite = { name = "tc:round_rect_white", color = Color.new(10, 10, 25) } }) panelItem:addChild(imgWorldPic) imgWorldPic:addChild(UIUtil.createImageNoPos("img", { margins = { 0, 0, 0, 0 }, touchable = false, sprite = { name = "tc:world_icon", } })) panelItem:addChild(UIUtil.createLabel("lb_world_name", "SuperJujuWorld", 128, 16, 128, 24, TextAlignment.Left, TextAlignment.VCenter)) panelItem:addChild(UIUtil.createLabel("lb_time", "2/22/2022 2:22 PM", 128, 48, 96, 32, TextAlignment.Left, TextAlignment.VCenter, { color = Color.Gray })) panelItem:addChild(UIUtil.createLabel("lb_tips", "Hardcore Mode, Version 2022", 128, 80, 96, 32, TextAlignment.Left, TextAlignment.VCenter, { color = Color.FrenchGray })) panelItem:addChild(UIUtil.createButtonWithImage("btn_remove", "tc:delete", 700, 0, 48, 48, { marginsTB = { 16, 16, false }, targetSprite = { color = Color.new(110, 108, 132, 255) } }, { sprite = { color = Color.new(180, 168, 232, 255) } })) panel:addChild(UIUtil.createButton("btn_back", Locale.BACK, 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, UI_SIZE.width * 0.66, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_create", Locale.NEW_WORLD_B, 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_ok", Locale.ENTER_WORLD, 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { UI_SIZE.width * 0.66, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) return root end function UIDesign.getNewWorldUI() local UI_SIZE = Size.new(600, 450) local root = UIUtil.createBlackFullScreenLayer("new_list_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, nil) panel:addChild(UIUtil.createLabelNoPos("lb_title", Locale.CREATE_NEW_WORLD, TextAlignment.HCenter, TextAlignment.VCenter, { positionY = 12, marginsLR = { 0, 0 }, fontSize = UIDefault.FontSize + 8 })) panel:addChild(UIUtil.createLabel("lb_name", Locale.WORLD_NAME_Q, 0, 60, 180, 48, TextAlignment.HCenter, TextAlignment.VCenter, {})) local panelName = UIUtil.createPanel("panel_name", 0, 60, 200, 48, { marginsLR = { 180, 16 }, sprite = { name = "tc:round_rect_white", color = Color.new(60, 60, 85) } }) panel:addChild(panelName) panelName:addChild(UIUtil.createPanelNoPos("bg", { margins = { 2, 2, 2, 2 }, sprite = { name = "tc:round_rect_white", color = Color.new(30, 30, 45) } })) local editName = UIInputField.new("edit") UIUtil.setMargins(editName, 8, 8, 8, 8) panelName:addChild(editName) panel:addChild(UIUtil.createLabel("lb_seed", Locale.WORLD_SEED_Q, 0, 120, 180, 48, TextAlignment.HCenter, TextAlignment.VCenter, {})) local panelSeed = UIUtil.createPanel("panel_seed", 0, 120, 200, 48, { marginsLR = { 180, 16 }, sprite = { name = "tc:round_rect_white", color = Color.new(60, 60, 85) } }) panel:addChild(panelSeed) panelSeed:addChild(UIUtil.createPanelNoPos("bg", { margins = { 2, 2, 2, 2 }, sprite = { name = "tc:round_rect_white", color = Color.new(30, 30, 45) } })) local editSeed = UIInputField.new("edit") UIUtil.setMargins(editSeed, 8, 8, 8, 8) panelSeed:addChild(editSeed) panel:addChild(UIUtil.createButton("btn_gm", Locale.SURVIVAL_MODE, 0, 190, 276, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 16, UI_SIZE.width * 0.5 + 8, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_bp", Locale.BP_SHARED_MODE, 0, 190, 276, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { UI_SIZE.width * 0.5 + 8, 16, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_move", Locale.MORE_SETTINGS, 0, 250, 276, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, marginsLR = { 16, 16 }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:getChild("btn_move").visible = false local panelInfo = UIUtil.createPanelNoPos("panel_info", { margins = { 16, 316, 16, 80 }, sprite = { name = "tc:round_rect_white", color = Color.new(28, 28, 40, 222) } }) panel:addChild(panelInfo) panelInfo:addChild(UIUtil.createPanelNoPos("bg", { margins = { 4, 4, 4, 4 }, sprite = { name = "tc:round_rect_white", color = Color.new(10, 10, 20, 222) } })) panelInfo:addChild(UIUtil.createLabelNoPos("lb_info", "Hello world! This is a Tip! 名字不能超过1000个字符!", TextAlignment.HCenter, TextAlignment.VCenter, { margins = { 0, 0, 0, 0 }, color = Color.Yellow })) panel:addChild(UIUtil.createButton("btn_back", Locale.BACK, 0, 200, 250, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, UI_SIZE.width * 0.5, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_ok", Locale.CREATE_WORLD, 0, 200, 250, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { UI_SIZE.width * 0.5, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) return root end function UIDesign.getServerListUI() local UI_SIZE = Size.new(800, 450) local root = UIUtil.createBlackFullScreenLayer("server_list_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, nil) panel:addChild(UIUtil.createLabelNoPos("lb_title", "选择服务器", TextAlignment.HCenter, TextAlignment.VCenter, { positionY = 12, marginsLR = { 0, 0 }, fontSize = UIDefault.FontSize + 8 })) local panelList = UIUtil.createScrollViewNoPos("panel_list", { margins = { 16, 64, 16, 80 }, sprite = { name = "tc:round_rect_white", color = Color.new(30, 30, 45) } }) panel:addChild(panelList) local panelItem = UIPanel.new("panel_item", 0, 0, panelList.size.width, 96) panelList:addChild(panelItem) panelItem:addChild(UIUtil.createImageNoPos("img_selected", { margins = { 0, 0, 0, 0 }, touchable = false, visible = false, sprite = { name = "tc:round_rect_white", color = Color.new(60, 60, 80, 222) } })) panelItem:addChild(UIUtil.createImage("img_line", 0, 96, 100, 2, { marginsLR = { 16, 16 }, sprite = { name = "tc:white", color = Color.new(60, 60, 80, 100) } })) panelItem:addChild(UIUtil.createImage("img_server_pic", 16, 16, 64, 64, { touchable = false, sprite = { name = "tc:round_rect_white", color = Color.new(10, 10, 25) } })) panelItem:addChild(UIUtil.createLabel("lb_server_name", "Blueyoshi Test Server", 96, 16, 128, 24, TextAlignment.Left, TextAlignment.VCenter)) panelItem:addChild(UIUtil.createLabel("lb_tips", "这是一个服务器首页文本!", 96, 48, 96, 32, TextAlignment.Left, TextAlignment.VCenter, { color = Color.FrenchGray })) panelItem:addChild(UIUtil.createImage("img_ping_bg", 0, 0, 30, 22, { margins = { nil, 16, 16, nil }, sprite = { name = "tc:ping_bg" } })) panelItem:addChild(UIUtil.createImage("img_ping_green", 0, 0, 30, 22, { margins = { nil, 16, 16, nil }, sprite = { name = "tc:ping_green" } })) panelItem:addChild(UIUtil.createLabel("lb_players", "114/1000", 96, 16, 30, 24, TextAlignment.Right, TextAlignment.VCenter, { margins = { nil, 16, 60, nil }, color = Color.FrenchGray })) panelItem:addChild(UIUtil.createButtonWithImage("btn_remove", "tc:delete", 700, 0, 48, 48, { margins = { nil, nil, 16, 8 }, targetSprite = { color = Color.new(110, 108, 132, 255) } }, { sprite = { color = Color.new(180, 168, 232, 255) } })) panelItem:addChild(UIUtil.createButtonWithImage("btn_cfg", "tc:conf", 700, 0, 48, 48, { margins = { nil, nil, 80, 8 }, targetSprite = { color = Color.new(110, 108, 132, 255) } }, { sprite = { color = Color.new(180, 168, 232, 255) } })) panel:addChild(UIUtil.createButton("btn_back", Locale.BACK, 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, UI_SIZE.width * 0.66, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_create", "添加服务器..", 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_ok", "进入服务器", 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { UI_SIZE.width * 0.66, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) return root end function UIDesign.getNewServerUI() local UI_SIZE = Size.new(600, 250) local root = UIUtil.createBlackFullScreenLayer("new_list_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, nil) panel:addChild(UIUtil.createLabelNoPos("lb_title", "编辑服务器信息", TextAlignment.HCenter, TextAlignment.VCenter, { positionY = 12, marginsLR = { 0, 0 }, fontSize = UIDefault.FontSize + 8 })) panel:addChild(UIUtil.createLabel("lb_name", "Server Name:", 0, 60, 180, 48, TextAlignment.HCenter, TextAlignment.VCenter, {})) local panelName = UIUtil.createPanel("panel_name", 0, 60, 200, 48, { marginsLR = { 180, 16 }, sprite = { name = "tc:round_rect_white", color = Color.new(60, 60, 85) } }) panel:addChild(panelName) panelName:addChild(UIUtil.createPanelNoPos("bg", { margins = { 2, 2, 2, 2 }, sprite = { name = "tc:round_rect_white", color = Color.new(30, 30, 45) } })) local editName = UIInputField.new("edit") UIUtil.setMargins(editName, 8, 8, 8, 8) panelName:addChild(editName) panel:addChild(UIUtil.createLabel("lb_addr", "Server Address:", 0, 120, 180, 48, TextAlignment.HCenter, TextAlignment.VCenter, {})) local panelAddr = UIUtil.createPanel("lb_addr", 0, 120, 200, 48, { marginsLR = { 180, 16 }, sprite = { name = "tc:round_rect_white", color = Color.new(60, 60, 85) } }) panel:addChild(panelAddr) panelAddr:addChild(UIUtil.createPanelNoPos("bg", { margins = { 2, 2, 2, 2 }, sprite = { name = "tc:round_rect_white", color = Color.new(30, 30, 45) } })) local editAddr = UIInputField.new("edit") UIUtil.setMargins(editAddr, 8, 8, 8, 8) panelAddr:addChild(editAddr) panel:addChild(UIUtil.createButton("btn_back", "Cancel", 0, 200, 250, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, UI_SIZE.width * 0.5, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_ok", "Done", 0, 200, 250, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { UI_SIZE.width * 0.5, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) return root end function UIDesign.getSettingUI() local UI_SIZE = Size.new(800, 450) local root = UIUtil.createBlackFullScreenLayer("setting_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, nil) panel:addChild(UIUtil.createLabelNoPos("lb_title", Locale.SETTING_PANEL, TextAlignment.HCenter, TextAlignment.VCenter, { positionY = 12, marginsLR = { 32, 60 }, fontSize = UIDefault.FontSize + 8 } )) local panelList = UIUtil.createScrollView("panel_list", 0, 0, 200, 32, { margins = { 16, 64, nil, 80 } }) panel:addChild(panelList) local panelItem = UIPanel.new("panel_item", 0, 0, panelList.size.width, 48) panelList:addChild(panelItem) panelItem:addChild(UIUtil.createImageNoPos("img_selected", { margins = { 0, 0, 0, 0 }, touchable = false, visible = true, sprite = { name = "tc:round_rect_white", color = Color.new(48, 48, 60, 222) } })) panelItem:addChild(UIUtil.createImage("lb_group_pic", 8, 8, 32, 32, { sprite = { name = "tc:conf" } })) panelItem:addChild(UIUtil.createLabel("lb_group_name", Locale.SOUND, 48, 16, 128, 24, TextAlignment.HCenter, TextAlignment.VCenter, { marginsTB = { 0, 0, false } }) ) local infoList = UIUtil.createScrollView("info_list", 0, 0, 300, 32, { margins = { 232, 64, 16, 80 }, sprite = { name = "tc:round_rect_white", color = Color.new(48, 48, 60, 160) } }) panel:addChild(infoList) local panelHold = UIUtil.createPanel("panel_hold", 0, 0, 32, 300, { marginsLR = { 0, 0 } }) infoList:addChild(panelHold) local panelSlider = UIUtil.createPanel("panel_slider", 0, 0, 32, 100, { marginsLR = { 0, 0 } }) infoList:addChild(panelSlider) panelSlider:addChild(UIUtil.createLabel("lb_title", "Value - 50%", 16, 16, 32, 32, TextAlignment.Left, TextAlignment.VCenter)) panelSlider:addChild(UIUtil.createSlider("slider", 0, 56, 100, 32, { marginsLR = { 10, 10 } })) panelSlider:addChild(UIUtil.createImage("img_line", 0, 0, 32, 2, { margins = { 16, nil, 16, 2, true, false }, sprite = { name = "tc:white", color = Color.new(20, 20, 30) } })) local panelBool = UIUtil.createPanel("panel_bool", 0, 0, 32, 64, { marginsLR = { 0, 0 } }) infoList:addChild(panelBool) panelBool:addChild(UIUtil.createLabel("lb_title", "Boolean Value", 16, 16, 32, 32, TextAlignment.Left, TextAlignment.VCenter)) panelBool:addChild(UIUtil.createSwitch("sw", 20, 16, 64, 32, { marginsLR = { nil, 16 }, selected = true })) panelBool:addChild(UIUtil.createImage("img_line", 0, 0, 32, 2, { margins = { 16, nil, 16, 2, true, false }, sprite = { name = "tc:white", color = Color.new(20, 20, 30) } })) panel:addChild(UIUtil.createButton("btn_ok", Locale.OK, 0, 200, 300, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, targetSprite = { color = Color.new(110, 108, 132, 255) }, margins = { 0, nil, 0, 16, false } })) return root end function UIDesign.getInfoPopupUI() local UI_SIZE = Size.new(500, 300) local root = UIUtil.createBlackFullScreenLayer("info_popup_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, nil) panel:addChild(UIUtil.createLabelNoPos("lb_title", Locale.TIPS, TextAlignment.HCenter, TextAlignment.VCenter, { positionY = 12, marginsLR = { 0, 0 }, fontSize = UIDefault.FontSize + 8 })) local panelInfo = UIUtil.createPanelNoPos("panel_info", { margins = { 16, 54, 16, 80 }, sprite = { name = "tc:round_rect_white", color = Color.new(28, 28, 40, 222) } }) panel:addChild(panelInfo) panelInfo:addChild(UIUtil.createPanelNoPos("bg", { margins = { 4, 4, 4, 4 }, sprite = { name = "tc:round_rect_white", color = Color.new(10, 10, 20, 222) } })) panelInfo:addChild(UIUtil.createLabelNoPos("lb_info", "gGui->OnMapDeleteEvent(event, controlID, pControl, pUserContext); mapDeleteUI->GetLabel(IDC_LABEL_INFO)->SetAlignment(AL_VCENTER | AL_HCENTER);", TextAlignment.HCenter, TextAlignment.VCenter, { horizontalOverflow = TextHorizontalOverflow.Wrap, margins = { 16, 16, 16, 16 }, color = Color.Yellow })) panel:addChild(UIUtil.createButton("btn_back", Locale.BACK, 0, 200, 200, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, UI_SIZE.width * 0.5, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_ok", Locale.OK, 0, 200, 200, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { UI_SIZE.width * 0.5, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) return root end function UIDesign.getModListUI() local UI_SIZE = Size.new(800, 450) local root = UIUtil.createBlackFullScreenLayer("mod_list_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, nil) panel:addChild(UIUtil.createLabelNoPos("lb_title", Locale.MOD_LIST, TextAlignment.HCenter, TextAlignment.VCenter, { positionY = 12, marginsLR = { 0, 0 }, fontSize = UIDefault.FontSize + 8 })) panel:addChild(UIUtil.createButton("btn_back", Locale.BACK, 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, UI_SIZE.width * 0.66, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_mod_folder", Locale.OPEN_MOD_FOLDER, 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { 0, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createButton("btn_mod_sources", Locale.MANAGER_SOURCES, 0, 200, 220, UIDefault.ButtonHeight, { anchorPoint = { 0.5, 0 }, margins = { UI_SIZE.width * 0.66, nil, 0, 16, false, false }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panel:addChild(UIUtil.createLabel("lb_list_title", string.format(Locale.ALL_MOD_LOADED, 0), 16, 64, 300, 24, TextAlignment.Left, TextAlignment.Top, { color = Color.Gray })) local panelList = UIUtil.createScrollView("panel_list", 0, 0, 300, 32, { margins = { 16, 96, nil, 80 }, }) panel:addChild(panelList) local panelItem = UIPanel.new("panel_item", 0, 0, panelList.size.width, 96) panelList:addChild(panelItem) panelItem:addChild(UIUtil.createImageNoPos("img_selected", { margins = { 0, 0, 0, 0 }, touchable = false, sprite = { name = "tc:round_rect_white", color = Color.new(48, 48, 60, 222) }, visible = false })) panelItem:addChild(UIUtil.createLabel("lb_mod_name", "ModNameHere", 96, 16, 128, 24, TextAlignment.Left, TextAlignment.VCenter)) panelItem:addChild(UIUtil.createLabel("lb_mod_tip", "the mod tip.. test for auto wrap", 96, 40, 128, 24, TextAlignment.Left, TextAlignment.Top, { marginsLR = { 96, 16 }, fontSize = UIDefault.SmallFontSize, color = Color.FrenchGray, horizontalOverflow = TextHorizontalOverflow.Wrap })) panelItem:addChild(UIUtil.createImage("img_mod_pic", 16, 16, 64, 64, { sprite = { name = "tc:round_rect_white" } })) local infoPanelList = UIUtil.createScrollViewNoPos("info_list", { margins = { 332, 64, 16, 80 }, }) panel:addChild(infoPanelList) local panelInfo1 = UIUtil.createPanel("panel_info_1", 0, 0, 32, 96, { marginsLR = { 0, 0 }, sprite = { name = "tc:round_rect_white", color = Color.new(48, 48, 60, 160) } }) infoPanelList:addChild(panelInfo1) local panelVersion = UIPanel.new("panel_version", 0, 0, 200, 96) panelInfo1:addChild(panelVersion) panelVersion:addChild(UIUtil.createLabel("lb_version_title", Locale.MOD_VERSION, 0, 16, 128, 24, TextAlignment.HCenter, TextAlignment.VCenter, { marginsLR = { 0, 0 }, color = Color.Gray })) panelVersion:addChild(UIUtil.createLabel("lb_version", "1.1.1.1", 0, 48, 128, 24, TextAlignment.HCenter, TextAlignment.VCenter, { marginsLR = { 0, 0 }, })) local panelAuthor = UIPanel.new("panel_author", 200, 0, 200, 96) panelInfo1:addChild(panelAuthor) panelAuthor:addChild(UIUtil.createLabel("lb_author_title", Locale.MOD_AUTHORS, 0, 16, 128, 24, TextAlignment.HCenter, TextAlignment.VCenter, { marginsLR = { 0, 0 }, color = Color.Gray })) panelAuthor:addChild(UIUtil.createLabel("lb_author", "Super Lazy BlueYoshi", 0, 48, 128, 24, TextAlignment.HCenter, TextAlignment.VCenter, { marginsLR = { 0, 0 } })) local panelInfoWeb = UIUtil.createPanel("panel_info_web", 0, 112, 32, 112, { marginsLR = { 0, 0 }, sprite = { name = "tc:round_rect_white", color = Color.new(48, 48, 60, 160) } }) infoPanelList:addChild(panelInfoWeb) panelInfoWeb:addChild(UIUtil.createLabel("lb_web", Locale.WEB, 16, 16, 300, 24)) panelInfoWeb:addChild(UIUtil.createButton("btn_web_1", Locale.WEB, 8, 56, 200, UIDefault.ButtonHeight, { marginsLR = { 16, nil }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) panelInfoWeb:addChild(UIUtil.createButton("btn_web_2", Locale.WEB, 200, 56, 200, UIDefault.ButtonHeight, { marginsLR = { nil, 16 }, targetSprite = { color = Color.new(110, 108, 132, 255) }, })) local panelInfo2 = UIUtil.createPanel("panel_info_2", 0, 188 + 64, 32, 400, { marginsLR = { 0, 0 }, sprite = { name = "tc:round_rect_white", color = Color.new(48, 48, 60, 160) } }) infoPanelList:addChild(panelInfo2) panelInfo2:addChild(UIUtil.createLabel("lb_des_caption", Locale.DESC, 16, 16, 300, 24)) panelInfo2:addChild(UIUtil.createLabel("lb_des", "Test Desc", 16, 48, 300, 24, TextAlignment.Left, TextAlignment.Top, { marginsLR = { 16, 16 }, color = Color.FrenchGray, horizontalOverflow = TextHorizontalOverflow.Wrap })) return root end function UIDesign.getTipUI() local UI_SIZE = Size.new(100, 100) local root = UIUtil.createPanel("tip_ui", 0, 0, UI_SIZE.width, UI_SIZE.height, { sprite = { name = "tc:window_frame_01", color = Color.new(255, 255, 255, 200) }, touchable = false }) root:addChild(UIUtil.createLabel("lb_tip", "This is a tip", 8, 8, 32, 32, TextAlignment.Left, TextAlignment.Top, { fontSize = UIDefault.SmallFontSize, color = Color.new(224, 224, 224, 255), isRichText = true, autoAdaptSize = true, })) return root end function UIDesign.getHudUI() local root = UIUtil.createPanel("hud_ui", 0, 0, GameWindow.displayResolution.width, GameWindow.displayResolution.height, { margins = { 0, 0, 0, 0, true, true }, touchable = false }) local panelElementBase = UIUtil.createPanel("panel_element_base", 0, 0, 32, 32) root:addChild(panelElementBase) root:addChild(UIUtil.createLabel("lb_music_name", "Music:Name", 0, 0, 32, 32, TextAlignment.Right, TextAlignment.Top, { margins = { nil, nil, 16, 32 }, fontSize = UIDefault.SmallFontSize, color = Color.new(155, 155, 155) } )) root:addChild(UIUtil.createLabel("lb_music_author", "MusicAuthor", 0, 0, 32, 32, TextAlignment.Right, TextAlignment.Top, { margins = { nil, nil, 16, 8 }, fontSize = UIDefault.SmallFontSize, color = Color.new(100, 100, 100) } )) local joystickCenter = UIJoystick.new("joystick_center") joystickCenter:setSize(300, 300) --joystickCenter.backSprite = UISpritePool:get("tc:joystick_base") --joystickCenter.frontSprite = UISpritePool:get("tc:joystick_controlled_aim") UIUtil.setMargins(joystickCenter, 0, 0, 0, 0, false, false) joystickCenter.controlRadius = 96 root:addChild(joystickCenter) local joystickLeft = UIJoystick.new("joystick_left") joystickLeft:setSize(250, 250) joystickLeft.backSprite = UISpritePool:get("tc:joystick_base") joystickLeft.frontSprite = UISpritePool:get("tc:joystick_controlled") joystickLeft.leftMarginEnabled = true joystickLeft.bottomMarginEnabled = true joystickLeft.controlRadius = 64 joystickLeft.backSprite.color = Color.new(255, 255, 255, 128) joystickLeft.frontSprite.color = Color.new(255, 255, 255, 128) root:addChild(joystickLeft) local joystickRight = UIJoystick.new("joystick_right") joystickRight:setSize(250, 250) joystickRight.backSprite = UISpritePool:get("tc:joystick_base") joystickRight.frontSprite = UISpritePool:get("tc:joystick_controlled_aim") joystickRight.rightMarginEnabled = true joystickRight.bottomMarginEnabled = true joystickRight.controlRadius = 96 joystickRight.backSprite.color = Color.new(255, 255, 255, 128) joystickRight.frontSprite.color = Color.new(255, 255, 255, 128) root:addChild(joystickRight) local panelBtn = UIUtil.createPanel("panel_btn", 0, 0, 54 * 6, 48, { margins = { 0, 8, 0, nil, false, false }, anchorPoint = { 0.5, 0 }, }) root:addChild(panelBtn) ---_setBtn ---@param btn UIButton local function _setBtn(btn, spriteName) local sprite = UISpritePool:get(spriteName) local color = Color.new(255, 255, 255, 200) btn.targetSprite = sprite btn.targetSprite.color = color btn.selectedSprite = sprite btn.selectedSprite.color = color btn.pressedSprite = sprite btn.pressedSprite.color = color btn.highlightedSprite = sprite btn.highlightedSprite.color = color end local check_box_front_or_wall = UIUtil.createButton("check_box_front_or_wall", "", 0, 0, 48, 48) _setBtn(check_box_front_or_wall, "tc:check_box_front_or_wall") panelBtn:addChild(check_box_front_or_wall) local check_box_smart = UIUtil.createButton("check_box_smart", "", 54 * 1, 0, 48, 48) _setBtn(check_box_smart, "tc:check_box_smart") panelBtn:addChild(check_box_smart) local button_recipe = UIUtil.createButton("button_recipe", "", 54 * 2, 0, 48, 48) _setBtn(button_recipe, "tc:button_recipe") panelBtn:addChild(button_recipe) local button_task = UIUtil.createButton("button_task", "", 54 * 3, 0, 48, 48) _setBtn(button_task, "tc:button_task") panelBtn:addChild(button_task) local btnBackpack = UIUtil.createButton("button_backpack", "", 54 * 4, 0, 48, 48) _setBtn(btnBackpack, "tc:button_backpack") panelBtn:addChild(btnBackpack) local btnOption = UIUtil.createButton("button_option", "", 54 * 5, 0, 48, 48) _setBtn(btnOption, "tc:button_option") panelBtn:addChild(btnOption) root:addChild(UIUtil.createLabel("lb_debug", "FPS", 32, 200, 32, 32)) root:addChild(UIUtil.createLabel("lb_hp", "114/514", 32, 128, 32, 32)) root:addChild(UIUtil.createLabel("lb_mana", "114/514", 32, 128, 32, 32)) local panelShortcut = UIUtil.createPanel("panel_shortcut", 0, 0, 56 * 10, 56, { margins = { 0, nil, 0, 0, false, false }, anchorPoint = { 0.5, 0 }, }) root:addChild(panelShortcut) -- 0-9: shortcut slots for i = 0, 9 do panelShortcut:addChild(UIUtil.createSlotStyle("slot", i * 56, 0, 56, 56, 2), i) end panelShortcut:addChild(UIUtil.createLabel("lb_exp", "114514", 0, -38, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter, { margins = { 0, nil, 0, nil, false, false }, isRichText = true, fontSize = UIDefault.SmallFontSize, } )) panelShortcut:addChild(UIUtil.createLabel("lb_item_name", "Test Item Name", 0, -68, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter, { margins = { 0, nil, 0, nil, false, false }, } )) -- advancement tips local panelAdvancements = UIUtil.createPanel("panel_advancements", 0, 0, 32, 32, { margins = { nil, 0, 0, nil }, touchable = false }) root:addChild(panelAdvancements) local ADVANCEMENT_TIP_SIZE = Size.new(400, 80) local panelAdvancementTip = UIUtil.createPanel("panel_advancement_tip", 0, 0, ADVANCEMENT_TIP_SIZE.width, ADVANCEMENT_TIP_SIZE.height, { margins = { nil, 0, 0, nil }, sprite = { name = "tc:advance_tip", color = Color.new(200, 200, 200, 255) }, touchable = false, visible = false, }) panelAdvancements:addChild(panelAdvancementTip) panelAdvancementTip:addChild(UIUtil.createPanel("panel_icon", 8, 8, 64, 64)) panelAdvancementTip:addChild(UIUtil.createLabel("lb_caption", Locale.GET_ADVANCEMENT, 72, 8, 32, 32, TextAlignment.Left, TextAlignment.VCenter, { fontSize = UIDefault.FontSize, color = Color.new(240, 240, 0, 255), isRichText = true, })) panelAdvancementTip:addChild(UIUtil.createLabel("lb_sub_caption", "", 72, 40, 32, 32, TextAlignment.Left, TextAlignment.VCenter, { fontSize = UIDefault.FontSize, color = Color.new(224, 224, 224, 255), isRichText = true, })) return root end function UIDesign.getItemListUI() end function UIDesign.getAdvancementUI() local root = UIUtil.createBlackFullScreenLayer("advancement_ui") local panelScroll = UIUtil.createScrollViewNoPos("scroll", { margins = { 0, 0, 0, 0, true, true } }) root:addChild(panelScroll) local panel = UIUtil.createPanel("panel", 0, 0, 300, 300) panelScroll:addChild(panel) root:addChild(UIUtil.createButton("btn_ok", Locale.BACK, 0, 0, 200, UIDefault.ButtonHeight, { margins = { 0, nil, 0, 32, false, false } })) return root end function UIDesign.getBackpackUI() local UI_SIZE = Size.new(512, 468) local root = UIUtil.createBlackFullScreenLayer("backpack_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, { style = "Gray", }) -- Equipment panel:addChild(UIUtil.createLabel("lb_equipment", Locale.EQUIPMENT, 16, 8, 32, 32, TextAlignment.Left, TextAlignment.VCenter, { fontSize = UIDefault.SmallFontSize, color = Color.Gray })) -- Appearance panel:addChild(UIUtil.createLabel("lb_appearance", Locale.APPEAR_ACCESSORY, 236, 8, 32, 32, TextAlignment.Right, TextAlignment.VCenter, { fontSize = UIDefault.SmallFontSize, color = Color.Gray })) -- Crafting panel:addChild(UIUtil.createLabel("lb_crafting", Locale.CRAFT, 286, 32, 32, 32, TextAlignment.Left, TextAlignment.VCenter, { fontSize = UIDefault.SmallFontSize, color = Color.Gray })) local inventoryStartY = UI_SIZE.height - 268 local statusStartY = 42 panel:addChild(UIUtil.createPanel("panel_status", 68, statusStartY, 100, 142, { sprite = { name = "tc:base2", color = Color.new(188, 188, 188, 200) } })) panel:addChild(UIUtil.createImage("img_craft_arrow", 393, 103, 32, 24, { sprite = { name = "tc:arrow3", color = Color.new(100, 100, 100, 188) } })) -- 0-9: shortcut slots for i = 0, 9 do panel:addChild(UIUtil.createSlot("slot", 16 + i * UIDefault.CellOffset, inventoryStartY + 204), i) end -- 10-49: inner backpack slots for i = 0, 39 do panel:addChild(UIUtil.createSlot("slot", 16 + math.fmod(i, 10) * UIDefault.CellOffset, inventoryStartY + math.floor(i / 10) * UIDefault.CellOffset), 10 + i) end local dressIconNames = { "tc:helmet", "tc:chestplate", "tc:leggings" } -- 50-52: equipment slots for i = 0, 2 do panel:addChild(UIUtil.createSlot("slot", 16, statusStartY + i * UIDefault.CellOffset, UIDefault.CellSize, UIDefault.CellSize, dressIconNames[i + 1] ), 50 + i) end -- 53-55: appearance slots for i = 0, 2 do panel:addChild(UIUtil.createSlot("slot", 174, statusStartY + i * UIDefault.CellOffset, UIDefault.CellSize, UIDefault.CellSize, dressIconNames[i + 1] ), 53 + i) end -- 56-64: crafting input slots, only display 4 slots local displays = { [0] = true, [1] = true, [3] = true, [4] = true } for i = 0, 8 do local c = UIUtil.createSlot("slot", 286 + math.fmod(i, 3) * UIDefault.CellOffset, statusStartY + UIDefault.CellOffset / 3 + math.floor(i / 3) * UIDefault.CellOffset) c.visible = displays[i] ~= nil and true or false panel:addChild(c, 56 + i) end -- 65: crafting result slots panel:addChild(UIUtil.createSlot("slot", 436, statusStartY + UIDefault.CellOffset, UIDefault.CellSize, UIDefault.CellSize, "tc:hammer"), 65) -- 66-68: accessory slots for i = 0, 2 do panel:addChild(UIUtil.createSlot("slot", 222, statusStartY + i * UIDefault.CellOffset, UIDefault.CellSize, UIDefault.CellSize ), 66 + i) end -- 69: drop slots panel:addChild(UIUtil.createSlot("slot", UI_SIZE.width + 16, UI_SIZE.height - 154, UIDefault.CellSize, UIDefault.CellSize, "tc:trash"), 69) panel:addChild(UIUtil.createButtonWithImage("btn_recipe", "tc:recipe_book", UI_SIZE.width + 16, UI_SIZE.height - UIDefault.ButtonHeight, UIDefault.ButtonHeight, UIDefault.ButtonHeight, { targetSprite = { color = Color.new(128, 128, 128) } })) panel:addChild(UIUtil.createButtonWithImage("btn_sort", "tc:sort", UI_SIZE.width + 16, UI_SIZE.height - UIDefault.ButtonHeight - 54, UIDefault.ButtonHeight, UIDefault.ButtonHeight, { targetSprite = { color = Color.new(128, 128, 128) } })) return root end function UIDesign.getRecipeBookUI() local UI_SIZE = Size.new(372, 468) local panel = UIUtil.createWindowPattern(nil, UI_SIZE, { style = "Gray", }) local panelList = UIUtil.createScrollView("panel_list", 0, 0, 336, 32, { margins = { 0, 16, 0, 16, false, true }, }) panelList.isScrollHorizontal = false panelList.isScrollVertical = true panel:addChild(panelList) local panelItem = UIUtil.createSlotStyle("panel_item", 0, 0, UIDefault.CellHugeSize, UIDefault.CellHugeSize, 4) panelList:addChild(panelItem) return panel end function UIDesign.getNeiUI() local UI_SIZE = Size.new(622, 380) local UI_LIST_WIDTH = UIDefault.CellSize * 6 local TAB_SIZE = 54 local root = UIUtil.createBlackFullScreenLayer("nei_ui") local infoPanel = UIUtil.createWindowPattern(root, UI_SIZE, { style = "Gray", }) UIUtil.setMargins(infoPanel, 0, 0, UI_LIST_WIDTH, 0, false, false) local panelSearch = UIUtil.createPanel("panel_search", 0, 0, UI_LIST_WIDTH, 32, { margins = { nil, 8, 8, 8, false, true } }) root:addChild(panelSearch) local panelCells = UIUtil.createPanel("panel_cells", 0, 0, 32, 32, { margins = { 0, 64, 0, 32, true, true } }) panelSearch:addChild(panelCells) panelSearch:addChild(UIUtil.createLabel("lb_page", "114/514", 0, 0, UI_LIST_WIDTH, 48, TextAlignment.HCenter, TextAlignment.VCenter, { fontSize = UIDefault.FontSize, })) panelSearch:addChild(UIUtil.createButtonWithImage("btn_prev", "tc:arrow1", 0, 0, 48, 48, { targetSprite = { color = Color.new(128, 128, 128) } })) panelSearch:addChild(UIUtil.createButtonWithImage("btn_next", "tc:arrow2", UI_LIST_WIDTH - 48, 0, 48, 48, { targetSprite = { color = Color.new(128, 128, 128) } })) root:addChild(UIUtil.createButton("btn_search_mode", Locale.SEARCH_FROM_OUTPUT, 8, 8, 160, 48, { margins = { nil, nil, UI_LIST_WIDTH + 32, 8 }, targetSprite = { color = Color.new(128, 128, 128) } })) root:addChild(UIUtil.createButton("btn_back_history", Locale.PRE_ITEM, 8, 8, 160, 48, { margins = { nil, nil, UI_LIST_WIDTH + 32, nil }, targetSprite = { color = Color.new(128, 128, 128) } })) local panelCell = UIUtil.createPanel("panel_cell", 0, 0, UIDefault.CellSize, UIDefault.CellSize, { sprite = { name = "tc:white", color = Color.new(100, 100, 100, 100) } }) panelSearch:addChild(panelCell) local panelTabs = UIUtil.createPanel("panel_tabs", 16, -TAB_SIZE + 7, TAB_SIZE, TAB_SIZE) infoPanel:addChild(panelTabs) local panelTab = UIUtil.createPanel("panel_tab", 16, -TAB_SIZE + 7, TAB_SIZE, TAB_SIZE, { sprite = { name = "tc:tab_clicked", } }) infoPanel:addChild(panelTab) local panelPositionDetail = UIUtil.createPanel("panel_position_detail", 0, 0, 360 - 16, 32, { margins = { nil, 16, 8, 16, false, true } }) infoPanel:addChild(panelPositionDetail) panelPositionDetail:addChild(UIUtil.createPanel("panel_detail", 0, 0, 344, 300, { margins = { 0, 0, 0, 0, false, false } })) infoPanel:addChild(UIUtil.createLabel("lb_recipe_name", "", 0, 0, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter, { margins = { 0, 8, 360, nil, true, false } })) local panelList = UIUtil.createScrollView("panel_list", 0, 0, 32, 32, { margins = { 16, 40, 360, 16, true, true }, sprite = { name = "tc:base_list_cell", } }) infoPanel:addChild(panelList) local panelItem = UIUtil.createPanel("panel_item", 0, 0, 32, 32, { sprite = { name = "tc:base_list_cell", } }) panelList:addChild(panelItem) local panelPreviewCell = UIUtil.createPanel("panel_preview_cell", 0, 0, UIDefault.CellSize, UIDefault.CellSize, { sprite = { name = "tc:white", color = Color.new(100, 100, 100, 0) } }) panelItem:addChild(panelPreviewCell) panelItem:addChild(UIUtil.createPanel("img_arrow", 0, 0, 32, 24, { sprite = { name = "tc:arrow3", color = Color.Gray }, touchable = false, })) return root end function UIDesign.generateBackpackPattern(panel, UI_SIZE) panel:addChild(UIUtil.createLabel("lb_inventory", Locale.INVENTORY, 16, 170, 32, 32, TextAlignment.Left, TextAlignment.VCenter, { fontSize = UIDefault.SmallFontSize, color = Color.Gray })) local inventoryStartY = UI_SIZE.height - 268 -- 0-9: shortcut slots for i = 0, 9 do panel:addChild(UIUtil.createSlot("slot", 16 + i * UIDefault.CellOffset, inventoryStartY + 204), i) end -- 10-49: inner backpack slots for i = 0, 39 do panel:addChild(UIUtil.createSlot("slot", 16 + math.fmod(i, 10) * UIDefault.CellOffset, inventoryStartY + math.floor(i / 10) * UIDefault.CellOffset), 10 + i) end end function UIDesign.getCraft3xUI() local UI_SIZE = Size.new(512, 468) local root = UIUtil.createBlackFullScreenLayer("craft3x_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, { style = "Gray", }) panel:addChild(UIUtil.createLabel("lb_title", Locale.CRAFT, 100, 8, 32, 32, TextAlignment.Left, TextAlignment.VCenter, { fontSize = UIDefault.SmallFontSize, color = Color.Gray })) UIDesign.generateBackpackPattern(panel, UI_SIZE) local offsetX = 100 local offsetY = 38 -- 50-58: input for i = 0, 8 do panel:addChild(UIUtil.createSlot("slot_input", offsetX + UIDefault.CellSize * (i % 3), offsetY + UIDefault.CellSize * math.floor(i / 3), UIDefault.CellSize, UIDefault.CellSize), 50 + i) end -- 59: output panel:addChild(UIUtil.createSlot("slot_output", offsetX + 240, offsetY + UIDefault.CellSize * 1.5 - UIDefault.CellLargeSize * 0.5, UIDefault.CellLargeSize, UIDefault.CellLargeSize), 50 + 9) panel:addChild(UIUtil.createImage("img_arrow", offsetX + 170, offsetY + 56, 40, 32, { sprite = { name = "tc:arrow4", color = Color.new(100, 100, 100), } })) panel:addChild(UIUtil.createButtonWithImage("btn_recipe", "tc:recipe_book", UI_SIZE.width + 16, UI_SIZE.height - UIDefault.ButtonHeight, UIDefault.ButtonHeight, UIDefault.ButtonHeight, { targetSprite = { color = Color.new(128, 128, 128) } })) return root end function UIDesign.getSmeltUI() local UI_SIZE = Size.new(512, 468) local root = UIUtil.createBlackFullScreenLayer("smelt_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, { style = "Gray", }) panel:addChild(UIUtil.createLabel("lb_title", Locale.FURNACE, 240, 8, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter, { fontSize = UIDefault.SmallFontSize, color = Color.Gray })) UIDesign.generateBackpackPattern(panel, UI_SIZE) local offsetX = 160 local offsetY = 38 -- 50: input 51: fuel 52: output 53: back panel:addChild(UIUtil.createSlot("slot_input", offsetX, offsetY, UIDefault.CellSize, UIDefault.CellSize), 50) panel:addChild(UIUtil.createSlot("slot_fuel", offsetX, offsetY + 88, UIDefault.CellSize, UIDefault.CellSize, "tc:fire"), 51) panel:addChild(UIUtil.createSlot("slot_output", offsetX + 150, offsetY + 40, UIDefault.CellLargeSize, UIDefault.CellLargeSize), 52) panel:addChild(UIUtil.createSlot("slot_back", offsetX - 60, offsetY + 88, UIDefault.CellSize, UIDefault.CellSize, "tc:fuel_return"), 53) panel:addChild(UIUtil.createImage("img_cook", offsetX + 80, offsetY + 52, 40, 32, { sprite = { name = "tc:process_00", } })) panel:addChild(UIUtil.createImage("img_burn", offsetX + 8, offsetY + 52, 30, 30, { sprite = { name = "tc:burn_00" } })) panel:addChild(UIUtil.createButtonWithImage("btn_recipe", "tc:recipe_book", UI_SIZE.width + 16, UI_SIZE.height - UIDefault.ButtonHeight, UIDefault.ButtonHeight, UIDefault.ButtonHeight, { targetSprite = { color = Color.new(128, 128, 128) } })) return root end function UIDesign.getEnchantmentUI() local UI_SIZE = Size.new(512, 468) local root = UIUtil.createBlackFullScreenLayer("enchantment_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, { style = "Gray", }) panel:addChild(UIUtil.createLabel("lb_title", Locale.ENCHANT, 60, 8, 32, 32, TextAlignment.Left, TextAlignment.VCenter, { fontSize = UIDefault.SmallFontSize, color = Color.Gray })) UIDesign.generateBackpackPattern(panel, UI_SIZE) -- 50-51: tool, lapis panel:addChild(UIUtil.createSlot("slot_tool", 60, 42, UIDefault.CellLargeSize, UIDefault.CellLargeSize, "tc:hammer"), 50) panel:addChild(UIUtil.createSlot("slot_lapis", 65, 120, UIDefault.CellSize, UIDefault.CellSize, "tc:lapis_lazuli_gray"), 51) local BTN_X, BTN_Y = 160, 30 local BTN_WIDTH, BTN_HEIGHT = 336, 48 for i = 1, 3 do local panelBtn = UIUtil.createPanel(string.format("panel_btn_%d", i), BTN_X, BTN_Y + (i - 1) * BTN_HEIGHT, BTN_WIDTH, BTN_HEIGHT, { sprite = { name = "tc:base_list_cell_highlight_2", } }) panel:addChild(panelBtn) panelBtn:addChild(UIUtil.createImage("img_exp", 12, 8, 32, 32, { sprite = { name = string.format("tc:enchantment_exp_%d", i), }, touchable = false })) panelBtn:addChild(UIUtil.createLabel("lb_cost", "3", 40, 8, 32, 32, TextAlignment.Left, TextAlignment.VCenter, { color = Color.Yellow } )) panelBtn:addChild(UIUtil.createLabel("lb_exp", "30", 290, 8, 32, 32, TextAlignment.Right, TextAlignment.VCenter, { color = Color.Yellow } )) panelBtn:addChild(UIUtil.createLabel("lb_preview", "精准采集IV ...", 160, 8, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter, { color = Color.Gray } )) end return root end function UIDesign.getRepairUI() local UI_SIZE = Size.new(512, 468) local root = UIUtil.createBlackFullScreenLayer("repair_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, { style = "Gray", }) panel:addChild(UIUtil.createLabel("lb_title", Locale.REPAIR, 240, 8, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter, { fontSize = UIDefault.FontSize, color = Color.Gray })) UIDesign.generateBackpackPattern(panel, UI_SIZE) local offsetX, offsetY = 100, 90 -- 50-52: tool, source, output panel:addChild(UIUtil.createSlot("slot_tool", offsetX + 0, offsetY + 0, UIDefault.CellSize, UIDefault.CellSize, "tc:hammer"), 50) panel:addChild(UIUtil.createSlot("slot_source", offsetX + 120, offsetY + 0, UIDefault.CellSize, UIDefault.CellSize, "tc:ingot_gray"), 51) panel:addChild(UIUtil.createSlot("slot_output", offsetX + 250, offsetY - 5, UIDefault.CellLargeSize, UIDefault.CellLargeSize, "tc:hammer"), 52) panel:addChild(UIUtil.createLabel("lb_exp", "附魔消耗:22", offsetX + 130, offsetY + 54, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter, { color = Color.Yellow, visible = false, } )) panel:addChild(UIUtil.createImage("img_add", offsetX + 68, offsetY + 8, 32, 32, { sprite = { name = "tc:adding", } })) panel:addChild(UIUtil.createImage("img_process", offsetX + 190, offsetY + 8, 40, 32, { sprite = { name = "tc:process_00", } })) panel:addChild(UIUtil.createButtonWithImage("btn_recipe", "tc:recipe_book", UI_SIZE.width + 16, UI_SIZE.height - UIDefault.ButtonHeight, UIDefault.ButtonHeight, UIDefault.ButtonHeight, { targetSprite = { color = Color.new(128, 128, 128) } })) return root end function UIDesign.getBrewingUI() local UI_SIZE = Size.new(512, 468) local root = UIUtil.createBlackFullScreenLayer("brewing_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, { style = "Gray", }) panel:addChild(UIUtil.createLabel("lb_title", Locale.BREWING_STAND, 240, 8, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter, { fontSize = UIDefault.SmallFontSize, color = Color.Gray })) UIDesign.generateBackpackPattern(panel, UI_SIZE) local offsetX = 240 local offsetY = 38 panel:addChild(UIUtil.createImage("img_tube", offsetX, offsetY + 52, 30, 30, { sprite = { name = "tc:tube" } })) panel:addChild(UIUtil.createImage("img_process", offsetX + 38, offsetY + 12, 24, 80, { sprite = { name = "tc:brewing_process_00", } })) panel:addChild(UIUtil.createImage("img_bubble", offsetX - 48, offsetY + 4, 40, 64, { sprite = { name = "tc:brewing_bubble_00" } })) panel:addChild(UIUtil.createImage("img_fuel", offsetX - 48, offsetY + 70, 40, 12, { sprite = { name = "tc:brewing_fuel_00" } })) -- 50: potion 51: source 52: output 53: fuel panel:addChild(UIUtil.createSlot("slot_potion", offsetX - 82, offsetY + 88, UIDefault.CellSize, UIDefault.CellSize, "tc:glass_bottle"), 50) panel:addChild(UIUtil.createSlot("slot_input", offsetX - 8, offsetY, UIDefault.CellSize, UIDefault.CellSize), 51) panel:addChild(UIUtil.createSlot("slot_output", offsetX + 66, offsetY + 80, UIDefault.CellLargeSize, UIDefault.CellLargeSize, "tc:glass_bottle"), 52) panel:addChild(UIUtil.createSlot("slot_fuel", offsetX - 100, offsetY, UIDefault.CellSize, UIDefault.CellSize, "tc:blaze_powder"), 53) panel:addChild(UIUtil.createButtonWithImage("btn_recipe", "tc:recipe_book", UI_SIZE.width + 16, UI_SIZE.height - UIDefault.ButtonHeight, UIDefault.ButtonHeight, UIDefault.ButtonHeight, { targetSprite = { color = Color.new(128, 128, 128) } })) return root end function UIDesign.getChest30UI() local UI_SIZE = Size.new(512, 468) local root = UIUtil.createBlackFullScreenLayer("chest30_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, { style = "Gray", }) panel:addChild(UIUtil.createLabel("lb_title", Locale.STORAGE, 16, 4, 32, 32, TextAlignment.Left, TextAlignment.VCenter, { fontSize = UIDefault.SmallFontSize, color = Color.Gray })) UIDesign.generateBackpackPattern(panel, UI_SIZE) local offsetX = 240 local offsetY = 34 for i = 0, 29 do panel:addChild(UIUtil.createSlot("slot", 16 + math.fmod(i, 10) * UIDefault.CellOffset, offsetY + math.floor(i / 10) * UIDefault.CellOffset), 50 + i) end local btnOffsetY = 76 panel:addChild(UIUtil.createButton("btn_sort", Locale.ARRANGE, 528, btnOffsetY, 160, UIDefault.ButtonHeight)) panel:addChild(UIUtil.createButton("btn_quick_pick", Locale.QUICK_PICK, 528, btnOffsetY + UIDefault.ButtonOffset, 160, UIDefault.ButtonHeight)) panel:addChild(UIUtil.createButton("btn_quick_push", Locale.QUICK_PUSH, 528, btnOffsetY + UIDefault.ButtonOffset * 2, 160, UIDefault.ButtonHeight)) panel:addChild(UIUtil.createButton("btn_quick_stack", Locale.QUICK_STACK, 528, btnOffsetY + UIDefault.ButtonOffset * 3, 160, UIDefault.ButtonHeight)) return root end function UIDesign.getShooter9UI() local UI_SIZE = Size.new(512, 468) local root = UIUtil.createBlackFullScreenLayer("shooter9_ui") local panel = UIUtil.createWindowPattern(root, UI_SIZE, { style = "Gray", }) panel:addChild(UIUtil.createLabel("lb_title", Locale.STORAGE, 16, 4, 32, 32, TextAlignment.Left, TextAlignment.VCenter, { fontSize = UIDefault.SmallFontSize, color = Color.Gray })) UIDesign.generateBackpackPattern(panel, UI_SIZE) local offsetX = 240 local offsetY = 34 for i = 0, 8 do panel:addChild(UIUtil.createSlot("slot", 16 + math.fmod(i, 3) * UIDefault.CellOffset, offsetY + math.floor(i / 3) * UIDefault.CellOffset), 50 + i) end return root end function UIDesign.getDeathUI() local root = UIUtil.createBlackFullScreenLayer("death_ui") local panel = UIUtil.createPanel("panel", 0, 0, 100, 200, { margins = { 0, 0, 0, 0, false, false } }) root:addChild(panel) panel:addChild(UIUtil.createLabel("lb_title", Locale.YOU_DIED, 0, 0, 100, 32, TextAlignment.HCenter, TextAlignment.VCenter, { fontSize = 60, color = Color.Red, })) panel:addChild(UIUtil.createLabel("lb_title_2", "重生中... 3", 0, 100, 100, 32, TextAlignment.HCenter, TextAlignment.VCenter, { fontSize = 40, color = Color.Red, })) return root end return UIDesign ================================================ FILE: ui/UILayerDefine.lua ================================================ local UILayerDefine = { BaseLayer = 1, AdvancementTipsLayer = 2, Totals = 2, } return UILayerDefine ================================================ FILE: ui/UIManager.lua ================================================ ---@class TC.UIManager local UIManager = class("UIManager") local OrderedArray = require("util.OrderedArray") local UISpritePool = require("UISpritePool") local MouseItemData = require("MouseItemData") local SettingsData = require("settings.SettingsData") local UILayerDefine = require("UILayerDefine") local g_instance ---@return TC.UIManager function UIManager.getInstance() if g_instance == nil then g_instance = UIManager.new() end return g_instance end function UIManager:__init() self.spritePool = UISpritePool.getInstance() self.canvasGameObject = nil self.canvas = nil self.baseLayers = {} ---@type UINode[] self.baseLayer = nil self.debugCanvasGameObject = nil self.debugCanvas = nil self._windowsLoaded = OrderedArray.new() self.durableBarTexture = nil self.cursorTexture = nil end function UIManager:init() self.canvasGameObject = GameObject.instantiate() self.canvasGameObject.canvas:init() self.canvas = self.canvasGameObject.canvas.uiRoot for i = 1, UILayerDefine.Totals do local layerName = string.format("layer_%d", i) local panel = UIPanel.new(layerName) panel:setLeftMargin(0, true) panel:setRightMargin(0, true) panel:setTopMargin(0, true) panel:setBottomMargin(0, true) panel.autoStretchWidth = true panel.autoStretchHeight = true panel.touchable = false self.canvas:addChild(panel) table.insert(self.baseLayers, panel) end self.canvas:applyMargin() self.baseLayer = self.baseLayers[UILayerDefine.BaseLayer] self:initDebug() self:onWindowResize() end function UIManager:initDebug() self.debugCanvasGameObject = GameObject.instantiate() self.debugCanvasGameObject.canvas:init() self.debugCanvas = self.debugCanvasGameObject.canvas.uiRoot self.debugCanvas.touchable = false self.debugRect = nil self.debugPoint = nil local panel = UIPanel.new("panel") panel:setMarginEnabled(true, true, true, true) panel.autoStretchWidth = true panel.autoStretchHeight = true self.debugCanvas:addChild(panel) local textDebug = UIText.new("text", 0, 0, 32, 32) textDebug.horizontalOverflow = TextHorizontalOverflow.Overflow textDebug.color = Color.Yellow panel:addChild(textDebug) local textDebug2 = UIText.new("text2", 32, 180, 32, 32) textDebug2:setBottomMargin(100, true) textDebug2.horizontalOverflow = TextHorizontalOverflow.Overflow textDebug2.isRichText = true textDebug2.fontSize = 18 panel:addChild(textDebug2) end ---addWindowsLoaded ---@param uiWindow TC.UIWindow ---@return number function UIManager:addWindowsLoaded(uiWindow) --self.canvas:addChild(uiWindow.root) self.baseLayer:addChild(uiWindow.root) return self._windowsLoaded:add(uiWindow) end function UIManager:removeWindowsLoaded(index) --self.canvas:removeChild(self._windowsLoaded:get(index).root) self.baseLayer:removeChild(self._windowsLoaded:get(index).root) self._windowsLoaded:remove(index) end ---initUISpriteResources ---@param mod Mod ---@param uiSpriteResourcePathInMod string function UIManager:initUISpriteResources(mod, uiSpriteResourcePathInMod) local searchPath = Path.join(mod.assetRootPath, uiSpriteResourcePathInMod) --print(searchPath) local texNames = AssetManager.getAllFiles(searchPath, ".png", true, false, true) for _, texPath in pairs(texNames) do local absPath = Path.join(searchPath, texPath) .. ".png" local texName = mod.modId .. ":" .. texPath UITexturePool.register(texName, TextureManager.load(absPath)) end for _, texPath in pairs(texNames) do local texName = mod.modId .. ":" .. texPath local cfgPath = Path.join(searchPath, texPath) .. ".json" local sprite if AssetManager.isPathExist(cfgPath) then sprite = UISprite.new() local json = AssetManager.readAsString(cfgPath) sprite:fromJson(json) else sprite = UISprite.new(texName) end --print("loading sprite: " .. texName) self.spritePool:add(texName, sprite) end end function UIManager:postInit() self.durableBarTexture = self.spritePool:get("tc:durable").textureLocation self.cursorTexture = self.spritePool:get("tc:cursor2").textureLocation ---@param mod Mod for _, mod in each(Mod.modList) do local modIconPath = Path.join(mod.assetRootPath, "mod_icon.png") if AssetManager.isPathExist(modIconPath) then local texName = mod.modId .. ":__icon" UITexturePool.register(texName, TextureManager.load(modIconPath)) local sprite = UISprite.new(texName) self.spritePool:add(texName, sprite) end end end function UIManager:update() if SettingsData.isShowUIDebug or SettingsData.isShowDebugInfo then self.debugCanvas.visible = true local lbText = UIText.cast(self.debugCanvas:getChild("panel.text")) local lbText2 = UIText.cast(self.debugCanvas:getChild("panel.text2")) lbText.visible = false lbText2.visible = false if SettingsData.isShowDebugInfo then lbText2.text = string.format("FPS:%d \nLogic:%d \nBatches:%d \nTriangles:%d", IntegratedClient.main.fps, IntegratedClient.main.gameSpeed, GraphicsDevice.drawCalls, GraphicsDevice.primitiveCount ) lbText2.visible = true end if SettingsData.isShowUIDebug then local pointer = self.canvas:screenPointToCanvasPoint(Input.mouse.position) --local node = self.canvas:getPointedNode(pointer) local node = self.baseLayer:getPointedNode(pointer) if node:valid() then local nodeScreenPos = self.canvas:canvasPointToScreenPoint(node.positionInCanvas) local bound = RectFloat.new(nodeScreenPos.x, nodeScreenPos.y, node.size.width, node.size.height) self.debugRect = bound self.debugPoint = Vector2.new( bound.x + bound.width * node.anchorPointX, bound.y + bound.height * node.anchorPointY ) lbText.fontSize = 16 lbText.text = node.name .. " (position:" .. tostring(node.positionInCanvas) .. " size:" .. tostring(node.size) .. ")" else self.debugRect = nil self.debugPoint = nil lbText.text = "[UI Debug Mode]" end lbText.visible = true end else self.debugCanvas.visible = false end if ClientState.current == ClientState.Gaming then MouseItemData.getInstance():update() end end function UIManager:render() if SettingsData.isShowUIDebug then if self.debugRect ~= nil then GraphicsDevice.drawRect2D(self.debugRect, Color.new(255, 255, 0, 20)) GraphicsDevice.drawRectHollow2D(self.debugRect, Color.new(255, 255, 0, 200)) end if self.debugPoint ~= nil then GraphicsDevice.drawRect2D(RectFloat.new(self.debugPoint.x - 2, self.debugPoint.y - 2, 4, 4), Color.new(255, 255, 0, 200)) end end if ClientState.current == ClientState.Gaming then MouseItemData.getInstance():render() end if not SettingsData.isMobileOperation then Sprite.beginBatch() local area = TextureManager.getSourceRect(self.cursorTexture) Sprite.draw(self.cursorTexture, Input.mouse.position, area, Color.White) Sprite.endBatch() Input.mouse:setCursorVisible(false) else Input.mouse:setCursorVisible(true) end end function UIManager:isWindowOpened(uiClassName) for _, index in ipairs(self._windowsLoaded.indices) do ---@type TC.UIWindow local uiWindow = self._windowsLoaded:get(index) if uiWindow.uiClassName == uiClassName then return true end end return false end function UIManager:hasUIGroup(uiGroup) for _, index in ipairs(self._windowsLoaded.indices) do ---@type TC.UIWindow local uiWindow = self._windowsLoaded:get(index) if uiWindow.uiGroup == uiGroup then return true end end return false end function UIManager:onWindowResize() self.canvas.size = GameWindow.displayResolution self.canvas:applyMargin() self.debugCanvas.size = GameWindow.displayResolution self.debugCanvas:applyMargin() for _, index in ipairs(self._windowsLoaded.indices) do ---@type TC.UIWindow local uiWindow = self._windowsLoaded:get(index) uiWindow:onWindowResize() end end function UIManager:_onEscPressed() local lastEscWindow = self:getLastAllowEscWindow() if lastEscWindow == nil then return end lastEscWindow:closeWindow() end function UIManager:getLastAllowEscWindow() local lastEscWindow for _, index in ipairs(self._windowsLoaded.indices) do ---@type TC.UIWindow local uiWindow = self._windowsLoaded:get(index) if uiWindow.allowCloseByEsc then lastEscWindow = uiWindow end end return lastEscWindow end ---getScreenPosition ---@param uiNode UINode function UIManager:getScreenPosition(uiNode) return self.canvas:canvasPointToScreenPoint(uiNode.positionInCanvas) end function UIManager:playClickSound() SoundUtils.PlaySound(Reg.SoundID("tc:click")) end return UIManager ================================================ FILE: ui/UISlotOp.lua ================================================ local UISlotOp = class("UISlotOp") local MouseItemData = require("MouseItemData") local SettingsData = require("settings.SettingsData") local SLOT_TAG_SELECTING = -10000 ---@param guiContainer any ---@param container Container ---@param slotIndex int ---@param slot Slot ---@param node UINode ---@param touch Touch function UISlotOp.slotOnTouchDown(guiContainer, container, slotIndex, slot, node, touch) if SettingsData.isMobileOperation then -- Mobile UISlotOp.slotOnTouchShowTip(slot, node, touch) else -- PC local isLeftButtonPressed = Input.mouse.isLeftButtonPressed local mouseItemData = MouseItemData.getInstance() local mouseSlot = mouseItemData.slot if not mouseSlot.hasStack then -- Current: Mouse:[] if slot.hasStack then -- Current: Mouse:[] Target:[item] if Input.keyboard:isKeyPressed(Keys.LeftShift) and guiContainer.checkSlotShiftMove ~= nil then -- Pressing Shift local targetContainer, targetIndexStart, targetCount = guiContainer:checkSlotShiftMove(slotIndex, slot:GetStack()) if targetContainer ~= nil then local maxSlots = targetContainer:GetSlotCount() local targetIndexEnd = math.min(maxSlots - 1, targetIndexStart + targetCount - 1) for targetIndex = targetIndexStart, targetIndexEnd do if not slot.hasStack then break end ---@type Slot local targetSlot = targetContainer:GetSlot(targetIndex) if targetSlot.hasStack then local fromStack = slot:GetStack() local toStack = targetSlot:GetStack() local merges = toStack:GetMergeCount(fromStack) if merges > 0 then toStack:SetStackSize(toStack.stackSize + merges) slot:DecrStackSize(merges) container:CommandSlotMoveTo(container, slotIndex, targetContainer, targetIndex, merges) end end end if slot.hasStack then for targetIndex = targetIndexStart, targetIndexEnd do ---@type Slot local targetSlot = targetContainer:GetSlot(targetIndex) if not targetSlot.hasStack then targetSlot:SwapStack(slot) UISlotOp._EnsureSwapAndFirstHasItemOnly(container, targetContainer, targetIndex, container, slotIndex) break end end end end else if isLeftButtonPressed then mouseSlot:SwapStack(slot) -- Current: Mouse:[item] Target:[] UISlotOp._EnsureSwapAndFirstHasItemOnly(container, nil, -1, container, slotIndex) else -- Get half of target slot items. local pickOutNum = math.ceil(slot:GetStack().stackSize / 2.0) if pickOutNum > 0 then mouseSlot:PushStack(slot:GetStack():SplitStack(pickOutNum)) local checkEmpty = false if slot:GetStack().stackSize == 0 then slot:ClearStack() checkEmpty = true end container:CommandEnsureSlotEmpty(nil, -1) container:CommandSlotMoveTo(container, slotIndex, nil, -1, mouseSlot:GetStack().stackSize) if checkEmpty then container:CommandEnsureSlotEmpty(container, slotIndex) end end end mouseItemData.isPcCurrentPicking = true end else -- Current: Mouse:[] Target:[] -- do nothing end else -- Current: Mouse:[item] if slot.hasStack then -- Current: Mouse:[item] Target:[item] mouseSlot:SwapStack(slot) UISlotOp._EnsureSwapAndBothHasItem(container, nil, -1, container, slotIndex) else -- Current: Mouse:[item] Target:[] end if isLeftButtonPressed then mouseItemData.pcIsAverageMode = true else mouseItemData.pcIsAverageMode = false end end end end ---slotOnTouchDown ---@param container Container ---@param slotIndex int ---@param slot Slot ---@param touch Touch ---@param node UINode function UISlotOp.slotOnTouchDoubleDown(container, slotIndex, slot, node, touch) if SettingsData.isMobileOperation then -- Mobile if slot.hasStack then local mouseItemData = MouseItemData.getInstance() local mouseSlot = mouseItemData.slot if not mouseSlot.hasStack then if slot:CanPick(slot:GetStack()) then mouseSlot:PushStack(slot:GetStack():SplitStack(1)) if slot:GetStack().stackSize == 0 then slot:ClearStack() end mouseItemData:startDragging(container, slotIndex) mouseItemData.touchingPosition = touch.position mouseItemData:startPicking() SoundUtils.PlaySound(Reg.SoundID("pop")) end end end else -- PC end end function UISlotOp.slotOnMousePointed(slot, node) if not SettingsData.isMobileOperation then UISlotOp.ensureMousePointedShowTips(slot) end end function UISlotOp.ensureMousePointedShowTips(slot) local TipUI = require("TipUI") if slot.hasStack then local mouseItemData = MouseItemData.getInstance() mouseItemData:showTip(slot:GetStack(), Input.mouse.position, 4) mouseItemData:stopKeepingTip() end end function UISlotOp.slotOnMousePointedEnter(slot, node) if not SettingsData.isMobileOperation then -- PC UISlotOp.ensureMousePointedShowTips(slot) end end function UISlotOp.slotOnMousePointedLeave(slot, node) if not SettingsData.isMobileOperation then -- PC end end ---slotOnTouchPointedMove ---@param container Container ---@param slotIndex int ---@param slot Slot ---@param node UINode ---@param touch Touch ---@param pos Vector2 function UISlotOp.slotOnTouchPointedMove(container, slotIndex, slot, node, touch, pos) local mouseItemData = MouseItemData.getInstance() if not SettingsData.isMobileOperation then -- PC if mouseItemData.isPcCurrentPicking then return end UISlotOp.addAndUpdateSelectingSlot(container, slotIndex, slot) end end function UISlotOp.isSlotSelecting(slot) return slot.tag < 0 end ---slotOnTouchMove ---@param container Container ---@param slotIndex int ---@param slot Slot ---@param node UINode ---@param touch Touch ---@param pos Vector2 function UISlotOp.slotOnTouchMove(container, slotIndex, slot, node, touch, pos) local mouseItemData = MouseItemData.getInstance() if SettingsData.isMobileOperation then -- Mobile local outOfCell = not (pos.x >= 0 and pos.y >= 0 and pos.x < node.width and pos.y < node.height) if outOfCell then if mouseItemData.pickingOneByOne then UISlotOp._stopMousePickingItem(container) end mouseItemData:closeTip() end if slot.hasStack then if outOfCell then local mouseSlot = mouseItemData.slot if not mouseSlot.hasStack then -- Current: Mouse:[] Target:[item] if slot:CanPick(slot:GetStack()) then -- touch is out of the origin slot, move the origin slot item to mouse item! -- Do: Target:[item] --> Mouse:[] mouseSlot:SwapStack(slot) slot:OnPick(mouseSlot:GetStack()) -- Current: Mouse:[item] Target:[] UISlotOp._EnsureSwapAndFirstHasItemOnly(container, nil, -1, container, slotIndex) mouseItemData:startDragging(container, slotIndex) mouseItemData.touchingPosition = touch.position mouseItemData:fixDisplayOffset() SoundUtils.PlaySound(Reg.SoundID("pop")) end end end end mouseItemData.touchingPosition = touch.position else -- PC end end --- ---@param container Container ---@param slotIndex int ---@param slot Slot ---@param touch Touch ---@param node UINode function UISlotOp.slotOnTouchPointedUp(container, slotIndex, slot, node, touch) local mouseItemData = MouseItemData.getInstance() local mouseSlot = mouseItemData.slot ---@type Slot if SettingsData.isMobileOperation then -- Mobile local originSlot = mouseItemData.originSlot if mouseSlot.hasStack then -- Current: Mouse:[item] if mouseItemData.pickingOneByOne then UISlotOp._stopMousePickingItem(container) end if not slot.hasStack then -- Current: Mouse:[item] Target:[] if slot:CanPush(mouseSlot:GetStack()) then -- Do: Mouse:[item] --> Target:[] slot:SwapStack(mouseSlot) slot:OnPush(slot:GetStack()) -- Current: Mouse:[] Target:[item] UISlotOp._EnsureSwapAndFirstHasItemOnly(container, container, slotIndex, nil, -1) SoundUtils.PlaySound(Reg.SoundID("pop")) else -- Current: Mouse:[item] Target:[] UISlotOp._solveMouseItemSendBackToOriginSlot(container) end else -- Current: Mouse:[item] Target:[item] if slot:CanPush(mouseSlot:GetStack()) then local merges = slot:GetStack():GetMergeCount(mouseSlot:GetStack()) if merges > 0 then -- same item type, do merge -- Mouse:[item] --> Target:[item] slot:GetStack():SetStackSize(slot:GetStack().stackSize + merges) mouseSlot:DecrStackSize(merges) slot:OnPush(slot:GetStack()) container:CommandSlotMoveTo(nil, -1, container, slotIndex, merges) SoundUtils.PlaySound(Reg.SoundID("pop")) if mouseSlot.hasStack then -- Current: Mouse:[item] Target:[item] UISlotOp._solveMouseItemSendBackToOriginSlot(container) else -- Current: Mouse:[] Target:[item] container:CommandEnsureSlotHasItem(container, slotIndex, slot:GetStack()) container:CommandEnsureSlotEmpty(nil, -1) end else if originSlot ~= nil then -- not same item type, do swap if not originSlot.hasStack then -- Current: Mouse:[item] Target:[item] Origin:[] if originSlot:CanPush(slot:GetStack()) and slot:CanPick(slot:GetStack()) and slot:CanPush(mouseSlot:GetStack()) then -- Do: Target:[item] --> Origin:[] originSlot:SwapStack(slot) SoundUtils.PlaySound(Reg.SoundID("pop")) originSlot:OnPush(originSlot:GetStack()) slot:OnPick(originSlot:GetStack()) -- Current: Mouse:[item] Target:[] Origin:[item] UISlotOp._EnsureSwapAndFirstHasItemOnly(container, mouseItemData.originContainer, mouseItemData.originSlotIndex, container, slotIndex) -- Do: Mouse:[item] --> Target:[] slot:SwapStack(mouseSlot) slot:OnPush(slot:GetStack()) -- Current: Mouse:[] Target:[item] Origin:[item] UISlotOp._EnsureSwapAndFirstHasItemOnly(container, container, slotIndex, nil, -1) else UISlotOp._solveMouseItemSendBackToOriginSlot(container) end else -- Current: Mouse:[item] Target:[item] Origin:[item] -- TODO end else -- never happened, in case mouseSlot:ClearStack() end end end end end else -- PC if mouseItemData.isPcCurrentPicking then return end UISlotOp.addAndUpdateSelectingSlot(container, slotIndex, slot) end end ---slotOnTouchUp ---@param container Container ---@param slotIndex int ---@param slot Slot ---@param node UINode ---@param touch Touch function UISlotOp.slotOnTouchUp(container, slotIndex, slot, node, touch) local mouseItemData = MouseItemData.getInstance() if SettingsData.isMobileOperation then -- Mobile if mouseItemData.slot.hasStack then if mouseItemData.pickingOneByOne then UISlotOp._stopMousePickingItem(container) end -- the mouse has item, send back to the origin slot UISlotOp._solveMouseItemSendBackToOriginSlot(container) end mouseItemData:stopDragging() mouseItemData:stopKeepingTip() else -- PC if not mouseItemData.isPcCurrentPicking then UISlotOp.sendAllSelectingSlots(container) end mouseItemData.isPcCurrentPicking = false end end ---addAndUpdateSelectingSlot ---@param container Container ---@param slotIndex int ---@param slot Slot function UISlotOp.addAndUpdateSelectingSlot(container, slotIndex, slot) -- processed if UISlotOp.isSlotSelecting(slot) then return end -- check mouse item exist local mouseItemData = MouseItemData.getInstance() local mouseSlot = mouseItemData.slot if not mouseSlot.hasStack then return end -- reach max size if #mouseItemData.pcSelectingSlots >= mouseSlot:GetStack().stackSize then return end -- cannot merge if slot.hasStack and slot:GetStack():GetMergeCount(mouseSlot:GetStack()) == 0 then return end UISlotOp.setSelectedNum(slot, 0) table.insert(mouseItemData.pcSelectingSlots, slot) table.insert(mouseItemData.pcSelectingContainerAndSlotIndices, { container, slotIndex }) UISlotOp.updateSelectingSlots() end ---sendAllSelectingSlots ---@param container Container function UISlotOp.sendAllSelectingSlots(container) local mouseItemData = MouseItemData.getInstance() local mouseSlot = mouseItemData.slot ---@param slot Slot for i, slot in ipairs(mouseItemData.pcSelectingSlots) do if not mouseSlot.hasStack then break end local targetContainerAndIndex = mouseItemData.pcSelectingContainerAndSlotIndices[i] local appends = UISlotOp.getSelectedNum(slot) local actualMoves = 0 if appends > 0 then local mouseStack = mouseSlot:GetStack() if not slot.hasStack then local outStack = mouseStack:SplitStack(appends) slot:PushStack(outStack) actualMoves = appends if mouseStack.stackSize == 0 then mouseSlot:ClearStack() end else local stack = slot:GetStack() local merges = stack:GetMergeCount(mouseStack) local actualAppends = math.min(merges, appends) if actualAppends > 0 then stack:SetStackSize(stack.stackSize + actualAppends) mouseSlot:DecrStackSize(actualAppends) actualMoves = actualAppends end end end if actualMoves > 0 then container:CommandSlotMoveTo(nil, -1, targetContainerAndIndex[1], targetContainerAndIndex[2], actualMoves ) end end for _, slot in ipairs(mouseItemData.pcSelectingSlots) do UISlotOp.clearSelected(slot) end UISlotOp.clearSelected(mouseItemData.slot) mouseItemData.pcSelectingSlots = {} mouseItemData.pcSelectingContainerAndSlotIndices = {} end function UISlotOp.updateSelectingSlots() local mouseItemData = MouseItemData.getInstance() local mouseSlot = mouseItemData.slot if not mouseSlot.hasStack then return end local mouseStack = mouseSlot:GetStack() local mouseStackSize = mouseStack.stackSize local slots = mouseItemData.pcSelectingSlots local totalSlots = #slots if totalSlots == 0 then return end local everyAppends = 1 local actualAppends = 0 if mouseItemData.pcIsAverageMode then everyAppends = math.floor(mouseStackSize / totalSlots) end ---@param slot Slot for _, slot in ipairs(slots) do local actual = 0 if not slot.hasStack then actual = everyAppends else actual = math.min(slot:GetStack():GetMergeCount(mouseStack), everyAppends) end UISlotOp.setSelectedNum(slot, actual) actualAppends = actualAppends + actual end UISlotOp.setSelectedNum(mouseSlot, mouseStackSize - actualAppends) end function UISlotOp.getSelectedNum(slot) return slot.tag - SLOT_TAG_SELECTING end function UISlotOp.setSelectedNum(slot, num) slot.tag = SLOT_TAG_SELECTING + num end function UISlotOp.clearSelected(slot) slot.tag = 0 end function UISlotOp._GetCommandTargetItemStack(container, slotIndex) return slotIndex == -1 and MouseItemData.getInstance().slot:GetStack() or container:GetSlot(slotIndex):GetStack() end ---EnsureSwapAndFirstHasItem ---@param container Container ---@param containerA Container ---@param slotIndexA int ---@param containerB Container ---@param slotIndexB int function UISlotOp._EnsureSwapAndFirstHasItemOnly(container, containerA, slotIndexA, containerB, slotIndexB) container:CommandSwapSlot(containerA, slotIndexA, containerB, slotIndexB) container:CommandEnsureSlotHasItem(containerA, slotIndexA, UISlotOp._GetCommandTargetItemStack(containerA, slotIndexA)) container:CommandEnsureSlotEmpty(containerB, slotIndexB) end ---EnsureSwapAndBothHasItem ---@param container Container ---@param containerA Container ---@param slotIndexA int ---@param containerB Container ---@param slotIndexB int function UISlotOp._EnsureSwapAndBothHasItem(container, containerA, slotIndexA, containerB, slotIndexB) container:CommandSwapSlot(containerA, slotIndexA, containerB, slotIndexB) container:CommandEnsureSlotHasItem(containerA, slotIndexA, UISlotOp._GetCommandTargetItemStack(containerA, slotIndexA)) container:CommandEnsureSlotHasItem(containerB, slotIndexB, UISlotOp._GetCommandTargetItemStack(containerB, slotIndexB)) end ---stopMousePickingItem ---@param container Container function UISlotOp._stopMousePickingItem(container) local mouseItemData = MouseItemData.getInstance() if mouseItemData.pickingOneByOne then local mouseSlot = mouseItemData.slot if mouseSlot.hasStack then container:CommandEnsureSlotEmpty(nil, -1) container:CommandSlotMoveTo( mouseItemData.originContainer, mouseItemData.originSlotIndex, nil, -1, mouseSlot:GetStack().stackSize) container:CommandEnsureSlotHasItem( nil, -1, mouseSlot:GetStack()) mouseItemData.originSlot:OnPick(mouseSlot:GetStack()) if mouseItemData.originSlot.hasStack then -- Current: Mouse:[item] Origin:[item] container:CommandEnsureSlotHasItem( mouseItemData.originContainer, mouseItemData.originSlotIndex, mouseItemData.originSlot:GetStack()) else -- Current: Mouse:[item] Origin:[] container:CommandEnsureSlotEmpty(mouseItemData.originContainer, mouseItemData.originSlotIndex) end end mouseItemData:stopPicking() end end ---solveMouseItemSendBackToOriginSlot ---@param container Container function UISlotOp._solveMouseItemSendBackToOriginSlot(container) local mouseItemData = MouseItemData.getInstance() local mouseSlot = mouseItemData.slot if mouseSlot.hasStack then local originSlot = mouseItemData.originSlot if originSlot ~= nil then -- mouse item left, send back to the origin slot container:CommandEnsureSlotHasItem(nil, -1, UISlotOp._GetCommandTargetItemStack(nil, -1)) if not originSlot.hasStack then if originSlot:CanPush(mouseSlot:GetStack()) then originSlot:SwapStack(mouseSlot) originSlot:OnPush(originSlot:GetStack()) -- now the origin slot has item and mouse item is empty UISlotOp._EnsureSwapAndFirstHasItemOnly(container, mouseItemData.originContainer, mouseItemData.originSlotIndex, nil, -1) SoundUtils.PlaySound(Reg.SoundID("pop")) end else if originSlot:CanPush(mouseSlot:GetStack()) then local merges = originSlot:GetStack():GetMergeCount(mouseSlot:GetStack()) if merges > 0 then originSlot:GetStack():SetStackSize(originSlot:GetStack().stackSize + merges) originSlot:OnPush(originSlot:GetStack()) mouseSlot:DecrStackSize(merges) container:CommandSlotMoveTo(nil, -1, mouseItemData.originContainer, mouseItemData.originSlotIndex, merges) SoundUtils.PlaySound(Reg.SoundID("pop")) end end end else -- in case mouseSlot:ClearStack() end if mouseSlot.hasStack then -- TODO DROP OUT! end end end ---slotOnTouchShowTip ---@param slot Slot ---@param node UINode ---@param touch Touch function UISlotOp.slotOnTouchShowTip(slot, node, touch) if slot.hasStack then local mouseItemData = MouseItemData.getInstance() mouseItemData:showTip(slot:GetStack(), touch.position, 128) mouseItemData.touchingPosition = touch.position mouseItemData:stopKeepingTip() end end --- ---@param stack ItemStack ---@param node UINode ---@param canvasPos Vector2 function UISlotOp.itemStackOnRenderWithShadow(stack, node, canvasPos) local SHADOW_OFFSET = 2 local SHADOW_OFFSET_HALF = SHADOW_OFFSET / 2 local pos = node.positionInCanvas + canvasPos + Vector2.new(node.width / 2 + SHADOW_OFFSET_HALF, node.height / 2 + SHADOW_OFFSET_HALF) local exData = SpriteExData.new() exData.origin = Vector2.new(16, 16) stack:Render(pos, Color.Black, exData) pos.x = pos.x - SHADOW_OFFSET pos.y = pos.y - SHADOW_OFFSET stack:Render(pos, Color.White, exData) end --- ---@param stack ItemStack ---@param node UINode ---@param canvasPos Vector2 function UISlotOp.itemStackOnRender(stack, node, canvasPos) local pos = node.positionInCanvas + canvasPos + Vector2.new(node.width / 2, node.height / 2) local exData = SpriteExData.new() exData.origin = Vector2.new(16, 16) stack:Render(pos, Color.White, exData) end ---slotOnRender ---@param slot Slot ---@param node UINode ---@param canvasPos Vector2 function UISlotOp.slotOnRender(slot, node, canvasPos) if slot.hasStack then UISlotOp.itemStackOnRender(slot:GetStack(), node, canvasPos) elseif slot.tag < 0 then local mouseItemData = MouseItemData.getInstance() local mouseSlot = mouseItemData.slot if mouseSlot.hasStack then UISlotOp.itemStackOnRender(mouseSlot:GetStack(), node, canvasPos) end end end ---slotOnRenderNum ---@param slot Slot ---@param node UINode ---@param canvasPos Vector2 function UISlotOp.slotOnRenderNum(slot, node, canvasPos) if slot.hasStack or slot.tag < 0 then local stack local useCustomNum = slot.tag < 0 if slot.hasStack then stack = slot:GetStack() else local mouseItemData = MouseItemData.getInstance() local mouseSlot = mouseItemData.slot if mouseSlot.hasStack then stack = mouseSlot:GetStack() end end if stack == nil then return end local pos = node.positionInCanvas + canvasPos + Vector2.new(node.width / 2, node.height / 2) local exData = SpriteExData.new() exData.origin = Vector2.new(16, 16) if useCustomNum then stack:RenderCustomNum(UISlotOp.getSelectedNum(slot), pos, Color.Yellow, exData) else stack:RenderNum(pos, Color.White, exData) end end end ---@param slot Slot ---@param node UINode ---@param canvasPos Vector2 function UISlotOp.slotOnRenderDurableBar(slot, node, canvasPos) if not slot.hasStack then return end local stack = slot:GetStack() local item = stack:GetItem() if item.maxDurable <= 0 or stack.durable >= item.maxDurable then return end local rate = stack.durable * 1.0 / item.maxDurable --local rate = 0.8 local UIManager = require("ui.UIManager") local texture = UIManager.getInstance().durableBarTexture local cutRect = Rect.new(0, 0, 32, 12) local cutRectContent = Rect.new(0, 12, math.floor(32 * rate), 12) local pos = node.positionInCanvas + canvasPos + Vector2.new(node.width / 2 - 16, node.height / 2 + 10) Sprite.draw(texture, pos, cutRect, Color.White) local colorContent = Color.new(220 * (1 - rate), 220 * rate, 0, 255) Sprite.draw(texture, pos, cutRectContent, colorContent) end function UISlotOp.onCheckPCDropOutItem() if SettingsData.isMobileOperation then return false end local mouseItemData = MouseItemData.getInstance() local mouseSlot = mouseItemData.slot if mouseSlot.hasStack then local NetworkProxy = require("network.NetworkProxy") local RPC_ID = require("network.RPC_ID") NetworkProxy.RPCSendServerBound(Mod.GetByID("tc"), RPC_ID.SB_DROP_ITEM_MOUSE) mouseSlot:ClearStack() return true end return false end return UISlotOp ================================================ FILE: ui/UISpritePool.lua ================================================ ---@class TC.UISpritePool local UISpritePool = class("UISpritePool") local s_uiSpritePool = nil ---@return TC.UISpritePool function UISpritePool.getInstance() if s_uiSpritePool == nil then s_uiSpritePool = UISpritePool.new() end return s_uiSpritePool end function UISpritePool:__init() self._pool = {} end ---add ---@param name string ---@param sprite UISprite function UISpritePool:add(name, sprite) self._pool[name] = sprite:clone() end ---@param name string ---@return boolean function UISpritePool:has(name) return self._pool[name] ~= nil end ---get ---@param name string ---@return UISprite function UISpritePool:get(name) local sprite = self._pool[name] assert(sprite ~= nil, "cannot find " .. name .. " in UISpritePool.") return sprite:clone() end function UISpritePool:clear() for k in pairs(self._pool) do self._pool[k] = nil end end return UISpritePool ================================================ FILE: ui/UIUtil.lua ================================================ ---@class TC.UIUtil local UIUtil = class("UIUtil") local UIDefault = require("UIDefault") local UISpritePool = require("UISpritePool").getInstance() local UISlotOp = require("UISlotOp") --- ---@param btn UIButton ---@param infoTable table function UIUtil.doInfoTableForButton(btn, infoTable) UIUtil.doInfoTable(btn, infoTable) if infoTable ~= nil then if infoTable.targetSprite ~= nil then if infoTable.targetSprite.name ~= nil then btn.targetSprite = UISpritePool:get(infoTable.targetSprite.name) end UIUtil.doInfoTableForSprite(btn.targetSprite, infoTable.targetSprite) end end end ---createButton ---@param name string ---@param caption string ---@param x number ---@param y number ---@param width number ---@param height number ---@param infoTable table ---@return UIButton function UIUtil.createButton(name, caption, x, y, width, height, infoTable) assert(x ~= nil) assert(y ~= nil) assert(width ~= nil) assert(height ~= nil) local btn = UIButton.new(name, x, y, width, height) btn.targetSprite = UISpritePool:get("tc:button_normal") btn.highlightedSprite = UISpritePool:get("tc:button_highlight") --btn.highlightedSprite.positionOffset.y = -3 btn.selectedSprite = UISpritePool:get("tc:button_highlight") btn.pressedSprite = UISpritePool:get("tc:button_pressed") btn.pressedSprite.positionOffset.y = 2 if caption ~= nil and caption ~= "" then local lb = UIText.new("lb_caption") lb.outlineSize = 1 lb:setMarginEnabled(true, true, true, true) lb.horizontalOverflow = TextHorizontalOverflow.Overflow --lb:setAutoStretch(true,true) lb.text = caption lb.fontSize = UIDefault.FontSize lb.horizontalAlignment = TextAlignment.HCenter lb.verticalAlignment = TextAlignment.VCenter btn:addChild(lb) end UIUtil.doInfoTableForButton(btn, infoTable) return btn end ---createButtonWithImage ---@param name string ---@param uiSpriteName string ---@param x number ---@param y number ---@param width number ---@param height number ---@param infoTable table ---@param imgInfoTable table ---@return UIButton function UIUtil.createButtonWithImage(name, uiSpriteName, x, y, width, height, infoTable, imgInfoTable) local btn = UIUtil.createButton(name, nil, x, y, width, height, infoTable) local image = UIImage.new("img") image:setMarginEnabled(true, true, true, true) image.sprite = UISpritePool:get(uiSpriteName) image.touchable = false btn:addChild(image) if imgInfoTable ~= nil then UIUtil.doInfoTableForImage(image, imgInfoTable) end return btn end function UIUtil.setSlotStyle(slot, cellStyle) cellStyle = cellStyle or 1 local targetSpriteName = "tc:cell_empty" local highlightedSpriteName = "tc:cell_selected" local selectedSpriteName = "tc:cell_selected" local pressedSpriteName = "tc:cell_selected" if cellStyle > 1 then local postFix = string.format("_%d", cellStyle) targetSpriteName = targetSpriteName .. postFix highlightedSpriteName = highlightedSpriteName .. postFix selectedSpriteName = selectedSpriteName .. postFix pressedSpriteName = pressedSpriteName .. postFix end local btn = UIButton.cast(slot) btn.targetSprite = UISpritePool:get(targetSpriteName) btn.highlightedSprite = UISpritePool:get(highlightedSpriteName) btn.selectedSprite = UISpritePool:get(selectedSpriteName) btn.pressedSprite = UISpritePool:get(pressedSpriteName) end function UIUtil.innerCreateSlot(name, x, y, width, height, iconName, cellStyle) width = width or UIDefault.CellSize height = height or UIDefault.CellSize local btn = UIButton.new(name, x, y, width, height) if iconName then local image = UIImage.new("img") image:setMarginEnabled(true, true, true, true) image.sprite = UISpritePool:get(iconName) image.sprite.color = Color.new(255, 255, 255, 128) image.touchable = false btn:addChild(image) end UIUtil.setSlotStyle(btn, cellStyle) return btn end function UIUtil.createSlot(name, x, y, width, height, iconName) return UIUtil.innerCreateSlot(name, x, y, width, height, iconName) end function UIUtil.createSlotStyle(name, x, y, width, height, style) return UIUtil.innerCreateSlot(name, x, y, width, height, nil, style) end ---hookSlotView ---@param slotNode UINode ---@param itemSlot Slot ---@param isClickShowTip boolean function UIUtil.hookSlotView(slotNode, itemSlot, isClickShowTip) if isClickShowTip == nil then isClickShowTip = true end slotNode:getPostDrawLayer(0):addListener({ UISlotOp.slotOnRender, itemSlot }) slotNode:getPostDrawLayer(1):addListener({ UISlotOp.slotOnRenderNum, itemSlot }) slotNode:getPostDrawLayer(1):addListener({ UISlotOp.slotOnRenderDurableBar, itemSlot }) slotNode:addMousePointedListener({ UISlotOp.slotOnMousePointed, itemSlot }) slotNode:addMousePointedEnterListener({ UISlotOp.slotOnMousePointedEnter, itemSlot }) slotNode:addMousePointedLeaveListener({ UISlotOp.slotOnMousePointedLeave, itemSlot }) if isClickShowTip then slotNode:addTouchDownListener({ UISlotOp.slotOnTouchShowTip, itemSlot }) end end ---hookSlot ---@param slotNode UINode ---@param guiContainer GuiContainer ---@param slotIndex int function UIUtil.hookSlot(slotNode, guiContainer, slotIndex) local slot = guiContainer.container:GetSlot(slotIndex) slotNode.allowDoubleClick = true UIUtil.hookSlotView(slotNode, slot, false) slotNode:addTouchDownListener({ UISlotOp.slotOnTouchDown, guiContainer, guiContainer.container, slotIndex, slot }) slotNode:addTouchDoubleDownListener({ UISlotOp.slotOnTouchDoubleDown, guiContainer.container, slotIndex, slot }) slotNode:addTouchMoveListener({ UISlotOp.slotOnTouchMove, guiContainer.container, slotIndex, slot }) slotNode:addTouchPointedMoveListener({ UISlotOp.slotOnTouchPointedMove, guiContainer.container, slotIndex, slot }) slotNode:addTouchPointedUpListener({ UISlotOp.slotOnTouchPointedUp, guiContainer.container, slotIndex, slot }) slotNode:addTouchUpAfterMoveListener({ UISlotOp.slotOnTouchUp, guiContainer.container, slotIndex, slot }) end ---doInfoTableForSprite ---@param uiSprite UISprite ---@param infoTable table function UIUtil.doInfoTableForSprite(uiSprite, infoTable) if infoTable ~= nil then if infoTable.color ~= nil then uiSprite.color = infoTable.color end if infoTable.style ~= nil then uiSprite.style = infoTable.style end end end ---doInfoTable ---@param uiNode UINode ---@param infoTable table function UIUtil.doInfoTable(uiNode, infoTable) if infoTable ~= nil then if infoTable.anchorPoint ~= nil then uiNode:setAnchorPoint(infoTable.anchorPoint[1], infoTable.anchorPoint[2]) end if infoTable.positionY ~= nil then uiNode.positionY = infoTable.positionY end if infoTable.positionX ~= nil then uiNode.positionX = infoTable.positionX end if infoTable.size ~= nil then uiNode.size = infoTable.size end if infoTable.touchable ~= nil then uiNode.touchable = infoTable.touchable end if infoTable.margins ~= nil then local autoStretchWidth = nil local autoStretchHeight = nil if infoTable.margins[5] ~= nil then autoStretchWidth = infoTable.margins[5] end if infoTable.margins[6] ~= nil then autoStretchHeight = infoTable.margins[6] end UIUtil.setMargins(uiNode, infoTable.margins[1], infoTable.margins[2], infoTable.margins[3], infoTable.margins[4], autoStretchWidth, autoStretchHeight) end if infoTable.marginsLR ~= nil then local autoStretch = nil if infoTable.marginsLR[3] ~= nil then autoStretch = infoTable.marginsLR[3] end UIUtil.setMarginsLR(uiNode, infoTable.marginsLR[1], infoTable.marginsLR[2], autoStretch) end if infoTable.marginsTB ~= nil then local autoStretch = false if infoTable.marginsTB[3] ~= nil then autoStretch = infoTable.marginsTB[3] end UIUtil.setMarginsTB(uiNode, infoTable.marginsTB[1], infoTable.marginsTB[2], autoStretch) end if infoTable.visible ~= nil then uiNode.visible = infoTable.visible end end end ---doInfoTableForImage ---@param img UIImage ---@param infoTable table function UIUtil.doInfoTableForImage(img, infoTable) UIUtil.doInfoTable(img, infoTable) if infoTable ~= nil then if infoTable.sprite ~= nil then if infoTable.sprite.name ~= nil then img.sprite = UISpritePool:get(infoTable.sprite.name) end UIUtil.doInfoTableForSprite(img.sprite, infoTable.sprite) end end end ---@param panel UIPanel ---@param infoTable table function UIUtil.doInfoTableForPanel(panel, infoTable) UIUtil.doInfoTable(panel, infoTable) if infoTable ~= nil then if infoTable.sprite ~= nil then if infoTable.sprite.name ~= nil then panel.sprite = UISpritePool:get(infoTable.sprite.name) end UIUtil.doInfoTableForSprite(panel.sprite, infoTable.sprite) end end end ---createImage ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@param infoTable table function UIUtil.createImage(name, x, y, width, height, infoTable) local img = UIImage.new(name, x, y, width, height) UIUtil.doInfoTableForImage(img, infoTable) return img end ---createImage ---@param name string ---@param infoTable table function UIUtil.createImageNoPos(name, infoTable) local img = UIImage.new(name) UIUtil.doInfoTableForImage(img, infoTable) return img end ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@param infoTable table ---@return UIPanel function UIUtil.createPanel(name, x, y, width, height, infoTable) local panel = UIPanel.new(name, x, y, width, height) UIUtil.doInfoTableForPanel(panel, infoTable) return panel end ---@param name string ---@param infoTable table ---@return UIPanel function UIUtil.createPanelNoPos(name, infoTable) local panel = UIPanel.new(name) UIUtil.doInfoTableForPanel(panel, infoTable) return panel end ---doInfoTableForSlider ---@param lb UISlider ---@param infoTable table function UIUtil.doInfoTableForSlider(slider, infoTable) UIUtil.doInfoTable(slider, infoTable) if infoTable ~= nil then end end ---createSlider ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@param infoTable table function UIUtil.createSlider(name, x, y, width, height, infoTable) local slider = UISlider.new(name, x, y, width, height) slider.barSprite = UISpritePool:get("tc:round_rect_white") slider.barSprite.color = Color.new(20, 20, 30) slider.activeBarSprite = UISpritePool:get("tc:round_rect_white") slider.activeBarSprite.color = Color.new(80, 80, 120) slider.sliderSprite = UISpritePool:get("tc:white_circle") slider.sliderSize = Size.new(24, 24) slider.sliderSprite.color = Color.new(140, 140, 180) UIUtil.doInfoTableForSlider(slider, infoTable) return slider end ---doInfoTableForLabel ---@param lb UIText ---@param infoTable table function UIUtil.doInfoTableForLabel(lb, infoTable) UIUtil.doInfoTable(lb, infoTable) if infoTable ~= nil then if infoTable.color ~= nil then lb.color = infoTable.color end if infoTable.fontSize ~= nil then lb.fontSize = infoTable.fontSize end if infoTable.isRichText ~= nil then lb.isRichText = infoTable.isRichText end if infoTable.autoAdaptSize ~= nil then lb.autoAdaptSize = infoTable.autoAdaptSize end if infoTable.horizontalOverflow ~= nil then lb.horizontalOverflow = infoTable.horizontalOverflow end end end ---createLabel ---@param name string ---@param content string ---@param x number ---@param y number ---@param width number ---@param height number ---@param horizontalAlignment TextAlignment_Value ---@param verticalAlignment TextAlignment_Value ---@param infoTable table ---@return UIText function UIUtil.createLabel(name, content, x, y, width, height, horizontalAlignment, verticalAlignment, infoTable) if horizontalAlignment == nil then horizontalAlignment = TextAlignment.Left end if verticalAlignment == nil then verticalAlignment = TextAlignment.Top end local lb = UIText.new(name, x, y, width, height) lb.outlineSize = 1 lb.text = content lb.fontSize = UIDefault.FontSize lb.horizontalAlignment = horizontalAlignment lb.verticalAlignment = verticalAlignment lb.horizontalOverflow = TextHorizontalOverflow.Overflow UIUtil.doInfoTableForLabel(lb, infoTable) return lb end ---createLabelNoPos ---@param name string ---@param content string ---@param horizontalAlignment TextAlignment_Value ---@param verticalAlignment TextAlignment_Value ---@param infoTable table ---@return UIText function UIUtil.createLabelNoPos(name, content, horizontalAlignment, verticalAlignment, infoTable) local lb = UIUtil.createLabel(name, content, 0, 0, 32, 32, horizontalAlignment, verticalAlignment, infoTable) return lb end --- ---@param panelList UIScrollView ---@param infoTable table function UIUtil.doInfoTableForScrollView(panelList, infoTable) UIUtil.doInfoTable(panelList, infoTable) if infoTable ~= nil then if infoTable.sprite ~= nil then if infoTable.sprite.name ~= nil then panelList.sprite = UISpritePool:get(infoTable.sprite.name) UIUtil.doInfoTableForSprite(panelList.sprite, infoTable.sprite) end end end end ---createScrollView ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@param infoTable table ---@return UIScrollView function UIUtil.createScrollView(name, x, y, width, height, infoTable) local panelList = UIScrollView.new(name, x, y, width, height) panelList.viewSize = Size.new(panelList.size.width, 600) UIUtil.doInfoTableForScrollView(panelList, infoTable) return panelList end ---createScrollView ---@param name string ---@param infoTable table function UIUtil.createScrollViewNoPos(name, infoTable) local panelList = UIScrollView.new(name) UIUtil.doInfoTableForScrollView(panelList, infoTable) panelList.viewSize = Size.new(panelList.size.width, 600) return panelList end --- ---@param panel UIPanel ---@param infoTable table function UIUtil.doInfoTableForPanel(panel, infoTable) UIUtil.doInfoTable(panel, infoTable) if infoTable ~= nil then if infoTable.sprite ~= nil then if infoTable.sprite.name ~= nil then panel.sprite = UISpritePool:get(infoTable.sprite.name) UIUtil.doInfoTableForSprite(panel.sprite, infoTable.sprite) end end end end ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@param infoTable table function UIUtil.createPanel(name, x, y, width, height, infoTable) local panel = UIPanel.new(name, x, y, width, height) UIUtil.doInfoTableForPanel(panel, infoTable) return panel end --- ---@param sw UISwitch ---@param infoTable table function UIUtil.doInfoTableForSwitch(sw, infoTable) UIUtil.doInfoTable(sw, infoTable) if infoTable ~= nil then if infoTable.selected ~= nil then sw:setSelected(infoTable.selected, false) end end end ---@param name string ---@param x number ---@param y number ---@param width number ---@param height number ---@param infoTable table function UIUtil.createSwitch(name, x, y, width, height, infoTable) local sw = UISwitch.new(name, x, y, width, height) sw.offBackgroundSprite = UISpritePool:get("tc:round_rect_white") sw.offBackgroundSprite.color = Color.new(20, 20, 30) sw.onBackgroundSprite = UISpritePool:get("tc:round_rect_white") sw.onBackgroundSprite.color = Color.new(80, 80, 120) sw.offSliderSprite = UISpritePool:get("tc:white_circle") sw.offSliderSprite.color = Color.new(140, 140, 180) sw.fadeTime = 0.25 sw.sliderSize = Size.new(24, 24) UIUtil.doInfoTableForSwitch(sw, infoTable) return sw end ---setMargins ---@param node UINode ---@param left number ---@param top number ---@param right number ---@param bottom number ---@param autoStretchWidth boolean ---@param autoStretchHeight boolean function UIUtil.setMargins(node, left, top, right, bottom, autoStretchWidth, autoStretchHeight) if left ~= nil then node:setLeftMargin(left, true) else node:setLeftMargin(0, false) end if top ~= nil then node:setTopMargin(top, true) else node:setTopMargin(0, false) end if right ~= nil then node:setRightMargin(right, true) else node:setRightMargin(0, false) end if bottom ~= nil then node:setBottomMargin(bottom, true) else node:setBottomMargin(0, false) end if autoStretchWidth == nil then if left ~= nil and right ~= nil then autoStretchWidth = true else autoStretchWidth = false end end if autoStretchHeight == nil then if top ~= nil and bottom ~= nil then autoStretchHeight = true else autoStretchHeight = false end end node.autoStretchWidth = autoStretchWidth node.autoStretchHeight = autoStretchHeight end ---setMarginsLR ---@param node UINode ---@param left number ---@param right number ---@param autoStretch boolean function UIUtil.setMarginsLR(node, left, right, autoStretch) UIUtil.setMargins(node, left, nil, right, nil, autoStretch, nil) end ---setMarginsTB ---@param node UINode ---@param top number ---@param bottom number ---@param autoStretch boolean function UIUtil.setMarginsTB(node, top, bottom, autoStretch) UIUtil.setMargins(node, nil, top, nil, bottom, nil, autoStretch) end ---setTable ---@param panelList UINode ---@param proxy any ---@param isVertical boolean ---@param countPreLine number ---@return boolean function UIUtil.setTable(panelList, proxy, isVertical, countPreLine) if not panelList:getChild("panel_item"):valid() then return false end isVertical = isVertical or true countPreLine = countPreLine or 1 local sv = UIScrollView.cast(panelList) sv:ScrollToLeft() sv:ScrollToTop() local count = 0 local panelItem = panelList:getChild("panel_item") panelItem.visible = false local lastCount = panelList:getChildrenCount() local childrenToRemoved = {} for i = 1, lastCount do local child = panelList:getChildByIndex(i - 1) if child.name ~= "panel_item" then table.insert(childrenToRemoved, child) end end ---@param child UINode for _, child in pairs(childrenToRemoved) do panelList:removeChild(child) end childrenToRemoved = {} if proxy._getTableElementCount == nil then count = 0 else count = proxy:_getTableElementCount() end local offsetX = 0 local offsetY = 0 local maxX = 0 local maxY = 0 local indexPreLine = 1 for i = 1, count do local itemName = string.format("panel_item_%d", i) local tempItem = panelList:getChild(itemName) local needCreate = false if tempItem:valid() then panelList:removeChild(tempItem) needCreate = true else needCreate = true end if needCreate then tempItem = panelItem:clone() tempItem.name = itemName panelList:addChild(tempItem, i) end tempItem:setAnchorPoint(0, 0) tempItem.visible = true if proxy._getTableElementSize ~= nil then local size = proxy:_getTableElementSize(i) if size ~= nil then tempItem.size = size tempItem:applyMargin() end end tempItem:setPosition(offsetX, offsetY) if proxy._setTableElement ~= nil then proxy:_setTableElement(tempItem, i) end local offsetWidth = tempItem.width local offsetHeight = tempItem.height if proxy._getTableElementPositionOffset ~= nil then local size = proxy:_getTableElementPositionOffset(i) offsetWidth, offsetHeight = size.width, size.height end maxX = tempItem.positionX + offsetWidth maxY = tempItem.positionY + offsetHeight if indexPreLine >= countPreLine then indexPreLine = 1 if isVertical then offsetY = offsetY + offsetHeight offsetX = 0 else offsetX = offsetX + offsetWidth offsetY = 0 end else indexPreLine = indexPreLine + 1 if isVertical then offsetX = offsetX + offsetWidth else offsetY = offsetY + offsetHeight end end end maxX = math.max(maxX, sv.width) maxY = math.max(maxY, sv.height) sv.viewSize = Size.new(maxX, maxY) sv:ScrollToLeft() sv:ScrollToTop() return true end ---getTableElement ---@param uiTable UIScrollView ---@param index number function UIUtil.getTableElement(uiTable, index) return uiTable:getChildByTag(index) end ---createBlackFullScreenLayer ---@param name string ---@return UIPanel function UIUtil.createBlackFullScreenLayer(name) local cover = UIPanel.new(name) cover.size = GameWindow.displayResolution cover:setMarginEnabled(true, true, true, true) cover:setAutoStretch(true, true) cover.sprite = UISpritePool:get("tc:black") cover.sprite.color = Color.new(255, 255, 255, 192) return cover end ---createWindowPattern ---@param root UINode ---@param windowSize Size ---@param cfgTable table ---@return UIPanel function UIUtil.createWindowPattern(root, windowSize, cfgTable) local panel = UIPanel.new("layer", 0, 0, windowSize.width, windowSize.height) UIUtil.setMargins(panel, 0, 0, 0, 0, false, false) if root ~= nil then root:addChild(panel) end if cfgTable and cfgTable.style then if cfgTable.style == "Gray" then local bg = UIImage.new("bg") bg.sprite = UISpritePool:get("tc:base") UIUtil.setMargins(bg, 0, 0, 0, 0) panel:addChild(bg) end else local bg_frame = UIImage.new("bg_frame") bg_frame.sprite = UISpritePool:get("tc:window_frame_01") bg_frame.sprite.color = Color.new(255, 255, 255, 160) UIUtil.setMargins(bg_frame, 0, 0, 0, 0) panel:addChild(bg_frame) local bg = UIImage.new("bg") UIUtil.setMargins(bg, 2, 2, 2, 2) bg.sprite = UISpritePool:get("tc:window_bg_01") bg.sprite.style = UISpriteStyle.Filled bg.sprite.color = Color.new(255, 255, 255, 30) bg_frame:addChild(bg) end return panel end ---renderProgress ---@param source string|TextureLocation ---@param pos Vector2 ---@param steps int ---@param totalSteps int ---@param dirX int L->R: 1 R->L: -1 ---@param dirY int T->B 1 B->T: -1 function UIUtil.renderProgress(source, pos, steps, totalSteps, dirX, dirY) if steps <= 0 or totalSteps <= 0 then return end if dirX == nil then dirX = 0 end if dirY == nil then dirY = 0 end if dirX == 0 and dirY == 0 then return end local texture if type(source) == 'string' then texture = UISpritePool:get(source).textureLocation else texture = source end local sourceRect = TextureManager.getSourceRect(texture) local sw = sourceRect.width local sh = sourceRect.height local offsetX = 0 local offsetY = 0 local rate = steps * 1.0 / totalSteps local rectCut if dirX ~= 0 then local pw = math.floor(sw * rate) if dirX > 0 then rectCut = Rect.new(0, 0, pw, sh) else offsetX = sw - pw rectCut = Rect.new(offsetX, 0, pw, sh) end else local ph = math.floor(sh * rate) if dirY > 0 then rectCut = Rect.new(0, 0, sw, ph) else offsetY = sh - ph rectCut = Rect.new(0, offsetY, sw, ph) end end local drawPos = Vector2.new(pos.x + offsetX, pos.y + offsetY) Sprite.draw(texture, drawPos, rectCut, Color.White) end return UIUtil ================================================ FILE: ui/UIWindow.lua ================================================ ---@class TC.UIWindow local UIWindow = class("UIWindow") local UIManager = require("UIManager") local MouseItemData = require("MouseItemData") local API = require("api") local UIDefault = require("ui.UIDefault") ---__init ---@param root UIPanel function UIWindow:__init(root, uiGroup) self.root = root self.manager = UIManager.getInstance() self.mouseItemData = MouseItemData.getInstance() self.windowId = self.manager:addWindowsLoaded(self) self.closed = false self.scheduleIds = {} self.allowCloseByEsc = false self.uiGroup = UIDefault.GROUP_NONE if uiGroup ~= nil then self.uiGroup = uiGroup end self.root.textBatchRendering = true self.uiClassName = self.__cname self._modifyInstances = {} self:initModifyFromOutside() end function UIWindow:initModifyFromOutside() local dict = API.getInstance().uiModifyDict[self.uiClassName] if dict ~= nil then for _, modifyClass in ipairs(dict) do local ins = modifyClass.new(self) table.insert(self._modifyInstances, ins) end end end function UIWindow:closeWindow() self.manager:removeWindowsLoaded(self.windowId) self.closed = true self:onDestroy() for _, scheduleID in ipairs(self.scheduleIds) do IntegratedClient.main:removeSchedule(scheduleID) end self.scheduleIds = {} end function UIWindow:onDestroy() end function UIWindow:initUpdateFunc(listener, intervalTicks) intervalTicks = intervalTicks or 0 local scheduleID = IntegratedClient.main:createSchedule(intervalTicks) IntegratedClient.main:getSchedule(scheduleID):addListener(listener) table.insert(self.scheduleIds, scheduleID) end function UIWindow:onWindowResize() self.root:applyMargin() end function UIWindow:onUpdate() end function UIWindow:postInitContent() for _, ins in ipairs(self._modifyInstances) do if ins.initContent ~= nil then ins:initContent() end end end return UIWindow ================================================ FILE: ui/WorldListUI.lua ================================================ ---@class TC.WorldListUI:TC.UIWindow local WorldListUI = class("WorldListUI", require("UIWindow")) local UIUtil = require("UIUtil") local MenuJoinInfo = require("client.MenuJoinInfo") local Locale = require("languages.Locale") function WorldListUI:__init() WorldListUI.super.__init(self, require("UIDesign").getWorldListUI()) ---@type UIScrollView self._panelList = nil self._indexSelected = 0 self._worldInfoList = {} self:initContent() end function WorldListUI:initContent() self:initWorldData() self._panelList = self.root:getChild("layer.panel_list") local panelItem = self._panelList:getChild("panel_item") self.itemSize = Size.new(panelItem.width / 1, panelItem.height) UIUtil.setTable(self._panelList, self, true, 1) self:updateSelection() self.root:getChild("layer.btn_ok"):addTouchUpListener({ self._onOkButtonClicked, self }) self.root:getChild("layer.btn_back"):addTouchUpListener({ self._onBackButtonClicked, self }) self.root:getChild("layer.btn_create"):addTouchUpListener({ self._onNewWorldClicked, self }) end function WorldListUI:getWorldLastModifiedTime(name) local filePath = Path.join(App.persistentDataPath, "worlds", name, "base.dat") if File.isPathExist(filePath) then return File.getLastWriteTime(filePath) end local filePathBackup = Path.join(App.persistentDataPath, "worlds", name, "base.dat.bak") return File.getLastWriteTime(filePathBackup) end function WorldListUI:initWorldData() local worldNames = File.getAllSubFolders(Path.join(App.persistentDataPath, "worlds")) for _, worldName in pairs(worldNames) do local worldData = WorldData.new() if WorldDataUtils.Load(worldName, worldData) then local info = { name = worldName, data = worldData, isCSC = worldData.clientSideCharacters, lastModifiedTime = self:getWorldLastModifiedTime(worldName) } table.insert(self._worldInfoList, info) end end table.sort(self._worldInfoList, function(element1, element2) return element1.lastModifiedTime > element2.lastModifiedTime end) end function WorldListUI:_getTableElementCount() return #self._worldInfoList end function WorldListUI:_getTableElementSize() return self.itemSize end ---_setTableElement ---@param node UINode ---@param index number function WorldListUI:_setTableElement(node, index) node.tag = index local info = self._worldInfoList[index] local tipText = "" tipText = tipText .. (info.isCSC and Locale.BP_SHARED_MODE or Locale.FORCE_NEW_PLAYER_MODE) UIText.cast(node:getChild("lb_world_name")).text = info.name UIText.cast(node:getChild("lb_time")).text = tostring(info.lastModifiedTime) UIText.cast(node:getChild("lb_tips")).text = tipText node.allowDoubleClick = true node:addTouchUpListener({ self._onElementClicked, self }) node:addTouchDoubleDownListener({ self._onElementDoubleClicked, self }) node:getChild("btn_remove"):addTouchUpListener({ self._onRemoveButtonClicked, self, index }) end function WorldListUI:_onOkButtonClicked() if self._indexSelected > 0 then MenuJoinInfo.getInstance().worldInfo.name = self._worldInfoList[self._indexSelected].name ClientStateManager.StartJoining(MenuJoinInfo.getInstance():getData()) self:closeWindow() self.manager:playClickSound() end end function WorldListUI:_onBackButtonClicked() self:closeWindow() self.manager:playClickSound() require("PlayerListUI").new() end function WorldListUI:_onNewWorldClicked() self.manager:playClickSound() self:closeWindow() require("NewWorldUI").new() end ---_onElementClicked ---@param node UINode ---@param _ Touch function WorldListUI:_onElementClicked(node) local index = node.tag if self._indexSelected ~= index then self.manager:playClickSound() self._indexSelected = index self:updateSelection() end end ---@param _ Touch ---@param node UINode function WorldListUI:_onElementDoubleClicked(node) self:_onElementClicked(node) self:_onOkButtonClicked() end ---@param index number function WorldListUI:_onRemoveButtonClicked(index) if self._indexSelected == index then local name = self._worldInfoList[index].name self.manager:playClickSound() local InfoPopupUI = require("InfoPopupUI") local infoUI = InfoPopupUI.new( Locale.SURE_TO_DELETE_WORLD_1 .. "\"" .. name .. "\"" .. Locale.SURE_TO_DELETE_WORLD_2, function() if name ~= nil and name ~= "" then print("remove world", name) WorldDataUtils.Remove(name) end end, function() WorldListUI.new() end ) self:closeWindow() end end function WorldListUI:updateSelection() for index = 1, #self._worldInfoList do local node = self._panelList:getChildByTag(index) local show = false if node.tag == self._indexSelected then show = true end node:getChild("img_selected").visible = show node:getChild("btn_remove").visible = show end local btnColor = self._indexSelected and Color.White or Color.Gray UIText.cast(self.root:getChild("layer.btn_ok.lb_caption")).color = btnColor end function WorldListUI:closeWindow() WorldListUI.super.closeWindow(self) end return WorldListUI ================================================ FILE: ui/advancement/AdvancementContainerClient.lua ================================================ ---@class TC.AdvancementContainerClient:Container local AdvancementContainerClient = class("AdvancementContainerClient", Container) local AdvancementTree = require("AdvancementTree") local UIData = require("AdvancementUIData") ---@param player Player function AdvancementContainerClient:__init(player) AdvancementContainerClient.super.__init(self) local source = self:_BuildTreeSource() self.tree = AdvancementTree.new(source) self:_ProcessData(player) end ---_ProcessData ---@param player Player function AdvancementContainerClient:_ProcessData(player) ---_DFS ---@param node TC.AdvancementTreeNode local function _DFS(node, state) local id = node.data local advancement = AdvancementUtils.Get(id) if player:IsAdvancementFinished(id) then print("advancement finish id", id, Reg.AdvancementIDName(id)) state = UIData.FINISH end node.displayState = state if state ~= UIData.FULL_LOCK then node.itemStack = ItemStack.new(ItemRegistry.GetItemByID(advancement.itemID)) end if state == UIData.FINISH then state = UIData.UNLOCK elseif state == UIData.UNLOCK then state = UIData.NEXT_UNLOCK else --state = UIData.FULL_LOCK state = UIData.NEXT_UNLOCK end for _, child in ipairs(node.children) do _DFS(child, state) end end --_DFS(self.tree.root, UIData.FULL_LOCK) _DFS(self.tree.root, UIData.NEXT_UNLOCK) end function AdvancementContainerClient:_BuildTreeSource() local maxID = Reg.MaxAdvancementID() local tempArray = {} local rootID = {} for id = 1, maxID do tempArray[id] = {} end for id = 1, maxID do local advancement = AdvancementUtils.Get(id) if advancement.parentID == 0 then rootID = id else table.insert(tempArray[advancement.parentID], id) end end local function dfs(curID) local tmp = { data = curID, nexts = {}, name = Reg.AdvancementIDName(curID) } for _, childID in ipairs(tempArray[curID]) do local child = dfs(childID) table.insert(tmp.nexts, child) end return tmp end return dfs(rootID) end function AdvancementContainerClient:OnEvent(eventId, eventString) end return AdvancementContainerClient ================================================ FILE: ui/advancement/AdvancementTree.lua ================================================ ---@class TC.AdvancementTreeNode local AdvancementTreeNode = class("AdvancementTreeNode") ---@class TC.AdvancementTree local AdvancementTree = class("AdvancementTree") local UIData = require("AdvancementUIData") local OFFSET_X = UIData.OFFSET_X local NODE_WIDTH = UIData.NODE_WIDTH local NODE_FULL_WIDTH = UIData.NODE_FULL_WIDTH local LEVEL_OFFSET = UIData.LEVEL_OFFSET function AdvancementTreeNode:__init() self.parent = nil ---@type TC.AdvancementTreeNode self.children = {} ---@type TC.AdvancementTreeNode[] self.level = 0 self.left = 0 self.right = 0 self.moveOffset = 0 self.data = 0 self.cellArea = RectFloat.new() self.displayState = UIData.FULL_LOCK self.itemStack = nil ---@type ItemStack end function AdvancementTreeNode:getArea() return RectFloat.new(self.left + OFFSET_X / 2, self.level * LEVEL_OFFSET, NODE_WIDTH, NODE_WIDTH) end function AdvancementTreeNode:renderDebug() local area = self:getArea() GraphicsDevice.drawRectHollow2D(area, Color.White) for _, child in ipairs(self.children) do child:renderDebug() local childArea = child:getArea() GraphicsDevice.drawLine2D(Vector2.new(area.centerX, area.bottomY), Vector2.new(childArea.centerX, childArea.y), Color.White) end end function AdvancementTree:__init(source) --source = self:randomGenSource(0) self.levelLastNodes = {} ---@type TC.AdvancementTreeNode[] self.root = self:genFromTable(source, 0) self.width = 0 self.height = 0 self:dfs(self.root) self:adaptData() end function AdvancementTree:randomGenSource(level) local source = {} source.data = 0 if level <= 5 and (level == 0 or math.random(0, 1) == 0) then local cnt = math.random(2, 4) source.nexts = {} for _ = 1, cnt do table.insert(source.nexts, self:randomGenSource(level + 1)) end end return source end function AdvancementTree:adaptData() ---@param node TC.AdvancementTreeNode local function _dfs(node) node.cellArea = RectFloat.new( node.left + OFFSET_X / 2, node.level * LEVEL_OFFSET, NODE_WIDTH, NODE_WIDTH) self.width = math.max(self.width, node.cellArea.rightX) self.height = math.max(self.height, node.cellArea.bottomY) for _, child in ipairs(node.children) do _dfs(child) end end _dfs(self.root) end ---genFromTable ---@param source table ---@param level number function AdvancementTree:genFromTable(source, level) local node = AdvancementTreeNode.new() node.level = level node.data = source.data if source.nexts ~= nil then for _, childSource in ipairs(source.nexts) do local childNode = self:genFromTable(childSource, level + 1) childNode.parent = node table.insert(node.children, childNode) end end return node end ---getLevelRightPos ---@param level number function AdvancementTree:getLevelRightPos(level) local pos = 0 local lastNode = self.levelLastNodes[level + 1] if lastNode ~= nil then pos = lastNode.right end return pos end ---dfs ---@param node TC.AdvancementTreeNode function AdvancementTree:dfs(node) if #node.children == 0 then node.left = self:getLevelRightPos(node.level) node.right = node.left + NODE_FULL_WIDTH else local cl, cr = 1000000000, -1000000000 for _, child in ipairs(node.children) do self:dfs(child) cl = math.min(cl, child.left) cr = math.max(cr, child.right) end local l = self:getLevelRightPos(node.level) local cx = math.floor((cl + cr) / 2 - NODE_FULL_WIDTH / 2) node.moveOffset = math.max(cx, l) - cx node.left = cx node.right = cx + NODE_FULL_WIDTH self:sink(node, 0) end self.levelLastNodes[node.level + 1] = node end ---sink ---@param node TC.AdvancementTreeNode ---@param move number function AdvancementTree:sink(node, move) local moveAll = node.moveOffset + move for _, child in ipairs(node.children) do self:sink(child, moveAll) end node.moveOffset = 0 node.left = node.left + moveAll node.right = node.right + moveAll end return AdvancementTree ================================================ FILE: ui/advancement/AdvancementUI.lua ================================================ ---@class TC.AdvancementUI:GuiContainer local AdvancementUI = class("AdvancementUI", GuiContainer) local UIUtil = require("ui.UIUtil") local UISlotOp = require("ui.UISlotOp") local UIData = require("AdvancementUIData") local HotkeyUIHelper = require("ui.HotkeyUIHelper") local GuiID = require("ui.GuiID") local SettingsData = require("settings.SettingsData") ---@param container TC.AdvancementContainerClient function AdvancementUI:__init(container) AdvancementUI.super.__init(self, container) self.ui = require("ui.UIWindow").new(require("ui.UIDesign").getAdvancementUI(), require("ui.UIDefault").GROUP_GAME_WINDOW) self.currentContainer = container self._hkHelper = HotkeyUIHelper.new(Mod.current, GuiID.Advancement) self:_initContent() end function AdvancementUI:DoClose() local player = PlayerUtils.GetCurrentClientPlayer() if player ~= nil and player:IsGuiOpened(Mod.current, GuiID.Advancement) then player:CloseGui(Mod.current, GuiID.Advancement) end end function AdvancementUI:_initContent() local scrollPanel = UIScrollView.cast(self.ui.root:getChild("scroll")) local basePanel = scrollPanel:getChild("panel") local panelOffsetX = 100 local panelOffsetY = 100 local originalWidth = scrollPanel.width local originalHeight = scrollPanel.height self.ui.root:getChild("btn_ok"):addTouchUpListener({ function(self) self:DoClose() end, self }) local tree = self.currentContainer.tree local inWidth = panelOffsetX * 2 + tree.width local inHeight = panelOffsetY * 2 + tree.height if inWidth < originalWidth then panelOffsetX = math.ceil((originalWidth - tree.width) / 2) inWidth = originalWidth end if inHeight < originalHeight then panelOffsetY = math.ceil((originalHeight - tree.height) / 2) inHeight = originalHeight end basePanel:setSize(inWidth, inHeight) scrollPanel.viewSize = basePanel.size local lineColors = { [UIData.FINISH] = Color.new(90, 90, 90), [UIData.UNLOCK] = Color.new(70, 70, 70), [UIData.NEXT_UNLOCK] = Color.new(50, 50, 50), [UIData.FULL_LOCK] = Color.new(30, 30, 30), } local cellColors = { [UIData.FINISH] = Color.White, [UIData.UNLOCK] = Color.new(128, 128, 128), [UIData.NEXT_UNLOCK] = Color.new(64, 64, 64), [UIData.FULL_LOCK] = Color.new(32, 32, 32), } ---@param node TC.AdvancementTreeNode local function _DFSLine(node) if #node.children > 0 then local area = node.cellArea local lineColor = lineColors[node.displayState] local parentCenterX = area.centerX local parentCenterY = area.centerY local lineSize = 4 local lineExtentHeight = UIData.LEVEL_OFFSET / 2 local lineExtentY = parentCenterY + lineExtentHeight local lineParentDown = UIUtil.createImage("img_line", panelOffsetX + parentCenterX - lineSize / 2, panelOffsetY + parentCenterY, lineSize, lineExtentHeight, { sprite = { name = "tc:white", color = lineColor } }) basePanel:addChild(lineParentDown) local lineExternMinX local lineExternMaxX for _, child in ipairs(node.children) do local childArea = child.cellArea local childCenterX = childArea.centerX local lineChildDown = UIUtil.createImage("img_line", panelOffsetX + childCenterX - lineSize / 2, panelOffsetY + lineExtentY, lineSize, lineExtentHeight, { sprite = { name = "tc:white", color = lineColor } }) basePanel:addChild(lineChildDown) if lineExternMinX == nil then lineExternMinX = childCenterX lineExternMaxX = childCenterX else lineExternMinX = math.min(lineExternMinX, childCenterX) lineExternMaxX = math.max(lineExternMaxX, childCenterX) end end if lineExternMinX ~= nil and lineExternMinX < lineExternMaxX then local externWidth = lineExternMaxX - lineExternMinX local lineExtern = UIUtil.createImage("img_line", panelOffsetX + lineExternMinX, panelOffsetY + lineExtentY - lineSize / 2, externWidth, lineSize, { sprite = { name = "tc:white", color = lineColor } }) basePanel:addChild(lineExtern) end end for _, child in ipairs(node.children) do _DFSLine(child) end end ---@param node TC.AdvancementTreeNode local function _DFSCell(node) local area = node.cellArea local cellColor = cellColors[node.displayState] local cell = UIUtil.createImage("cell", panelOffsetX + area.x, panelOffsetY + area.y, area.width, area.height, { sprite = { name = "tc:advancement_cell", color = cellColor } }) if node.itemStack ~= nil then cell:getPostDrawLayer(0):addListener({ UISlotOp.itemStackOnRenderWithShadow, node.itemStack }) end if SettingsData.isMobileOperation then cell:addTouchUpListener({ AdvancementUI.OnClickCell, self, node }) else cell:addMousePointedListener({ AdvancementUI.OnPointedInCell, self, node }) end basePanel:addChild(cell) for _, child in ipairs(node.children) do _DFSCell(child) end end _DFSLine(tree.root) _DFSCell(tree.root) end ---OnClickCell ---@param node TC.AdvancementTreeNode ---@param touch Touch function AdvancementUI:OnClickCell(node, _, touch) self:UpdateTips(touch.position, node) end function AdvancementUI:OnPointedInCell(node, _) self:UpdateTips(Input.mouse.position, node) end function AdvancementUI:UpdateTips(position, node) local TipUI = require("ui.TipUI") local advancement = AdvancementUtils.Get(node.data) local name = LangUtils.AdvancementName(node.data) local desc = LangUtils.AdvancementDescription(node.data) local contentTable if node.displayState == UIData.FINISH then contentTable = { --"量子科技", --"制造出一颗量子电池!", name, "" .. desc .. "", "已得到!", } elseif node.displayState == UIData.UNLOCK then contentTable = { --"量子科技", --"制造出一颗量子电池!", name, "" .. desc .. "", } elseif node.displayState == UIData.NEXT_UNLOCK then local parentName = advancement.parentID > 0 and LangUtils.AdvancementName(advancement.parentID) or "" contentTable = { --"量子发电机", --"需要完成: 量子科技", name, "需要完成: " .. parentName .. "", } else contentTable = { "???", "未解锁", } end if SettingsData.isMobileOperation then TipUI.generate(contentTable) else if TipUI.isShowing() then TipUI.changeNewContent(contentTable) TipUI.resetKeepTime() else TipUI.generate(contentTable, 2) end end TipUI.adaptPosition(position) end function AdvancementUI:OnClose() self._hkHelper:destroy() self.ui:closeWindow() end return AdvancementUI ================================================ FILE: ui/advancement/AdvancementUIData.lua ================================================ local AdvancementUIData = { OFFSET_X = 8, NODE_WIDTH = 44, NODE_FULL_WIDTH = 52, LEVEL_OFFSET = 60, FINISH = 0, UNLOCK = 1, NEXT_UNLOCK = 2, FULL_LOCK = 3, } return AdvancementUIData ================================================ FILE: ui/backpack/BackpackContainerClient.lua ================================================ ---@class TC.BackpackContainerClient:Container local BackpackContainerClient = class("BackpackContainerClient", Container) local ContainerHelper = require("ui.ContainerHelper") ---@param player Player function BackpackContainerClient:__init(player) BackpackContainerClient.super.__init(self) self.TOTAL_SLOT = 70 self.tempSlots = Inventory.new(self.TOTAL_SLOT) ContainerHelper.ContainerClientInitSlots(self, self.tempSlots) end function BackpackContainerClient:OnEvent(eventId, eventString) end function BackpackContainerClient:OnUpdate() end function BackpackContainerClient:OnClose() end function BackpackContainerClient:CanInteractWith(player) return true end return BackpackContainerClient ================================================ FILE: ui/backpack/BackpackContainerServer.lua ================================================ ---@class TC.BackpackContainerServer:Container local BackpackContainerServer = class("BackpackContainerServer", Container) local UIData = require("BackpackUIData") local ContainerHelper = require("ui.ContainerHelper") local Craft3xHelper = require("ui.craft3x.Craft3xHelper") local RecipeBookServer = require("ui.recipe_book.RecipeBookServer") local GPlayer = require("player.GPlayer") ---@param player Player function BackpackContainerServer:__init(player) BackpackContainerServer.super.__init(self) self.playerIndex = player.entityIndex self.inventory = player.backpackInventory self.equipmentInventory = player.equipmentInventory self.accessoryInventory = GPlayer.GetInstance(player).accessoryInventory self.trashInventory = GPlayer.GetInstance(player).trashInventory self.xi = player.centerXi self.yi = player.centerYi -- 0-8 inputs 9 output self.craftSlots = Inventory.new(10) -- 0-49 inventory ContainerHelper.ContainerServerAddBackpack(player, self) for i = 1, 3 do -- 50-52 equipment self:AddSlotToContainer(self.equipmentInventory, i - 1) end for i = 1, 3 do -- 53-55 appearance self:AddSlotToContainer(self.equipmentInventory, i - 1 + 3) end --local craft2xMapping = { 0, 1, 3, 4 } --for i = 1, 4 do -- -- 56-59 craft inputs -- local slotIndexInCraft = craft2xMapping[i] -- -- Craft3xHelper.InitSlot(self, self.craftSlots, slotIndexInCraft) --end for i = 0, 8 do -- 56-64 craft inputs Craft3xHelper.InitSlot(self, self.craftSlots, i) end -- 65 craft output Craft3xHelper.InitSlot(self, self.craftSlots, 9) for i = 1, 3 do -- 66-68 accessory self:AddSlotToContainer(self.accessoryInventory, i - 1) end -- 69 trash self:AddSlotToContainer(self.trashInventory, 0) self.recipeBookServer = RecipeBookServer.new( Reg.RecipeConfigID("Craft3x"), player, self.craftSlots, 0, 9) end function BackpackContainerServer:OnEvent(eventId, eventString) if eventId == UIData.EventID.SortBackpack then --self.inventory:SortAll() self.inventory:Sort(10, 40) elseif eventId == UIData.EventID.RecipeBookRequest then local recipeID = tonumber(eventString) self.recipeBookServer:FlushValidRecipe(recipeID) if PlayerUtils.IsAlive(self.playerIndex) then local player = PlayerUtils.Get(self.playerIndex) player:FinishAdvancement(Reg.AdvancementID("recipe_book")) end elseif eventId == UIData.EventID.PickOutput then Craft3xHelper.TryPickOutput(self.playerIndex, self, self.craftSlots) end end function BackpackContainerServer:OnUpdate() end function BackpackContainerServer:OnClose() Craft3xHelper.Close(self.craftSlots, self.playerIndex, self.xi, self.yi) end function BackpackContainerServer:CanInteractWith(_) return true end return BackpackContainerServer ================================================ FILE: ui/backpack/BackpackUI.lua ================================================ ---@class TC.BackpackUI:GuiContainer local BackpackUI = class("BackpackUI", GuiContainer) local UIUtil = require("ui.UIUtil") local BackpackUIData = require("BackpackUIData") local InputControl = require("client.InputControl") local HotkeyUIHelper = require("ui.HotkeyUIHelper") local s_isRecipeBookReminded = false ---@param container TC.BackpackContainerClient function BackpackUI:__init(container) BackpackUI.super.__init(self, container) self.currentContainer = container self.ui = require("ui.UIWindow").new(require("ui.UIDesign").getBackpackUI(), require("ui.UIDefault").GROUP_GAME_WINDOW) self._rootLayer = self.ui.root:getChild("layer") self._recipeBookIcon = UIImage.cast(self._rootLayer:getChild("btn_recipe.img")) self._reminderTicks = 0 self._panelStatus = self._rootLayer:getChild("panel_status") self._playerBone = nil local listenSlots = {} for i = 0, 49 do table.insert(listenSlots, self.currentContainer.tempSlots:GetSlot(i)) end for i = 56, 59 do table.insert(listenSlots, self.currentContainer.tempSlots:GetSlot(i)) end table.insert(listenSlots, PlayerUtils.GetCurrentClientPlayer().mouseInventory:GetSlot(0)) self.recipeBookUI = require("ui.recipe_book.RecipeBookUI").new( Reg.RecipeConfigID("Craft3x"), self._rootLayer, false, listenSlots, { self._onValidRecipeClicked, self }, "110" .. "110" .. "000" ) local GuiID = require("ui.GuiID") self._hkHelper = HotkeyUIHelper.new(Mod.current, GuiID.Backpack) self:_initContent() end function BackpackUI:_initContent() -- bone module local player = PlayerUtils.GetCurrentClientPlayer() local gPlayer = require("player.GPlayer").GetInstance(player) self._playerBone = gPlayer.bone self._panelStatus:getPostDrawLayer(0):addListener({ self._onRenderBone, self }) self.ui.root:addTouchUpListener({ BackpackUI._onBgClicked, self }) local maxSlots = self.container:GetSlotCount() local craftOutputTag = 65 for i = 1, maxSlots do local tag = i - 1 if tag ~= craftOutputTag then UIUtil.hookSlot(self._rootLayer:getChildByTag(tag), self, tag) end end local outputNode = self._rootLayer:getChildByTag(craftOutputTag) local outputSlot = self.currentContainer.tempSlots:GetSlot(craftOutputTag) UIUtil.hookSlotView(outputNode, outputSlot, true) outputNode:addTouchUpListener({ BackpackUI._onOutputClicked, self, outputSlot }) self._rootLayer:getChild("btn_recipe"):addTouchUpListener({ BackpackUI._onRecipeTriggerClicked, self }) self._rootLayer:getChild("btn_sort"):addTouchUpListener({ BackpackUI._onSortClicked, self }) self.ui:initUpdateFunc({ BackpackUI._onUpdate, self }) end function BackpackUI:_onUpdate() if not s_isRecipeBookReminded then self._reminderTicks = self._reminderTicks + 1 self._recipeBookIcon.sprite.style = UISpriteStyle.Filled local rate = 1.10 + Utils.SinValue(self._reminderTicks, 64) * 0.10 self._recipeBookIcon.width = 32 * rate self._recipeBookIcon.height = 32 * rate self._recipeBookIcon:applyMargin() end end function BackpackUI:_onRenderBone() local screenPos = self.ui.manager:getScreenPosition(self._panelStatus) self._playerBone.joints.position = screenPos + Vector2.new(44, 120) self._playerBone.joints.scale = Vector2.new(1.5, 1.5) --self._playerBone:update() self._playerBone.joints:render() end ---_onOutputClicked ---@param slot Slot function BackpackUI:_onOutputClicked(slot) if slot.hasStack then self.ui.manager:playClickSound() self:TriggerServerEvent(BackpackUIData.EventID.PickOutput) end end function BackpackUI:_onValidRecipeClicked(recipeID) self:TriggerServerEvent(BackpackUIData.EventID.RecipeBookRequest, tostring(recipeID)) end function BackpackUI:_onRecipeTriggerClicked() self.recipeBookUI:SetDisplayState(not self.recipeBookUI.showing) if not s_isRecipeBookReminded then s_isRecipeBookReminded = true self._recipeBookIcon.sprite.style = UISpriteStyle.Filled self._recipeBookIcon.width = 32 self._recipeBookIcon.height = 32 self._recipeBookIcon:applyMargin() end self.ui.manager:playClickSound() end function BackpackUI:_onSortClicked() self.ui.manager:playClickSound() self:TriggerServerEvent(BackpackUIData.EventID.SortBackpack) end function BackpackUI:OnUpdate() end function BackpackUI:OnClose() self._hkHelper:destroy() self.ui:closeWindow() self.recipeBookUI:closeWindow() end function BackpackUI:_onBgClicked() if require("ui.UISlotOp").onCheckPCDropOutItem() then return end self:_closeMe() end function BackpackUI:_closeMe() local player = PlayerUtils.GetCurrentClientPlayer() if player then local GuiID = require("ui.GuiID") player:CloseGui(Mod.current, GuiID.Backpack) end end ---checkSlotShiftMove ---@param slotIndex int ---@param itemStack ItemStack function BackpackUI:checkSlotShiftMove(slotIndex, itemStack) if slotIndex < 50 then -- shortcut/backpack to equipment local item = itemStack:GetItem() if item.toolType == "HELMET" then if not self.container:GetSlot(50).hasStack then return self.container, 50, 1 end elseif item.toolType == "CHESTPLATE" then if not self.container:GetSlot(51).hasStack then return self.container, 51, 1 end elseif item.toolType == "LEGGINGS" then if not self.container:GetSlot(52).hasStack then return self.container, 52, 1 end end end if slotIndex < 10 then -- shortcut to backpack return self.container, 10, 40 elseif slotIndex < 50 then -- backpack to shortcut return self.container, 0, 10 else -- equipment/craft2x to backpack/shortcut return self.container, 0, 50 end end return BackpackUI ================================================ FILE: ui/backpack/BackpackUIData.lua ================================================ local BackpackUIData = { EventID = { SortBackpack = 1, RecipeBookRequest = 2, PickOutput = 3, }, } return BackpackUIData ================================================ FILE: ui/brewing/BrewingContainerClient.lua ================================================ ---@class TC.BrewingContainerClient:Container local BrewingContainerClient = class("BrewingContainerClient", Container) local ContainerHelper = require("ui.ContainerHelper") function BrewingContainerClient:__init(player, xi, yi) BrewingContainerClient.super.__init(self) self.progress = 0 self.remainTimes = 0 self.bubbleProgressRate = 0.0 self.isBrewing = false self.TOTAL_SLOT = 54 self.tempSlots = Inventory.new(self.TOTAL_SLOT) ContainerHelper.ContainerClientInitSlots(self, self.tempSlots) end function BrewingContainerClient:OnUpdate() if not self.isBrewing then self.bubbleProgressRate = 0 else self.bubbleProgressRate = self.bubbleProgressRate + Time.deltaTime if self.bubbleProgressRate >= 1.0 then self.bubbleProgressRate = 0.0 end end end function BrewingContainerClient:OnReceiveChange(id, value) if id == 0 then self.progress = value elseif id == 1 then self.remainTimes = value elseif id == 2 then self.isBrewing = value end end return BrewingContainerClient ================================================ FILE: ui/brewing/BrewingContainerServer.lua ================================================ ---@class TC.BrewingContainerServer:Container local BrewingContainerServer = class("BrewingContainerServer", Container) local ContainerHelper = require("ui.ContainerHelper") local UIData = require("BrewingUIData") local RecipeBookServer = require("ui.recipe_book.RecipeBookServer") ---__init ---@param player Player ---@param xi int ---@param yi int function BrewingContainerServer:__init(player, xi, yi) BrewingContainerServer.super.__init(self) self.playerIndex = player.entityIndex self.inventory = player.backpackInventory self.xi = xi self.yi = yi -- 0-49 inventory ContainerHelper.ContainerServerAddBackpack(player, self) local brewingEntity = self:GetBrewingEntity() for i = 0, 3 do local slot = brewingEntity.inventory:GetSlot(i) self:AddSlotToContainer(brewingEntity.inventory, i) if i ~= 2 then slot:AddOnPickListener({ BrewingContainerServer.OnChanged, self }) slot:AddOnPushListener({ BrewingContainerServer.OnChanged, self }) end end self.recipeBookServer = RecipeBookServer.new( Reg.RecipeConfigID("Brew"), player, brewingEntity.inventory, 0, 2) end function BrewingContainerServer:GetBrewingEntity() local blockEntity = MapUtils.GetBlockEntity(Reg.BlockEntityID("BrewingEntity"), self.xi, self.yi) if blockEntity == nil then return nil end ---@type TC.BrewingEntity local modEntity = blockEntity:GetModBlockEntity() return modEntity end function BrewingContainerServer:OnChanged() local modEntity = self:GetBrewingEntity() if modEntity then modEntity:FlushRecipeData() end end function BrewingContainerServer:OnDetectChange() local modEntity = self:GetBrewingEntity() if modEntity then local progress = 0 if modEntity.totalProcessTime > 0 then progress = math.ceil(modEntity.processedTime * 16.0 / modEntity.totalProcessTime) progress = math.min(math.max(progress, 0), 16) end self:DetectAndSendChangeInteger(0, progress) self:DetectAndSendChangeInteger(1, modEntity.remainProcessTimes) self:DetectAndSendChangeBoolean(2, modEntity.currentRecipeID > 0) end end function BrewingContainerServer:OnEvent(eventId, eventString) if eventId == UIData.EventID.RecipeBookRequest then local recipeID = tonumber(eventString) self.recipeBookServer:FlushValidRecipe(recipeID) elseif eventId == UIData.EventID.PickOutput then self:TryPickOutput() end end function BrewingContainerServer:TryPickOutput() if not PlayerUtils.IsAlive(self.playerIndex) then return end local player = PlayerUtils.Get(self.playerIndex) local brewingEntity = self:GetBrewingEntity() if brewingEntity == nil then return end local inventory = player.backpackInventory local outputSlot = brewingEntity.inventory:GetSlot(2) if outputSlot.hasStack then local outStack = inventory:AddItemStack(outputSlot:GetStack()) if outStack:Valid() then player:DropItem(outStack) end outputSlot:ClearStack() end self:OnChanged() end function BrewingContainerServer:CanInteractWith(player) if self:GetBrewingEntity() == nil then return false end local ok = ContainerHelper.InInteractDistance(player, self.xi, self.yi) return ok end return BrewingContainerServer ================================================ FILE: ui/brewing/BrewingUI.lua ================================================ ---@class TC.BrewingUI:GuiContainer local BrewingUI = class("BrewingUI", GuiContainer) local UIUtil = require("ui.UIUtil") local GuiID = require("ui.GuiID") local UIData = require("BrewingUIData") local HotkeyUIHelper = require("ui.HotkeyUIHelper") ---@param container TC.BrewingContainerClient function BrewingUI:__init(container) BrewingUI.super.__init(self, container) self.brewingContainer = container self.ui = require("ui.UIWindow").new(require("ui.UIDesign").getBrewingUI(), require("ui.UIDefault").GROUP_GAME_WINDOW) self.rootLayer = self.ui.root:getChild("layer") local listenSlots = {} for i = 0, 49 do table.insert(listenSlots, self.brewingContainer.tempSlots:GetSlot(i)) end for i = 50, 51 do table.insert(listenSlots, self.brewingContainer.tempSlots:GetSlot(i)) end table.insert(listenSlots, PlayerUtils.GetCurrentClientPlayer().mouseInventory:GetSlot(0)) self.recipeBookUI = require("ui.recipe_book.RecipeBookUI").new( Reg.RecipeConfigID("Brew"), self.rootLayer, false, listenSlots, { self._onValidRecipeClicked, self }, "11" ) self._hkHelper = HotkeyUIHelper.new(Mod.current, GuiID.Brewing) self:_initContent() end function BrewingUI:_initContent() local maxSlots = self.container:GetSlotCount() for i = 1, maxSlots do local tag = i - 1 if tag == 52 then local outputNode = self.rootLayer:getChildByTag(tag) local outputSlot = self.brewingContainer.tempSlots:GetSlot(tag) UIUtil.hookSlotView(outputNode, outputSlot, true) outputNode:addTouchUpListener({ self._onOutputClicked, self, outputSlot }) else UIUtil.hookSlot(self.rootLayer:getChildByTag(tag), self, tag) end end self.rootLayer:getChild("img_process"):getPostDrawLayer(0):addListener({ BrewingUI.OnRenderProcessProgress, self }) self.rootLayer:getChild("img_bubble"):getPostDrawLayer(0):addListener({ BrewingUI.OnRenderBubbleProgress, self }) self.rootLayer:getChild("img_fuel"):getPostDrawLayer(0):addListener({ BrewingUI.OnRenderFuelProgress, self }) self.rootLayer:getChild("btn_recipe"):addTouchUpListener({ self._onRecipeTriggerClicked, self }) self.ui.root:addTouchUpListener({ self.OnBgClicked, self }) end --- ---@param node UINode ---@param canvasPos Vector2 function BrewingUI:OnRenderProcessProgress(node, canvasPos) UIUtil.renderProgress("tc:brewing_process_01", node.positionInCanvas + canvasPos, self.brewingContainer.progress, 16, 0, 1) end --- ---@param node UINode ---@param canvasPos Vector2 function BrewingUI:OnRenderBubbleProgress(node, canvasPos) UIUtil.renderProgress("tc:brewing_bubble_01", node.positionInCanvas + canvasPos, math.floor(self.brewingContainer.bubbleProgressRate * 32.0), 32, 0, -1) end --- ---@param node UINode ---@param canvasPos Vector2 function BrewingUI:OnRenderFuelProgress(node, canvasPos) UIUtil.renderProgress("tc:brewing_fuel_01", node.positionInCanvas + canvasPos, self.brewingContainer.remainTimes, 20, 0, -1) end ---@param slot Slot function BrewingUI:_onOutputClicked(slot) if slot.hasStack then self.ui.manager:playClickSound() self:TriggerServerEvent(UIData.EventID.PickOutput) end end function BrewingUI:_onValidRecipeClicked(recipeID) self:TriggerServerEvent(UIData.EventID.RecipeBookRequest, tostring(recipeID)) end function BrewingUI:_onRecipeTriggerClicked() self.recipeBookUI:SetDisplayState(not self.recipeBookUI.showing) self.ui.manager:playClickSound() end function BrewingUI:OnBgClicked() if require("ui.UISlotOp").onCheckPCDropOutItem() then return end local player = PlayerUtils.GetCurrentClientPlayer() if player then player:CloseGui(Mod.current, GuiID.Brewing) end end function BrewingUI:OnClose() self._hkHelper:destroy() self.ui:closeWindow() self.recipeBookUI:closeWindow() end return BrewingUI ================================================ FILE: ui/brewing/BrewingUIData.lua ================================================ local BackpackUIData = { EventID = { RecipeBookRequest = 1, PickOutput = 2, }, } return BackpackUIData ================================================ FILE: ui/chest/Chest30ContainerClient.lua ================================================ ---@class TC.Chest30ContainerClient:TC.IChestContainerClient local Chest30ContainerClient = class("Chest30ContainerClient", require("IChestContainerClient")) function Chest30ContainerClient:__init(player, xi, yi) Chest30ContainerClient.super.__init(self, 30, player, xi, yi) end return Chest30ContainerClient ================================================ FILE: ui/chest/Chest30ContainerServer.lua ================================================ ---@class TC.Chest30ContainerServer:TC.IChestContainerServer local Chest30ContainerServer = class("Chest30ContainerServer", require("IChestContainerServer")) ---__init ---@param player Player ---@param xi int ---@param yi int function Chest30ContainerServer:__init(player, xi, yi) Chest30ContainerServer.super.__init(self, 30, "Chest30Entity", player, xi, yi) end return Chest30ContainerServer ================================================ FILE: ui/chest/Chest30UI.lua ================================================ ---@class TC.Chest30UI:TC.IChestUI local Chest30UI = class("Chest30UI", require("IChestUI")) ---@param container TC.Chest30ContainerClient function Chest30UI:__init(container) Chest30UI.super.__init(self, require("ui.UIDesign").getChest30UI(), container, require("ui.GuiID").Chest30) end return Chest30UI ================================================ FILE: ui/chest/ChestUIData.lua ================================================ local ChestUIData = { EventID = { SortChest = 1, QuickPick = 2, QuickPush = 3, QuickStack = 4, }, } return ChestUIData ================================================ FILE: ui/chest/EnderChest30ContainerServer.lua ================================================ ---@class TC.EnderChest30ContainerServer:TC.IChestContainerServer local EnderChest30ContainerServer = class("EnderChest30ContainerServer", require("IChestContainerServer")) ---__init ---@param player Player ---@param xi int ---@param yi int function EnderChest30ContainerServer:__init(player, xi, yi) EnderChest30ContainerServer.super.__init(self, 30, "", player, xi, yi, player.enderInventory) end return EnderChest30ContainerServer ================================================ FILE: ui/chest/EnderChest30UI.lua ================================================ ---@class TC.EnderChest30UI:TC.IChestUI local EnderChest30UI = class("EnderChest30UI", require("IChestUI")) ---@param container TC.Chest30ContainerClient function EnderChest30UI:__init(container) EnderChest30UI.super.__init(self, require("ui.UIDesign").getChest30UI(), container, require("ui.GuiID").EnderChest30) end return EnderChest30UI ================================================ FILE: ui/chest/IChestContainerClient.lua ================================================ ---@class TC.IChestContainerClient:Container local IChestContainerClient = class("IChestContainerClient", Container) local ContainerHelper = require("ui.ContainerHelper") function IChestContainerClient:__init(slotCount, player, xi, yi) IChestContainerClient.super.__init(self) self.TOTAL_SLOT = slotCount + 50 self.tempSlots = Inventory.new(self.TOTAL_SLOT) ContainerHelper.ContainerClientInitSlots(self, self.tempSlots) end return IChestContainerClient ================================================ FILE: ui/chest/IChestContainerServer.lua ================================================ ---@class TC.IChestContainerServer:Container local IChestContainerServer = class("IChestContainerServer", Container) local ContainerHelper = require("ui.ContainerHelper") local UIData = require("ChestUIData") ---__init ---@param slotCount int ---@param blockEntityName string ---@param player Player ---@param xi int ---@param yi int ---@param hookInventory Inventory function IChestContainerServer:__init(slotCount, blockEntityName, player, xi, yi, hookInventory) IChestContainerServer.super.__init(self) self.playerIndex = player.entityIndex self.backpackInventory = player.backpackInventory self.xi = xi self.yi = yi -- 0-49 inventory ContainerHelper.ContainerServerAddBackpack(player, self) self.slotCount = slotCount self.hasBlockEntity = not (blockEntityName == nil or blockEntityName == "") self.blockEntityName = blockEntityName ---@type Inventory self.chestInventory = nil if self.hasBlockEntity then local chestEntity = self:GetMyEntity() self.chestInventory = chestEntity.inventory else self.chestInventory = hookInventory end for i = 1, slotCount do self:AddSlotToContainer(self.chestInventory, i - 1) end local frontID = MapUtils.GetFrontID(xi, yi) if frontID > 0 then local data = BlockUtils.GetData(frontID) if data:HasAnimation() then MapUtils.PlayAnimation(self.xi, self.yi, 0, 4, 4, true) MapUtils.SetAnimationIndex(self.xi, self.yi, 1) end if data.functionSoundId then SoundUtils.PlaySound(data.functionSoundId, xi, yi) end if data.functionSoundGroupId then SoundUtils.PlaySoundGroup(data.functionSoundGroupId, xi, yi) end end end function IChestContainerServer:OnClose() if not self.hasBlockEntity or (self.hasBlockEntity and self:IsMyEntityExist()) then local frontID = MapUtils.GetFrontID(self.xi, self.yi) if frontID > 0 then local data = BlockUtils.GetData(frontID) if data:HasAnimation() then MapUtils.PlayAnimation(self.xi, self.yi, 0, 4, 4, false) MapUtils.SetAnimationIndex(self.xi, self.yi, 0) end if data.functionSoundId2 then SoundUtils.PlaySound(data.functionSoundId2, self.xi, self.yi) end if data.functionSoundGroupId2 then SoundUtils.PlaySoundGroup(data.functionSoundGroupId2, self.xi, self.yi) end end end end function IChestContainerServer:IsMyEntityExist() local blockEntity = MapUtils.GetBlockEntity(Reg.BlockEntityID(self.blockEntityName), self.xi, self.yi) return blockEntity ~= nil end function IChestContainerServer:GetMyEntity() local blockEntity = MapUtils.GetBlockEntity(Reg.BlockEntityID(self.blockEntityName), self.xi, self.yi) if blockEntity == nil then return nil end ---@type TC.IChestEntity local modEntity = blockEntity:GetModBlockEntity() return modEntity end function IChestContainerServer:CanInteractWith(player) if (self.hasBlockEntity and not self:IsMyEntityExist()) then return false end return ContainerHelper.InInteractDistance(player, self.xi, self.yi) end function IChestContainerServer:OnEvent(eventId, eventString) if eventId == UIData.EventID.SortChest then self.chestInventory:SortAll() elseif eventId == UIData.EventID.QuickPick then self.chestInventory:QuickPushAllTo( 0, self.chestInventory.slotCount, self.backpackInventory, 0, self.backpackInventory.slotCount ) elseif eventId == UIData.EventID.QuickPush then self.backpackInventory:QuickPushAllTo( 10, 40, self.chestInventory, 0, self.chestInventory.slotCount ) elseif eventId == UIData.EventID.QuickStack then self.backpackInventory:QuickPushAllTo( 0, self.backpackInventory.slotCount, self.chestInventory, 0, self.chestInventory.slotCount, true ) end end return IChestContainerServer ================================================ FILE: ui/chest/IChestUI.lua ================================================ ---@class TC.IChestUI:GuiContainer local IChestUI = class("IChestUI", GuiContainer) local UIUtil = require("ui.UIUtil") local UIData = require("ChestUIData") local HotkeyUIHelper = require("ui.HotkeyUIHelper") ---@param container TC.IChestContainerClient function IChestUI:__init(rootNode, container, guiID) IChestUI.super.__init(self, container) self.ui = require("ui.UIWindow").new(rootNode, require("ui.UIDefault").GROUP_GAME_WINDOW) self.rootLayer = self.ui.root:getChild("layer") self.guiID = guiID self._hkHelper = HotkeyUIHelper.new(Mod.current, self.guiID) self:_innerInitContent() end function IChestUI:_innerInitContent() local maxSlots = self.container:GetSlotCount() for i = 1, maxSlots do UIUtil.hookSlot(self.rootLayer:getChildByTag(i - 1), self, i - 1) end local btnSort = self.rootLayer:getChild("btn_sort") local btnQuickPick = self.rootLayer:getChild("btn_quick_pick") local btnQuickPush = self.rootLayer:getChild("btn_quick_push") local btnQuickStack = self.rootLayer:getChild("btn_quick_stack") if btnSort:valid() then btnSort:addTouchUpListener({ IChestUI.OnSortBtnClicked, self }) end if btnQuickPick:valid() then btnQuickPick:addTouchUpListener({ IChestUI.OnQuickPickBtnClicked, self }) end if btnQuickPush:valid() then btnQuickPush:addTouchUpListener({ IChestUI.OnQuickPushBtnClicked, self }) end if btnQuickStack:valid() then btnQuickStack:addTouchUpListener({ IChestUI.OnQuickStackBtnClicked, self }) end self.ui.root:addTouchUpListener({ IChestUI.OnBgClicked, self }) end function IChestUI:OnSortBtnClicked() self.ui.manager:playClickSound() self:TriggerServerEvent(UIData.EventID.SortChest) end function IChestUI:OnQuickPushBtnClicked() self.ui.manager:playClickSound() self:TriggerServerEvent(UIData.EventID.QuickPush) end function IChestUI:OnQuickPickBtnClicked() self.ui.manager:playClickSound() self:TriggerServerEvent(UIData.EventID.QuickPick) end function IChestUI:OnQuickStackBtnClicked() self.ui.manager:playClickSound() self:TriggerServerEvent(UIData.EventID.QuickStack) end function IChestUI:OnBgClicked() if require("ui.UISlotOp").onCheckPCDropOutItem() then return end local player = PlayerUtils.GetCurrentClientPlayer() if player then player:CloseGui(Mod.current, self.guiID) end end function IChestUI:OnClose() self._hkHelper:destroy() self.ui:closeWindow() end ---checkSlotShiftMove ---@param slotIndex int ---@param itemStack ItemStack function IChestUI:checkSlotShiftMove(slotIndex, itemStack) if slotIndex < 50 then -- shortcut/backpack to chest return self.container, 50, self.container:GetSlotCount() - 50 else -- chest to shortcut/backpack return self.container, 0, 50 end end return IChestUI ================================================ FILE: ui/craft3x/Craft3xContainerClient.lua ================================================ ---@class TC.Craft3xContainerClient:Container local Craft3xContainerClient = class("Craft3xContainerClient", Container) local ContainerHelper = require("ui.ContainerHelper") ---@param player Player function Craft3xContainerClient:__init(player) Craft3xContainerClient.super.__init(self) self.TOTAL_SLOT = 60 -- 50 + 9 + 1 self.tempSlots = Inventory.new(self.TOTAL_SLOT) ContainerHelper.ContainerClientInitSlots(self, self.tempSlots) end function Craft3xContainerClient:OnEvent(eventId, eventString) end function Craft3xContainerClient:CanInteractWith(player) return true end return Craft3xContainerClient ================================================ FILE: ui/craft3x/Craft3xContainerServer.lua ================================================ ---@class TC.Craft3xContainerServer:Container local Craft3xContainerServer = class("Craft3xContainerServer", Container) local ContainerHelper = require("ui.ContainerHelper") local Craft3xHelper = require("Craft3xHelper") local RecipeBookServer = require("ui.recipe_book.RecipeBookServer") local Craft3xUIData = require("Craft3xUIData") ---__init ---@param player Player ---@param xi int ---@param yi int function Craft3xContainerServer:__init(player, xi, yi) Craft3xContainerServer.super.__init(self) self.playerIndex = player.entityIndex self.backpackInventory = player.backpackInventory self.xi = xi self.yi = yi -- 0-49 inventory ContainerHelper.ContainerServerAddBackpack(player, self) -- 0-8 inputs 9 output self.craftSlots = Inventory.new(10) for i = 0, 9 do Craft3xHelper.InitSlot(self, self.craftSlots, i) end self.recipeBookServer = RecipeBookServer.new( Reg.RecipeConfigID("Craft3x"), player, self.craftSlots, 0, 9) end function Craft3xContainerServer:OnClose() Craft3xHelper.Close(self.craftSlots, self.playerIndex, self.xi, self.yi) end function Craft3xContainerServer:CanInteractWith(player) return ContainerHelper.InInteractDistance(player, self.xi, self.yi) end function Craft3xContainerServer:OnEvent(eventId, eventString) if eventId == Craft3xUIData.EventID.RecipeBookRequest then local recipeID = tonumber(eventString) self.recipeBookServer:FlushValidRecipe(recipeID) if PlayerUtils.IsAlive(self.playerIndex) then local player = PlayerUtils.Get(self.playerIndex) player:FinishAdvancement(Reg.AdvancementID("recipe_book")) end elseif eventId == Craft3xUIData.EventID.PickOutput then Craft3xHelper.TryPickOutput(self.playerIndex, self, self.craftSlots) end end return Craft3xContainerServer ================================================ FILE: ui/craft3x/Craft3xHelper.lua ================================================ local Craft3xHelper = class("Craft3xHelper") local ContainerHelper = require("ui.ContainerHelper") ---InitSlot ---@param containerServer Container ---@param craftSlots Inventory ---@param slotIndexInCraft int function Craft3xHelper.InitSlot(containerServer, craftSlots, slotIndexInCraft) local slot = craftSlots:GetSlot(slotIndexInCraft) if slotIndexInCraft <= 8 then slot:AddOnPickListener({ Craft3xHelper.FlushDataFromInputs, containerServer, craftSlots }) slot:AddOnPushListener({ Craft3xHelper.FlushDataFromInputs, containerServer, craftSlots }) else --slot:AddOnPickListener({ Craft3xHelper.FlushDataFromOutput, containerServer, craftSlots }) end containerServer:AddSlotToContainer(craftSlots, slotIndexInCraft, true) end ---@param containerServer Container ---@param craftSlots Inventory function Craft3xHelper.FlushDataFromInputs(containerServer, craftSlots) local recipeID = RecipeUtils.SearchRecipe(Reg.RecipeConfigID("Craft3x"), craftSlots, 0, 9) if containerServer._lastCraftRecipeID == nil or containerServer._lastCraftRecipeID ~= recipeID then containerServer._lastCraftRecipeID = recipeID local outputSlot = craftSlots:GetSlot(9) outputSlot:ClearStack() if recipeID > 0 then local recipe = RecipeUtils.GetRecipe(recipeID) local resultStack = recipe.outputs[1]:GetStack() outputSlot:PushStack(resultStack:Clone()) end end end ---@param playerIndex int ---@param containerServer Container ---@param craftSlots Inventory ---@param isToMouse boolean function Craft3xHelper.TryPickOutput(playerIndex, containerServer, craftSlots, isToMouse) if PlayerUtils.IsAlive(playerIndex) then local player = PlayerUtils.Get(playerIndex) local inventory = player.backpackInventory local outputSlot = craftSlots:GetSlot(9) if outputSlot.hasStack then local ok = false if isToMouse then local mouseSlot = player.mouseInventory:GetSlot(0) if not mouseSlot.hasStack then mouseSlot:PushStack(outputSlot:GetStack()) outputSlot:ClearStack() ok = true end end if not ok then local outStack = inventory:AddItemStack(outputSlot:GetStack()) if outStack:Valid() then player:DropItem(outStack) end outputSlot:ClearStack() end end Craft3xHelper.FlushDataFromOutput(containerServer, craftSlots) end end ---@param containerServer Container ---@param craftSlots Inventory function Craft3xHelper.FlushDataFromOutput(containerServer, craftSlots) if containerServer._lastCraftRecipeID == nil or containerServer._lastCraftRecipeID == 0 then return end -- We consider that every input element only has one item! -- So just decrease every input slot by one directly. local recipe = RecipeUtils.GetRecipe(containerServer._lastCraftRecipeID) for i = 0, 8 do local inputSlot = craftSlots:GetSlot(i) if inputSlot.hasStack then inputSlot:DecrStackSize(1) end end containerServer._lastCraftRecipeID = nil Craft3xHelper.FlushDataFromInputs(containerServer, craftSlots) -- return back local returnItemSlot = recipe.outputs[2] if returnItemSlot.hasStack then local stack = returnItemSlot:GetStack():Clone() if containerServer.playerIndex ~= nil then local player = PlayerUtils.Get(containerServer.playerIndex) if player then local remain = player.backpackInventory:AddItemStack(stack) if remain:Valid() then player:DropItem(remain) end end end end end function Craft3xHelper.Close(craftSlots, playerIndex, xi, yi) ContainerHelper.CloseSendBackItems(playerIndex, xi, yi, craftSlots, { 0, 1, 2, 3, 4, 5, 6, 7, 8 }) -- directly remove the result item craftSlots:GetSlot(9):ClearStack() end return Craft3xHelper ================================================ FILE: ui/craft3x/Craft3xUI.lua ================================================ ---@class TC.Craft3xUI:GuiContainer local Craft3xUI = class("Craft3xUI", GuiContainer) local UIUtil = require("ui.UIUtil") local GuiID = require("ui.GuiID") local UIData = require("Craft3xUIData") local HotkeyUIHelper = require("ui.HotkeyUIHelper") ---@param container TC.Craft3xContainerClient function Craft3xUI:__init(container) Craft3xUI.super.__init(self, container) self.craftContainer = container self.ui = require("ui.UIWindow").new(require("ui.UIDesign").getCraft3xUI(), require("ui.UIDefault").GROUP_GAME_WINDOW) self.rootLayer = self.ui.root:getChild("layer") local listenSlots = {} for i = 0, 49 do table.insert(listenSlots, self.craftContainer.tempSlots:GetSlot(i)) end for i = 50, 58 do table.insert(listenSlots, self.craftContainer.tempSlots:GetSlot(i)) end table.insert(listenSlots, PlayerUtils.GetCurrentClientPlayer().mouseInventory:GetSlot(0)) self.recipeBookUI = require("ui.recipe_book.RecipeBookUI").new( Reg.RecipeConfigID("Craft3x"), self.rootLayer, false, listenSlots, { self._onValidRecipeClicked, self }, "111" .. "111" .. "111" ) self._hkHelper = HotkeyUIHelper.new(Mod.current, GuiID.Craft3x) self:_initContent() end function Craft3xUI:_initContent() for i = 0, 58 do UIUtil.hookSlot(self.rootLayer:getChildByTag(i), self, i) end local outputNode = self.rootLayer:getChildByTag(59) local outputSlot = self.craftContainer.tempSlots:GetSlot(59) UIUtil.hookSlotView(outputNode, outputSlot, true) outputNode:addTouchUpListener({ self._onOutputClicked, self, outputSlot }) self.rootLayer:getChild("btn_recipe"):addTouchUpListener({ Craft3xUI._onRecipeTriggerClicked, self }) self.ui.root:addTouchUpListener({ Craft3xUI.OnBgClicked, self }) end ---_onOutputClicked ---@param slot Slot function Craft3xUI:_onOutputClicked(slot) if slot.hasStack then self.ui.manager:playClickSound() if require("settings.SettingsData").isMobileOperation then self:TriggerServerEvent(UIData.EventID.PickOutput) else if Input.keyboard:isKeyPressed(Keys.LeftShift) then self:TriggerServerEvent(UIData.EventID.PickOutput) else self:TriggerServerEvent(UIData.EventID.PickOutput, "1") end end end end function Craft3xUI:_onValidRecipeClicked(recipeID) self:TriggerServerEvent(UIData.EventID.RecipeBookRequest, tostring(recipeID)) end function Craft3xUI:_onRecipeTriggerClicked() self.recipeBookUI:SetDisplayState(not self.recipeBookUI.showing) self.ui.manager:playClickSound() end function Craft3xUI:OnBgClicked() if require("ui.UISlotOp").onCheckPCDropOutItem() then return end local player = PlayerUtils.GetCurrentClientPlayer() if player then player:CloseGui(Mod.current, GuiID.Craft3x) end end function Craft3xUI:OnClose() self._hkHelper:destroy() self.ui:closeWindow() self.recipeBookUI:closeWindow() end ---checkSlotShiftMove ---@param slotIndex int ---@param itemStack ItemStack function Craft3xUI:checkSlotShiftMove(slotIndex, itemStack) if slotIndex < 10 then -- shortcut to backpack return self.container, 10, 40 elseif slotIndex < 50 then -- backpack to shortcut return self.container, 0, 10 end end return Craft3xUI ================================================ FILE: ui/craft3x/Craft3xUIData.lua ================================================ local Craft3xUIData = { EventID = { RecipeBookRequest = 1, PickOutput = 2, }, } return Craft3xUIData ================================================ FILE: ui/enchant/EnchantContainerClient.lua ================================================ ---@class TC.EnchantContainerClient:Container local EnchantContainerClient = class("EnchantContainerClient", Container) local ContainerHelper = require("ui.ContainerHelper") function EnchantContainerClient:__init(player, xi, yi) EnchantContainerClient.super.__init(self) self.TOTAL_SLOT = 50 + 2 self.tempSlots = Inventory.new(self.TOTAL_SLOT) ContainerHelper.ContainerClientInitSlots(self, self.tempSlots) self.dataChangedCallback = nil self.btnData = {} for _ = 1, 3 do table.insert(self.btnData, { needExp = 0, cost = 0, firstEnchantmentID = 0, firstEnchantmentLevel = 0, }) end end function EnchantContainerClient:OnReceiveChange(id, value) if id == 0 then local tableData = JsonUtil.fromJson(value) for i, element in ipairs(tableData) do local data = self.btnData[i] data.needExp = element.needExp data.cost = element.cost data.firstEnchantmentID = element.firstEnchantmentID data.firstEnchantmentLevel = element.firstEnchantmentLevel end if self.dataChangedCallback ~= nil and #self.dataChangedCallback == 2 then self.dataChangedCallback[1](self.dataChangedCallback[2]) end end end return EnchantContainerClient ================================================ FILE: ui/enchant/EnchantContainerServer.lua ================================================ ---@class TC.EnchantContainerServer:Container local EnchantContainerServer = class("EnchantContainerServer", Container) local ContainerHelper = require("ui.ContainerHelper") local UIData = require("EnchantUIData") local Algorithm = require("util.Algorithm") local ENCHANT_SLOTS = 2 local ENCHANT_BTN_COUNT = 3 local MAX_ENCHANT_LEVEL = 30 ---__init ---@param player Player ---@param xi int ---@param yi int function EnchantContainerServer:__init(player, xi, yi) EnchantContainerServer.super.__init(self) self.playerIndex = player.entityIndex self.inventory = player.backpackInventory self.xi = xi self.yi = yi -- 0-49 inventory ContainerHelper.ContainerServerAddBackpack(player, self) self._tempSlots = Inventory.new(ENCHANT_SLOTS) self._toolSlot = self._tempSlots:GetSlot(0) self._lapisSlot = self._tempSlots:GetSlot(1) self._btnData = {} for i = 0, ENCHANT_SLOTS - 1 do local slot = self._tempSlots:GetSlot(i) self:AddSlotToContainer(self._tempSlots, i) slot:AddOnPickListener({ EnchantContainerServer.OnChanged, self }) slot:AddOnPushListener({ EnchantContainerServer.OnChanged, self }) end end function EnchantContainerServer:OnChanged() self:_OnFlushData() end function EnchantContainerServer:_OnFlushData() local canEnchant = false local isBookEnchanting = false if self._toolSlot.hasStack then local stack = self._toolSlot:GetStack() if stack:GetItem().id == Reg.ItemID("book") then if stack.stackSize == 1 then canEnchant = true isBookEnchanting = true end elseif not stack:HasEnchantment() then canEnchant = true end end self._btnData = {} if canEnchant then local stack = self._toolSlot:GetStack() local maxCheckLevel = self:_CheckMaxLevel() -- generate level for every button local expLevels = {} for i = 1, ENCHANT_BTN_COUNT do local expLevel = math.ceil(maxCheckLevel * i / ENCHANT_BTN_COUNT - 2 + math.random(0, 4)) expLevels[i] = math.max(1, math.min(MAX_ENCHANT_LEVEL, expLevel)) end for i = 1, ENCHANT_BTN_COUNT do local expLevel = expLevels[i] -- calculate how many enchantments can attach in current item local maxAttachCount = math.max(1, math.ceil(expLevel / 30 * 4)) maxAttachCount = math.random(1, maxAttachCount) -- get all available enchantments local pendingEnchantmentIDs = {} for enchantmentID = 1, Reg.MaxEnchantmentID() do local data = EnchantmentUtils.GetData(enchantmentID) -- reach the enchantment level limit if not data.noCreating and expLevel >= data.minCreatingLevel then -- current item can use this enchantment if isBookEnchanting or data:IsToolTypeValid(stack:GetItem().toolType) then table.insert(pendingEnchantmentIDs, enchantmentID) end end end -- random shuffle the available enchantment list Algorithm.Shuffle(pendingEnchantmentIDs) local resultIDs = {} local resultEnchantments = {} local times = 0 for _, enchantmentID in ipairs(pendingEnchantmentIDs) do local ok = false if #resultIDs == 0 then ok = true else -- skip if this enchantment conflict with exist enchantments ok = true for _, existID in ipairs(resultIDs) do if EnchantmentUtils.IsConflict(enchantmentID, existID) then ok = false break end end end if ok then local data = EnchantmentUtils.GetData(enchantmentID) local t = math.max(1, math.floor(data.allowMaxLevel * expLevel / 30)) local level = math.random(1, t) times = times + 1 if times > maxAttachCount then break end local enchantment = Enchantment.new(enchantmentID, level) table.insert(resultIDs, enchantmentID) table.insert(resultEnchantments, enchantment) end end local cost = self:_GetCostExpLevel(expLevel) table.insert(self._btnData, { expLevel = expLevel, enchantments = resultEnchantments, costExpLevel = cost, enabled = self:_IsBtnEnable(expLevel, cost) }) end end if #self._btnData ~= ENCHANT_BTN_COUNT then canEnchant = false else for _, data in ipairs(self._btnData) do if #data.enchantments == 0 then canEnchant = false break end end end if not canEnchant then -- remove all data self._btnData = {} end self:_SendData() end function EnchantContainerServer:_SendData() local tableData = {} for i = 1, ENCHANT_BTN_COUNT do local data = self._btnData[i] local needExp = 0 local cost = 0 local firstEnchantmentID = 0 local firstEnchantmentLevel = 0 if data ~= nil then needExp = data.expLevel * (data.enabled and 1 or -1) cost = data.costExpLevel local enchantment = data.enchantments[1] if enchantment then firstEnchantmentID = enchantment.id firstEnchantmentLevel = enchantment.level end end table.insert(tableData, { needExp = needExp, cost = cost, firstEnchantmentID = firstEnchantmentID, firstEnchantmentLevel = firstEnchantmentLevel, }) end local jsonString = JsonUtil.toJson(tableData) self:DetectAndSendChangeString(0, jsonString) end function EnchantContainerServer:_CheckMaxLevel() local sourceXi = self.xi local sourceYi = self.yi local BLOCK_BOOK_ID = Reg.BlockID("tc:book") local BOOKCASE_SUB_GROUP_ID = Reg.BlockSubGroupID("BOOKCASE") -- Get books and bookcases around the enchantment table to -- gain how many level can reach. local maxCheckLevel = 0 for xi = sourceXi - 5, sourceXi + 5 do for yi = sourceYi - 6, sourceYi do local blockID = MapUtils.GetFrontID(xi, yi) if blockID > 0 then local cxi, cyi = MapUtils.GetBodyPos(xi, yi) if xi == cxi and yi == cyi then if blockID == BLOCK_BOOK_ID then maxCheckLevel = maxCheckLevel + 2 else local data = BlockUtils.GetData(blockID) if data.subGroup == BOOKCASE_SUB_GROUP_ID then maxCheckLevel = maxCheckLevel + 8 end end end end end end maxCheckLevel = math.max(1, math.min(MAX_ENCHANT_LEVEL, maxCheckLevel)) return maxCheckLevel end function EnchantContainerServer:OnEvent(eventId, eventString) if eventId == UIData.EventID.ClickBtn then local index = tonumber(eventString) if index == nil then return end if not (index >= 1 and index <= 3) then return end self:_OnClickBtn(index) end end function EnchantContainerServer:_OnClickBtn(index) if not (index >= 1 and index <= ENCHANT_BTN_COUNT) then return end if #self._btnData ~= ENCHANT_BTN_COUNT then return end if not self._toolSlot.hasStack then return end local data = self._btnData[index] if not data.enabled then return end local stack = self._toolSlot:GetStack() if stack:GetItem().id == Reg.ItemID("book") then if stack.stackSize ~= 1 then return end self._toolSlot:ClearStack() self._toolSlot:PushStack(ItemStack.new(ItemRegistry.GetItemByIDName("enchanted_book"))) end local costExpLevel = data.costExpLevel local enchantments = data.enchantments stack = self._toolSlot:GetStack() for _, enchantment in ipairs(enchantments) do stack:AddEnchantment(enchantment.id, enchantment.level) end SoundUtils.PlaySoundGroup(Reg.SoundGroupID("enchant"), self.xi, self.yi) -- reduce exp local player = PlayerUtils.Get(self.playerIndex) if player then player:RemoveExpLevel(costExpLevel) end -- reduce lapis if self._lapisSlot.hasStack then self._lapisSlot:DecrStackSize(costExpLevel) end self:OnChanged() end function EnchantContainerServer:_GetCostExpLevel(targetExpLevel) return math.max(1, math.ceil(targetExpLevel / 10.0)) end function EnchantContainerServer:_IsBtnEnable(targetExpLevel, costExpLevel) local player = PlayerUtils.Get(self.playerIndex) if not player then return false end -- check player experience level if player.expLevel < targetExpLevel or player.expLevel < costExpLevel then return false end -- check lapis count if not self._lapisSlot.hasStack then return false end local stack = self._lapisSlot:GetStack() if stack:GetItem().id ~= Reg.ItemID("lapis_lazuli") then return false end if stack.stackSize < costExpLevel then return false end return true end function EnchantContainerServer:CanInteractWith(player) local ok = ContainerHelper.InInteractDistance(player, self.xi, self.yi) return ok end function EnchantContainerServer:OnClose() ContainerHelper.CloseSendBackItems(self.playerIndex, self.xi, self.yi, self._tempSlots, { 0, 1 }) end return EnchantContainerServer ================================================ FILE: ui/enchant/EnchantUI.lua ================================================ ---@class TC.EnchantUI:GuiContainer local EnchantUI = class("EnchantUI", GuiContainer) local UIUtil = require("ui.UIUtil") local GuiID = require("ui.GuiID") local UISpritePool = require("ui.UISpritePool") local StringUtil = require("util.StringUtil") local UIData = require("EnchantUIData") local HotkeyUIHelper = require("ui.HotkeyUIHelper") ---@param container TC.EnchantContainerClient function EnchantUI:__init(container) EnchantUI.super.__init(self, container) self.enchantContainer = container self.enchantContainer.dataChangedCallback = { self._OnDataChanged, self } self.ui = require("ui.UIWindow").new(require("ui.UIDesign").getEnchantmentUI(), require("ui.UIDefault").GROUP_GAME_WINDOW) self.rootLayer = self.ui.root:getChild("layer") self._panelButtons = { UIPanel.cast(self.rootLayer:getChild("panel_btn_1")), UIPanel.cast(self.rootLayer:getChild("panel_btn_2")), UIPanel.cast(self.rootLayer:getChild("panel_btn_3")), } self._hkHelper = HotkeyUIHelper.new(Mod.current, GuiID.Enchantment) self:_initContent() end function EnchantUI:_initContent() local maxSlots = self.container:GetSlotCount() for i = 1, maxSlots do local tag = i - 1 UIUtil.hookSlot(self.rootLayer:getChildByTag(tag), self, tag) end self.ui.root:addTouchUpListener({ self.OnBgClicked, self }) ---@param panelBtn UIPanel for i, panelBtn in ipairs(self._panelButtons) do panelBtn:addTouchUpListener({ self._OnBtnClicked, self, i }) end self:_FlushButtons() end function EnchantUI:_OnBtnClicked(index) self:TriggerServerEvent(UIData.EventID.ClickBtn, tostring(index)) end function EnchantUI:_OnDataChanged() self:_FlushButtons() end function EnchantUI:_FlushButtons() local btnData = self.enchantContainer.btnData for i, data in ipairs(btnData) do ---@type UIPanel local panelBtn = self._panelButtons[i] local visible = data.needExp ~= 0 panelBtn:getChild("img_exp").visible = visible panelBtn:getChild("lb_exp").visible = visible panelBtn:getChild("lb_cost").visible = visible panelBtn:getChild("lb_preview").visible = visible if data.needExp <= 0 then panelBtn.sprite = UISpritePool.getInstance():get("tc:base_list_cell") else panelBtn.sprite = UISpritePool.getInstance():get("tc:base_list_cell_highlight_2") end if visible then local previewText = "..." if data.firstEnchantmentID > 0 and data.cost <= 20 then previewText = string.format("%s %s ...", LangUtils.EnchantmentName(data.firstEnchantmentID), StringUtil.NumberToRoman(data.firstEnchantmentLevel) ) end local displayNeedExp = math.abs(data.needExp) local cost = data.cost if cost >= 1 and cost <= 3 then UIImage.cast(panelBtn:getChild("img_exp")).sprite = UISpritePool.getInstance():get( string.format("tc:enchantment_exp_%d", cost)) end UIText.cast(panelBtn:getChild("lb_preview")).text = previewText UIText.cast(panelBtn:getChild("lb_exp")).text = tostring(displayNeedExp) UIText.cast(panelBtn:getChild("lb_cost")).text = tostring(cost) end end end function EnchantUI:OnBgClicked() if require("ui.UISlotOp").onCheckPCDropOutItem() then return end local player = PlayerUtils.GetCurrentClientPlayer() if player then player:CloseGui(Mod.current, GuiID.Enchantment) end end function EnchantUI:OnClose() self._hkHelper:destroy() self.ui:closeWindow() end ---checkSlotShiftMove ---@param slotIndex int ---@param itemStack ItemStack function EnchantUI:checkSlotShiftMove(slotIndex, itemStack) if slotIndex ~= 51 then if itemStack:GetItem().id == Reg.ItemID("lapis_lazuli") then return self.container, 51, 1 end else return self.container, 0, 50 end if slotIndex < 10 then -- shortcut to backpack return self.container, 10, 40 elseif slotIndex < 50 then -- backpack to shortcut return self.container, 0, 10 end end return EnchantUI ================================================ FILE: ui/enchant/EnchantUIData.lua ================================================ local EnchantUIData = { EventID = { ClickBtn = 1, }, } return EnchantUIData ================================================ FILE: ui/hud/HudUI.lua ================================================ ---@class TC.HudUI:TC.UIWindow local HudUI = class("HudUI", require("ui.UIWindow")) local InputControl = require("client.InputControl") local UISpritePool = require("ui.UISpritePool") local UIUtil = require("ui.UIUtil") local UISlotOp = require("ui.UISlotOp") local SettingsData = require("settings.SettingsData") local GPlayer = require("player.GPlayer") local MusicSystem = require("client.MusicSystem") local UIDefault = require("ui.UIDefault") local s_instance local ADVANCEMENT_TIP_FADE_IN_TIME = 32 local ADVANCEMENT_TIP_FADE_OUT_TIME = 64 * 5 local ADVANCEMENT_TIP_FADE_IDLE_TIME = 32 local ADVANCEMENT_TIP_FADE_OUT_START_TIME = ADVANCEMENT_TIP_FADE_IN_TIME + ADVANCEMENT_TIP_FADE_OUT_TIME local ADVANCEMENT_TIP_TOTAL_TIME = ADVANCEMENT_TIP_FADE_OUT_START_TIME + ADVANCEMENT_TIP_FADE_IDLE_TIME ---@class TC.AdvancementTipData local AdvancementTipData = class("AdvancementTipData") ---__init ---@param node UINode ---@param itemStack ItemStack function AdvancementTipData:__init(node, itemStack) self.node = node self.itemStack = itemStack self.tickTime = 0 end function HudUI:__init() HudUI.super.__init(self, require("ui.UIDesign").getHudUI(), UIDefault.GROUP_GAME_HUD) s_instance = self self._centerTouchTicks = 0 self._lastCenterTouchPos = nil self._debugLabel = UIText.cast(self.root:getChild("lb_debug")) self._lbHp = UIText.cast(self.root:getChild("lb_hp")) self._lbMana = UIText.cast(self.root:getChild("lb_mana")) self._lbExpLevel = UIText.cast(self.root:getChild("panel_shortcut.lb_exp")) self._lbItemName = UIText.cast(self.root:getChild("panel_shortcut.lb_item_name")) self._panelBtn = self.root:getChild("panel_btn") self._btnFrontWall = UIButton.cast(self._panelBtn:getChild("check_box_front_or_wall")) self._btnSmart = UIButton.cast(self._panelBtn:getChild("check_box_smart")) self._btnBackpack = UIButton.cast(self._panelBtn:getChild("button_backpack")) self._btnRecipe = UIButton.cast(self._panelBtn:getChild("button_recipe")) self._btnOption = UIButton.cast(self._panelBtn:getChild("button_option")) self._btnAdvancement = UIButton.cast(self._panelBtn:getChild("button_task")) self._jl = UIJoystick.cast(self.root:getChild("joystick_left")) self._jr = UIJoystick.cast(self.root:getChild("joystick_right")) self._jc = UIJoystick.cast(self.root:getChild("joystick_center")) self._musicNameCR = UIText.cast(self.root:getChild("lb_music_name")) self._musicAuthorCR = UIText.cast(self.root:getChild("lb_music_author")) self._advancementPanel = UIPanel.cast(self.root:getChild("panel_advancements")) self._baseAdvancementTipNode = UIPanel.cast(self._advancementPanel:getChild("panel_advancement_tip")) self._advancementTips = {} ---@type TC.AdvancementTipData[] self._advancementTipX = self._baseAdvancementTipNode.positionX self._advancementTipHeight = self._baseAdvancementTipNode.height local uiSpritePool = UISpritePool.getInstance() self._textureAim = uiSpritePool:get("tc:aim").textureLocation self._textureHealth = uiSpritePool:get("tc:health").textureLocation self._textureHunger = uiSpritePool:get("tc:hunger").textureLocation self._textureMana = uiSpritePool:get("tc:mana").textureLocation self._textureExpBar = uiSpritePool:get("tc:exp_bar").textureLocation self._lastHp = -1 self._lastMaxHp = -1 self._lastMana = -1 self._lastMaxMana = -1 self._lastExpLevel = -1 self._lastHeldIndex = -1 self._lastManaIconLines = 0 self._manaIconLines = 0 self._tickTime = 0 self._itemNameHideTickTime = 0 self._initPlayerData = false self._shortcutSlotNodes = {} self:loadHotkeys() self:initContent() end function HudUI:loadHotkeys() local inputControl = InputControl.getInstance() self._backpackHotKey = Input.keyboard:getHotKeys(inputControl.keyMap.Backpack):addListener({ HudUI._tryOpenBackpack, self }) self._taskHotKey = Input.keyboard:getHotKeys(inputControl.keyMap.Task):addListener({ HudUI._tryOpenTask, self }) self._neiHotKey = Input.keyboard:getHotKeys(inputControl.keyMap.Nei):addListener({ HudUI._tryOpenNei, self }) self._optionHotKey = Input.keyboard:getHotKeys(inputControl.keyMap.Esc):addListener({ HudUI._onEsc, self }) self._smartHotKey = Input.keyboard:getHotKeys(inputControl.keyMap.Ctrl):addListener({ HudUI._onCtrl, self }) end function HudUI:destroyHotkeys() if self._backpackHotKey then Input.keyboard:getHotKeys(InputControl.getInstance().keyMap.Backpack):removeListener(self._backpackHotKey) self._backpackHotKey = nil end if self._taskHotKey then Input.keyboard:getHotKeys(InputControl.getInstance().keyMap.Task):removeListener(self._taskHotKey) self._taskHotKey = nil end if self._neiHotKey then Input.keyboard:getHotKeys(InputControl.getInstance().keyMap.Nei):removeListener(self._neiHotKey) self._neiHotKey = nil end if self._optionHotKey then Input.keyboard:getHotKeys(InputControl.getInstance().keyMap.Esc):removeListener(self._optionHotKey) self._optionHotKey = nil end if self._smartHotKey then Input.keyboard:getHotKeys(InputControl.getInstance().keyMap.Ctrl):removeListener(self._smartHotKey) self._smartHotKey = nil end end function HudUI:initContent() local inputControl = InputControl.getInstance() local jl = self._jl local jr = self._jr local jc = self._jc inputControl.virtualJoystickLeftNode = jl inputControl.virtualJoystickRightNode = jr inputControl.virtualJoystickCenterNode = jc -- catch all touches for map operation self.root.touchable = true self.root:addTouchDownListener({ HudUI.onMapTouchDown, self }) jc:addTouchDownListener({ HudUI.onTouchDownCenter, self }) jc:addTouchUpAfterMoveListener({ HudUI.onTouchUpCenter, self }) self.root:getChild("panel_shortcut"):getPreDrawLayer(0):addListener({ HudUI._onRenderExpBar, self }) self.root:getChild("panel_element_base"):getPreDrawLayer(0):addListener({ HudUI._onRenderHudElement, self }) self._btnFrontWall:addTouchUpListener({ HudUI._onFrontWallClicked, self }) self._btnSmart:addTouchUpListener({ HudUI._onSmartClicked, self }) self._btnBackpack:addTouchUpListener({ HudUI._onBackpackClicked, self }) self._btnRecipe:addTouchUpListener({ HudUI._onRecipeBtnClicked, self }) self._btnOption:addTouchUpListener({ HudUI._onOptionBtnClicked, self }) self._btnAdvancement:addTouchUpListener({ HudUI._onTaskBtnClicked, self }) end function HudUI.showAdvancementTip(advancementID) if s_instance == nil then return end s_instance:createAdvancementTipUI(advancementID) end function HudUI:createAdvancementTipUI(advancementID) local advancement = AdvancementUtils.Get(advancementID) local itemStack = ItemStack.new(ItemRegistry.GetItemByID(advancement.itemID)) local node = self._baseAdvancementTipNode:clone() UIText.cast(node:getChild("lb_sub_caption")).text = LangUtils.AdvancementName(advancementID) node:getChild("panel_icon"):getPostDrawLayer(0):addListener( { UISlotOp.itemStackOnRenderWithShadow, itemStack }) node.visible = true self._advancementPanel:addChild(node) table.insert(self._advancementTips, AdvancementTipData.new(node, itemStack)) end function HudUI._changeBtnSprite(btn, flag, spriteName1, spriteName2) local spriteName = flag and spriteName1 or spriteName2 local sprite = UISpritePool.getInstance():get(spriteName) local color = Color.new(255, 255, 255, 200) btn.targetSprite = sprite btn.targetSprite.color = color btn.selectedSprite = sprite btn.selectedSprite.color = color btn.pressedSprite = sprite btn.pressedSprite.color = color btn.highlightedSprite = sprite btn.highlightedSprite.color = color end function HudUI:_onFrontWallClicked() self.manager:playClickSound() local inputControl = InputControl.getInstance() inputControl.operatingWall = not inputControl.operatingWall HudUI._changeBtnSprite(self._btnFrontWall, inputControl.operatingWall, "tc:check_box_front_or_wall_2", "tc:check_box_front_or_wall" ) end function HudUI:_onSmartClicked() self.manager:playClickSound() local inputControl = InputControl.getInstance() inputControl.isSmart = not inputControl.isSmart HudUI._changeBtnSprite(self._btnSmart, inputControl.isSmart, "tc:check_box_smart_2", "tc:check_box_smart" ) end function HudUI:_onBackpackClicked() self:_tryOpenBackpack() self.manager:playClickSound() end function HudUI:_tryOpenBackpack() if self.manager:hasUIGroup(UIDefault.GROUP_GAME_WINDOW) then return end local player = PlayerUtils.GetCurrentClientPlayer() if not player then return end local GuiID = require("ui.GuiID") if player:IsGuiOpened(Mod.current, GuiID.Backpack) then return end player:OpenGuiRemote(Mod.current, GuiID.Backpack, player.centerXi, player.centerYi) end function HudUI:_onTaskBtnClicked() self:_tryOpenTask() self.manager:playClickSound() end function HudUI:_tryOpenTask() if self.manager:hasUIGroup(UIDefault.GROUP_GAME_WINDOW) then return end local player = PlayerUtils.GetCurrentClientPlayer() if not player then return end local GuiID = require("ui.GuiID") if player:IsGuiOpened(Mod.current, GuiID.Advancement) then return end player:OpenGui(Mod.current, GuiID.Advancement, player.centerXi, player.centerYi) end function HudUI:_tryOpenNei() if self.manager:hasUIGroup(UIDefault.GROUP_GAME_WINDOW) then return end require("ui.nei.NeiUI").new() end function HudUI:_openRecipe() self:_tryOpenNei() end function HudUI:_onRecipeBtnClicked() self.manager:playClickSound() self:_openRecipe() end function HudUI:_onOptionBtnClicked() self.manager:playClickSound() self:_tryOpenOption() end function HudUI:_onEsc() self:_tryOpenOption() end function HudUI:_onCtrl() if self.manager:hasUIGroup(UIDefault.GROUP_GAME_WINDOW) then return end self:_onSmartClicked() end function HudUI:_tryOpenOption() if self.manager:hasUIGroup(UIDefault.GROUP_GAME_WINDOW) then return end if self.manager:isWindowOpened("OptionUI") then return end require("ui.OptionUI").new() end function HudUI:_checkPlayerData() if self._initPlayerData then return end local player = PlayerUtils.GetCurrentClientPlayer() if player then self._initPlayerData = true local backpackInventory = player.backpackInventory local panelShortcut = self.root:getChild("panel_shortcut") for i = 1, 10 do local slotNode = UIButton.cast(panelShortcut:getChildByTag(i - 1)) table.insert(self._shortcutSlotNodes, slotNode) UIUtil.hookSlotView(slotNode, backpackInventory:GetSlot(i - 1), false) slotNode:addTouchDownListener({ HudUI._onSlotTouchDown, self, i - 1 }) end self:refreshShortcut(player) end end function HudUI:_onSlotTouchDown(index, _, _) local player = PlayerUtils.GetCurrentClientPlayer() if player then player.heldSlotIndex = index self:refreshShortcut(player) end end ---@param player Player function HudUI:refreshShortcut(player) local heldIndex = player.heldSlotIndex if self._lastHeldIndex == heldIndex then return end self._lastHeldIndex = heldIndex for i = 1, #self._shortcutSlotNodes do self._shortcutSlotNodes[i].selected = (i - 1 == heldIndex) end local itemName = "" local slot = player.backpackInventory:GetSlot(heldIndex) if slot.hasStack then local itemId = slot:GetStack():GetItem().id itemName = LangUtils.ItemName(itemId) end self._lbItemName.text = itemName self._lbItemName.color = Color.new(193, 187, 220) self._lbItemName.visible = true self._itemNameHideTickTime = 64 end ---onTouchDownCenter ---@param touch Touch function HudUI:onTouchDownCenter(_, touch) self._lastCenterTouchPos = touch.position:clone() self._centerTouchTicks = 64 end ---@param touch Touch function HudUI:onTouchUpCenter(_, touch) if self._lastCenterTouchPos ~= nil then local d = touch.position:getDistance(self._lastCenterTouchPos) if d < 6 then self:activateMapClicking(touch.position) end end end function HudUI:updateTouchTicking() if self._centerTouchTicks == 0 then self._lastCenterTouchPos = nil elseif self._centerTouchTicks > 0 then self._centerTouchTicks = self._centerTouchTicks - 1 end end ---activateMapClicking ---@param touchPosition Vector2 function HudUI:activateMapClicking(touchPosition) local inputControl = InputControl.getInstance() inputControl.isMapClicking = true inputControl.touchMapPosition = touchPosition:clone() --print("touch map", inputControl.touchMapPosition) end ---onMapTouchDown ---@param touch Touch function HudUI:onMapTouchDown(_, touch) if not SettingsData.isMobileOperation then if not Input.mouse.isRightButtonPressed then return end end self:activateMapClicking(touch.position) end function HudUI:update() --self._debugLabel.text = string.format("FPS:%d Logic:%d Batches:%d Triangles:%d", -- IntegratedClient.main.fps, -- IntegratedClient.main.gameSpeed, -- GraphicsDevice.drawCalls, -- GraphicsDevice.primitiveCount --) --self._debugLabel.isRichText = true self._debugLabel.visible = false local showMobileLayout = SettingsData.isMobileOperation self._jl.visible = showMobileLayout self._jr.visible = showMobileLayout self._jc.visible = showMobileLayout self._panelBtn.visible = showMobileLayout local inputControl = InputControl.getInstance() inputControl.isPcMouseAtMap = false if not SettingsData.isMobileOperation then local pointer = self.manager.canvas:screenPointToCanvasPoint(Input.mouse.position) local node = self.manager.baseLayer:getPointedNode(pointer) if node:valid() then if node.name == "hud_ui" then inputControl.isPcMouseAtMap = true end end end if SettingsData.showMusicInfo and MusicSystem.getInstance().musicCopyright ~= nil and Audio.musicVolume > 0.3 then local cr = MusicSystem.getInstance().musicCopyright self._musicNameCR.visible = true self._musicAuthorCR.visible = true self._musicNameCR.text = cr.title self._musicAuthorCR.text = cr.author else self._musicNameCR.visible = false self._musicAuthorCR.visible = false end -- 先屏蔽 self._musicNameCR.visible = false self._musicAuthorCR.visible = false self:_checkPlayerData() local player = PlayerUtils.GetCurrentClientPlayer() if player then self:refreshShortcut(player) if not (player.health == self._lastHp and player.maxHealth == self._lastMaxHp) then self._lastHp = player.health self._lastMaxHp = player.maxHealth self._lbHp.text = string.format("%d/%d", player.health, player.maxHealth) self._lbHp.isRichText = true self._lbHp:setPosition(16, 46) end if not (player.mana == self._lastMana and player.maxMana == self._lastMaxMana and self._manaIconLines == self._lastManaIconLines) then self._lastMana = player.mana self._lastHp = player.health self._lastManaIconLines = self._manaIconLines self._lbMana.text = string.format("%d/%d", player.mana, player.maxMana) self._lbMana.isRichText = true self._lbMana:setPosition(16, 100 + (self._manaIconLines - 1) * 32) end if not (player.expLevel == self._lastExpLevel) then self._lastExpLevel = player.expLevel self._lbExpLevel.text = string.format("%d", player.expLevel) self._lbExpLevel.isRichText = true end end self._tickTime = self._tickTime + 1 if self._itemNameHideTickTime > 0 then self._itemNameHideTickTime = self._itemNameHideTickTime - 1 if self._itemNameHideTickTime == 0 then self._lbItemName.visible = false end end local currentX = self._advancementTipX local currentY = 0 local TIP_HEIGHT = self._advancementTipHeight for i = #self._advancementTips, 1, -1 do local data = self._advancementTips[i] data.tickTime = data.tickTime + 1 local t = data.tickTime if t >= ADVANCEMENT_TIP_TOTAL_TIME then self._advancementPanel:removeChild(data.node) table.remove(self._advancementTips, i) else local deltaY = 0 if t < ADVANCEMENT_TIP_FADE_IN_TIME then deltaY = (t * 1.0 / ADVANCEMENT_TIP_FADE_IN_TIME - 1.0) * TIP_HEIGHT elseif t < ADVANCEMENT_TIP_FADE_OUT_START_TIME then deltaY = 0 else deltaY = ((ADVANCEMENT_TIP_TOTAL_TIME - t) * 1.0 / ADVANCEMENT_TIP_FADE_IN_TIME - 1.0) * TIP_HEIGHT end currentY = currentY + deltaY data.node:setPosition(currentX, currentY) currentY = currentY + TIP_HEIGHT end end end function HudUI:_onRenderHudElement() local player = PlayerUtils.GetCurrentClientPlayer() if not player then return end self:_renderAim(player) self:_renderHp(player) self:_renderMana(player) self:_renderHunger(player) end function HudUI:renderGaming() end ---@param player Player function HudUI:_renderAim(player) -- only render in mobile if not SettingsData.isMobileOperation then return end local globalPlayer = GPlayer.GetInstance(player) if not globalPlayer.showingAimPoint then return end local show = false local inputControl = InputControl.getInstance() if inputControl.aimMode == 1 then if inputControl.aimDistance > 0.05 and inputControl.aimPressing then show = true end else show = true end if show and not (globalPlayer.aimOffsetX == 0 and globalPlayer.aimOffsetY == 0) then local cutRect = Rect.new(0, 0, 32, 32) local drawX = player.centerX + globalPlayer.aimOffsetX - 16 - MiscUtils.screenX local drawY = player.centerY + globalPlayer.aimOffsetY - 16 - MiscUtils.screenY Sprite.draw(self._textureAim, Vector2.new(drawX, drawY), cutRect, Color.White) end end ---@param player Player function HudUI:_renderHp(player) if player.gameMode == GameMode.Creative then return end local FIX_LEFT_X = 16 local FIX_TOP_Y = 16 local VALUE_PRE_HEART = 20 local ALPHA_EMPTY = 32 local SCALE_EMPTY = 0.75 local DEFAULT_STEP = 26 local maxHp = player.maxHealth local hp = player.health local cnt = math.ceil(maxHp * 1.0 / VALUE_PRE_HEART) local index = math.min(math.floor(hp / VALUE_PRE_HEART), cnt - 1) local drawX, drawY = FIX_LEFT_X, FIX_TOP_Y local cutRect = Rect.new(0, 0, 32, 32) local color = Color.White local spriteEx = SpriteExData.new() for i = 0, cnt - 1 do local scale = 1 local alpha = 255 if i == index then if hp ~= maxHp then scale = 1 + Utils.SinValue(self._tickTime, 64) * 0.0625 alpha = math.floor(ALPHA_EMPTY + (255 - ALPHA_EMPTY) * (hp - index * VALUE_PRE_HEART) / VALUE_PRE_HEART) end elseif i > index then scale = SCALE_EMPTY alpha = ALPHA_EMPTY end color = Color.new(255, 255, 255, alpha) spriteEx.scaleRateX = scale spriteEx.scaleRateY = scale local offset = 32 * -(scale - 1) / 2 local realDrawX = math.floor(drawX + offset) local realDrawY = math.floor(drawY + offset) Sprite.draw(self._textureHealth, Vector2.new(realDrawX, realDrawY), cutRect, color, spriteEx, 0) local step = DEFAULT_STEP if maxHp > 100 then step = step - math.floor((maxHp - 100) / 40) end step = math.max(step, 14) drawX = drawX + step end end ---@param player Player function HudUI:_renderHunger(player) if player.gameMode == GameMode.Creative then return end local VALUE_PRE_HEART = 10 local MAX_HUNGER = 100 local DEFAULT_STEP = 26 local ALPHA_EMPTY = 32 local SCALE_EMPTY = 0.75 local hunger = player.foodLevel local cnt = math.ceil(MAX_HUNGER * 1.0 / VALUE_PRE_HEART) local index = math.min(math.floor(hunger / VALUE_PRE_HEART), cnt - 1) local FIX_RIGHT_X = GameWindow.displayResolution.width - 16 local FIX_TOP_Y = 16 local drawX, drawY = FIX_RIGHT_X - DEFAULT_STEP, FIX_TOP_Y local cutRect = Rect.new(0, 0, 32, 32) local color = Color.White local spriteEx = SpriteExData.new() for i = 0, cnt - 1 do local scale = 1 local alpha = 255 if i == index then if hunger ~= MAX_HUNGER then scale = 1 + Utils.SinValue(self._tickTime, 64) * 0.0625 alpha = math.floor(ALPHA_EMPTY + (255 - ALPHA_EMPTY) * (hunger - index * VALUE_PRE_HEART) / VALUE_PRE_HEART) end elseif i > index then scale = SCALE_EMPTY alpha = ALPHA_EMPTY end color = Color.new(255, 255, 255, alpha) spriteEx.scaleRateX = scale spriteEx.scaleRateY = scale local offset = 32 * -(scale - 1) / 2 local realDrawX = math.floor(drawX + offset) local realDrawY = math.floor(drawY + offset) Sprite.draw(self._textureHunger, Vector2.new(realDrawX, realDrawY), cutRect, color, spriteEx, 0) drawX = drawX - DEFAULT_STEP end end ---@param player Player function HudUI:_renderMana(player) if player.gameMode == GameMode.Creative then return end local FIX_LEFT_X = 16 local FIX_TOP_Y = 70 local VALUE_PRE_HEART = 20 local ALPHA_EMPTY = 128 local SCALE_EMPTY = 0.75 local DEFAULT_STEP = 26 local DEFAULT_STEP_Y = 32 local DISPLAY_DISTANCE_PRE_LINE = 260 local maxMana = player.maxMana local mana = player.mana local cnt = math.ceil(maxMana * 1.0 / VALUE_PRE_HEART) local index = math.min(math.floor(mana / VALUE_PRE_HEART), cnt - 1) local drawX, drawY = FIX_LEFT_X, FIX_TOP_Y local maxDrawX = FIX_LEFT_X + DISPLAY_DISTANCE_PRE_LINE local cutRect = Rect.new(0, 0, 32, 32) local color = Color.White local spriteEx = SpriteExData.new() self._manaIconLines = 1 for i = 0, cnt - 1 do local scale = 1 local alpha = 255 if i == index then if mana ~= maxMana then scale = 1 + Utils.SinValue(self._tickTime, 64) * 0.0625 alpha = math.floor(ALPHA_EMPTY + (255 - ALPHA_EMPTY) * (mana - index * VALUE_PRE_HEART) / VALUE_PRE_HEART) end elseif i > index then scale = SCALE_EMPTY alpha = ALPHA_EMPTY end color = Color.new(255, 255, 255, alpha) spriteEx.scaleRateX = scale spriteEx.scaleRateY = scale local offset = 32 * -(scale - 1) / 2 local realDrawX = math.floor(drawX + offset) local realDrawY = math.floor(drawY + offset) Sprite.draw(self._textureMana, Vector2.new(realDrawX, realDrawY), cutRect, color, spriteEx, 0) local step = DEFAULT_STEP drawX = drawX + step if drawX >= maxDrawX then drawX = FIX_LEFT_X drawY = drawY + DEFAULT_STEP_Y if i < cnt - 1 then self._manaIconLines = self._manaIconLines + 1 end end end end ---@param node UINode ---@param canvasPos Vector2 function HudUI:_onRenderExpBar(node, canvasPos) local player = PlayerUtils.GetCurrentClientPlayer() if not player then return end local needExp = player:GetLevelNeedExp(player.expLevel) if needExp <= 0 then return end local barWidth, barHeight = 560, 12 local drawX = canvasPos.x + node.positionInCanvas.x local drawY = canvasPos.y + node.positionInCanvas.y - barHeight - 4 local drawPos = Vector2.new(drawX, drawY) local remainExp = player.remainExp local rate = math.min(1.0, math.max(0.0, remainExp * 1.0 / needExp)) local cutRectBack = Rect.new(0, barHeight, barWidth, barHeight) local cutRectFront = Rect.new(0, 0, barWidth * rate, barHeight) Sprite.draw(self._textureExpBar, drawPos, cutRectBack, Color.White) Sprite.draw(self._textureExpBar, drawPos, cutRectFront, Color.White) end function HudUI:closeWindow() self:destroyHotkeys() HudUI.super.closeWindow(self) s_instance = nil end return HudUI ================================================ FILE: ui/nei/NeiDataBrewing.lua ================================================ local NeiDataBrewing = class("NeiDataBrewing") local UIUtil = require("ui.UIUtil") local UIDefault = require("ui.UIDefault") local Locale = require("languages.Locale") local MAX_ANIMATION_INDEX = 32 local ANIMATION_SPEED = 4 function NeiDataBrewing:__init() self._animationTick = 0 self._animationIndex = 0 end function NeiDataBrewing:getPanelSize() return Size.new(280, 180) end function NeiDataBrewing:getTitle() return "酿造" end function NeiDataBrewing:createUI(panelRoot, recipeID) local offsetX = 120 local offsetY = 10 panelRoot:addChild(UIUtil.createImage("img_tube", offsetX, offsetY + 52, 30, 30, { sprite = { name = "tc:tube" } })) panelRoot:addChild(UIUtil.createImage("img_process", offsetX + 38, offsetY + 12, 24, 80, { sprite = { name = "tc:brewing_process_00", } })) panelRoot:addChild(UIUtil.createImage("img_bubble", offsetX - 48, offsetY + 4, 40, 64, { sprite = { name = "tc:brewing_bubble_00" } })) panelRoot:addChild(UIUtil.createImage("img_fuel", offsetX - 48, offsetY + 70, 40, 12, { sprite = { name = "tc:brewing_fuel_00" } })) -- 0: potion 1: source 2: output 3: fuel panelRoot:addChild(UIUtil.createSlot("slot_potion", offsetX - 82, offsetY + 88, UIDefault.CellSize, UIDefault.CellSize, "tc:glass_bottle"), 0) panelRoot:addChild(UIUtil.createSlot("slot_input", offsetX - 8, offsetY, UIDefault.CellSize, UIDefault.CellSize), 1) panelRoot:addChild(UIUtil.createSlot("slot_output", offsetX + 66, offsetY + 80, UIDefault.CellLargeSize, UIDefault.CellLargeSize, "tc:glass_bottle"), 2) --panelRoot:addChild(UIUtil.createSlot("slot_fuel", -- offsetX - 100, offsetY, UIDefault.CellSize, UIDefault.CellSize, "tc:blaze_powder"), 3) local recipe = RecipeUtils.GetRecipe(recipeID) local time = recipe.exData.time local text = string.format(Locale.TIME_COST, time * 0.02) panelRoot:addChild(UIUtil.createLabel("lb_desc", text, 120, 160, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter )) panelRoot:getChild("img_process"):getPostDrawLayer(0):addListener({ NeiDataBrewing.OnRenderProcessProgress, self }) panelRoot:getChild("img_bubble"):getPostDrawLayer(0):addListener({ NeiDataBrewing.OnRenderBubbleProgress, self }) panelRoot:getChild("img_fuel"):getPostDrawLayer(0):addListener({ NeiDataBrewing.OnRenderFuelProgress, self }) end function NeiDataBrewing:onUpdateTick() self._animationTick = self._animationTick + 1 if self._animationTick > ANIMATION_SPEED then self._animationTick = 0 self._animationIndex = self._animationIndex + 1 if self._animationIndex > MAX_ANIMATION_INDEX then self._animationIndex = 0 end end end --- ---@param node UINode ---@param canvasPos Vector2 function NeiDataBrewing:OnRenderProcessProgress(node, canvasPos) local step = math.ceil(self._animationIndex / MAX_ANIMATION_INDEX * 16) UIUtil.renderProgress("tc:brewing_process_01", node.positionInCanvas + canvasPos, step, 16, 0, 1) end --- ---@param node UINode ---@param canvasPos Vector2 function NeiDataBrewing:OnRenderBubbleProgress(node, canvasPos) local step = math.ceil(self._animationIndex / MAX_ANIMATION_INDEX * 32) UIUtil.renderProgress("tc:brewing_bubble_01", node.positionInCanvas + canvasPos, step, 32, 0, -1) end --- ---@param node UINode ---@param canvasPos Vector2 function NeiDataBrewing:OnRenderFuelProgress(node, canvasPos) local step = math.ceil(self._animationIndex / MAX_ANIMATION_INDEX * 20) UIUtil.renderProgress("tc:brewing_fuel_01", node.positionInCanvas + canvasPos, 20 - step, 20, 0, -1) end return NeiDataBrewing ================================================ FILE: ui/nei/NeiDataCrafting.lua ================================================ local NeiDataCrafting = class("NeiDataCrafting") local UIUtil = require("ui.UIUtil") local UIDefault = require("ui.UIDefault") function NeiDataCrafting:getPanelSize() return Size.new(256, 144) end function NeiDataCrafting:getTitle() return "合成" end function NeiDataCrafting:createUI(panelRoot, recipeID) for i = 0, 8 do panelRoot:addChild(UIUtil.createSlot("slot", (i % 3) * UIDefault.CellOffset, math.floor(i / 3) * UIDefault.CellOffset), i) end panelRoot:addChild(UIUtil.createSlot("slot", 200, 43, UIDefault.CellLargeSize, UIDefault.CellLargeSize), 9) panelRoot:addChild(UIUtil.createImage("img_craft_arrow", 158, 60, 32, 24, { sprite = { name = "tc:arrow3", color = Color.new(100, 100, 100, 188) } })) end return NeiDataCrafting ================================================ FILE: ui/nei/NeiDataProxy.lua ================================================ local NeiDataProxy = class("NeiDataProxy") function NeiDataProxy:__init() self._dataDict = { [Reg.RecipeConfigID("Craft3x")] = require("NeiDataCrafting").new(), [Reg.RecipeConfigID("Smelt")] = require("NeiDataSmelting").new(), [Reg.RecipeConfigID("Repair")] = require("NeiDataRepairing").new(), [Reg.RecipeConfigID("Brew")] = require("NeiDataBrewing").new(), } end function NeiDataProxy:getData(recipeConfigID) return self._dataDict[recipeConfigID] end return NeiDataProxy ================================================ FILE: ui/nei/NeiDataRepairing.lua ================================================ local NeiDataRepairing = class("NeiDataRepairing") local UIUtil = require("ui.UIUtil") local UIDefault = require("ui.UIDefault") function NeiDataRepairing:getPanelSize() return Size.new(320, 60) end function NeiDataRepairing:getTitle() return "修复" end function NeiDataRepairing:createUI(panelRoot, recipeID) local offsetX, offsetY = 0, 0 local recipe = RecipeUtils.GetRecipe(recipeID) local repairPercent = math.ceil(recipe.exData.repairRate * 100) -- 50-52: tool, source, output panelRoot:addChild(UIUtil.createSlot("slot_tool", offsetX + 0, offsetY + 0, UIDefault.CellSize, UIDefault.CellSize, "tc:hammer"), 0) panelRoot:addChild(UIUtil.createSlot("slot_source", offsetX + 120, offsetY + 0, UIDefault.CellSize, UIDefault.CellSize, "tc:ingot_gray"), 1) panelRoot:addChild(UIUtil.createSlot("slot_output", offsetX + 250, offsetY - 5, UIDefault.CellLargeSize, UIDefault.CellLargeSize, "tc:hammer"), 2) panelRoot:addChild(UIUtil.createLabel("lb_exp", string.format("修复率:%d%%", repairPercent), offsetX + 130, offsetY + 54, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter, { color = Color.Yellow } )) panelRoot:addChild(UIUtil.createImage("img_add", offsetX + 68, offsetY + 8, 32, 32, { sprite = { name = "tc:adding", } })) panelRoot:addChild(UIUtil.createImage("img_process", offsetX + 190, offsetY + 8, 40, 32, { sprite = { name = "tc:process_00", } })) end return NeiDataRepairing ================================================ FILE: ui/nei/NeiDataSmelting.lua ================================================ local NeiDataSmelting = class("NeiDataSmelting") local UIUtil = require("ui.UIUtil") local UIDefault = require("ui.UIDefault") local Locale = require("languages.Locale") local MAX_ANIMATION_INDEX = 16 local ANIMATION_SPEED = 8 function NeiDataSmelting:__init() self._animationTick = 0 self._animationIndex = 0 end function NeiDataSmelting:getPanelSize() return Size.new(190, 130) end function NeiDataSmelting:getTitle() return "烧炼" end function NeiDataSmelting:createUI(panelRoot, recipeID) panelRoot:addChild(UIUtil.createSlot("slot", 0, 5), 0) panelRoot:addChild(UIUtil.createSlot("slot", 130, 20, UIDefault.CellLargeSize, UIDefault.CellLargeSize), 1) panelRoot:addChild(UIUtil.createImage("img_cook", 70, 34, 40, 32, { sprite = { name = "tc:process_00" } })) panelRoot:addChild(UIUtil.createImage("img_burn", 8, 68, 30, 30, { sprite = { name = "tc:burn_00" } })) local recipe = RecipeUtils.GetRecipe(recipeID) local time = recipe.exData.time local text = string.format(Locale.BURN_TIME_COST, time * 0.02) panelRoot:addChild(UIUtil.createLabel("lb_desc", text, 80, 120, 32, 32, TextAlignment.HCenter, TextAlignment.VCenter )) panelRoot:getChild("img_cook"):getPostDrawLayer(0):addListener({ NeiDataSmelting.OnRenderCookProgress, self }) panelRoot:getChild("img_burn"):getPostDrawLayer(0):addListener({ NeiDataSmelting.OnRenderBurnProgress, self }) end function NeiDataSmelting:onUpdateTick() self._animationTick = self._animationTick + 1 if self._animationTick > ANIMATION_SPEED then self._animationTick = 0 self._animationIndex = self._animationIndex + 1 if self._animationIndex > MAX_ANIMATION_INDEX then self._animationIndex = 0 end end end ---OnRenderCookProgress ---@param node UINode ---@param canvasPos Vector2 function NeiDataSmelting:OnRenderCookProgress(node, canvasPos) UIUtil.renderProgress("tc:process_01", node.positionInCanvas + canvasPos, self._animationIndex, 16, 1, 0) end --- ---@param node UINode ---@param canvasPos Vector2 function NeiDataSmelting:OnRenderBurnProgress(node, canvasPos) UIUtil.renderProgress("tc:burn_01", node.positionInCanvas + canvasPos, 16 - self._animationIndex, 16, 0, -1) end return NeiDataSmelting ================================================ FILE: ui/nei/NeiUI.lua ================================================ ---@class TC.NeiUI:TC.UIWindow local NeiUI = class("NeiUI", require("ui.UIWindow")) local UIUtil = require("ui.UIUtil") local UIDefault = require("ui.UIDefault") local SettingsData = require("settings.SettingsData") local RawHotkeyUIHelper = require("ui.RawHotkeyUIHelper") local Locale = require("languages.Locale") local ORE_DICTIONARY_FLUSH_TICKS = 40 local PREVIEW_INPUT_CNT_PRE_LINE = 3 local PREVIEW_OUTPUT_CNT_PRE_LINE = 1 ---@class TC.NeiHistoryEntity local NeiHistoryEntity = class("NeiHistoryEntity") ---__init ---@param itemStack ItemStack ---@param fromOutput boolean ---@param tabIndex int ---@param recipeIndexInTab int function NeiHistoryEntity:__init(itemStack, fromOutput, tabIndex, recipeIndexInTab) self.itemStack = itemStack self.fromOutput = fromOutput self.tabIndex = tabIndex self.recipeIndexInTab = recipeIndexInTab end local NeiHistory = class("NeiHistory") local MAX_HISTORY_SIZE = 100 function NeiHistory:__init() self._entities = {} ---@type TC.NeiHistoryEntity[] end ---push ---@param entity TC.NeiHistoryEntity function NeiHistory:push(entity) if #self._entities >= MAX_HISTORY_SIZE then table.remove(self._entities, 1) end table.insert(self._entities, entity) end function NeiHistory:pop() if #self._entities > 0 then return table.remove(self._entities, #self._entities) end return nil end ---@class TC.SearchRequest local SearchRequest = class("SearchRequest") ---__init ---@param itemStack ItemStack ---@param itemID int ---@param fromOutput boolean function SearchRequest:__init(itemStack, itemID, fromOutput) self.itemStack = itemStack self.itemID = itemID self.fromOutput = fromOutput self._relateOreDictionaryIDs = ItemRegistry.GetItemByID(itemID).oreDictionaryIDs end ---isSameRequest ---@param itemStack ItemStack ---@param fromOutput boolean function SearchRequest:isSameRequest(itemStack, fromOutput) if fromOutput == self.fromOutput then if itemStack:GetItem().id == self.itemID then return true end end return false end function SearchRequest:_fixInputTypeAndID(type, id) if not self.fromOutput and type == RecipeInputSlotType.OreDictionary then for _, oreDictionaryID in each(self._relateOreDictionaryIDs) do if id == oreDictionaryID then return RecipeInputSlotType.Item, self.itemID end end end return type, id end ---@class TC.PreviewRecipeData local PreviewRecipeData = class("PreviewRecipeData") ---__init ---@param validInputCache table ---@param validOutputSlots Slot[] function PreviewRecipeData:__init(validInputCache, validOutputSlots) self.validInputCache = validInputCache self.validOutputSlots = validOutputSlots end ---@class TC.OreDictionaryRecord local OreDictionaryRecord = class("OreDictionaryRecord") function OreDictionaryRecord:__init(oreDictionaryID, stackSize, slotIndex) self.oreDictionaryID = oreDictionaryID self.stackSize = stackSize self.slotIndex = slotIndex self.cursor = 1 end function OreDictionaryRecord:getCurrentItemID() local ids = ItemUtils.GetOreDictionaryItemIDs(self.oreDictionaryID) return ids[self.cursor] end function OreDictionaryRecord:nextCursor() local ids = ItemUtils.GetOreDictionaryItemIDs(self.oreDictionaryID) if self.cursor >= ids.count then self.cursor = 1 else self.cursor = self.cursor + 1 end end function NeiUI:__init() NeiUI.super.__init(self, require("ui.UIDesign").getNeiUI(), require("ui.UIDefault").GROUP_GAME_WINDOW) self._searchListInventory = Inventory.new(0) self._searchPanelCells = self.root:getChild("panel_search.panel_cells") self._searchBaseCell = self.root:getChild("panel_search.panel_cell") self._lbSearchListPage = UIText.cast(self.root:getChild("panel_search.lb_page")) self._baseInfoPanel = UIPanel.cast(self.root:getChild("layer")) self._tabsNode = UIPanel.cast(self._baseInfoPanel:getChild("panel_tabs")) self._baseTabNode = UIPanel.cast(self._baseInfoPanel:getChild("panel_tab")) self._previewPanelList = self._baseInfoPanel:getChild("panel_list") self._positionPanelDetail = UIPanel.cast(self._baseInfoPanel:getChild("panel_position_detail")) self._lbInfoTitle = UIText.cast(self._baseInfoPanel:getChild("lb_recipe_name")) self._panelDetail = UIPanel.cast(self._positionPanelDetail:getChild("panel_detail")) self._btnSearchMode = UIButton.cast(self.root:getChild("btn_search_mode")) self._btnBackHistory = UIButton.cast(self.root:getChild("btn_back_history")) self._dataProxy = require("NeiDataProxy").new() self._isCurrentSearchFromOutput = true self._oreDictionaryFlushTicks = ORE_DICTIONARY_FLUSH_TICKS self._isDisplayAll = true self._currentItemRootGroupID = 1 self._displayLines = 1 self._displayCntPreLine = 1 self._displayCellCntPrePage = 1 self._currentPageIndex = 0 self._totalPageCnt = 1 self._searchTotalDisplayCnt = 0 self._history = NeiHistory.new() ---@type TC.SearchRequest self._currentSearchRequest = nil ---@type ItemStack self._nextSearchRequestStack = nil self._currentSearchData = {} self._tabRecipeConfigs = {} self._currentTabIndex = 0 self._currentRecipeIndexInTab = 0 self._tabCount = 0 self._tabInventory = Inventory.new(0) self._detailData = nil self._previewInventory = Inventory.new(0) self._detailInventory = Inventory.new(0) self._previewOreDictionaryRecords = {} ---@type TC.OreDictionaryRecord[] self._detailOreDictionaryRecords = {} ---@type TC.OreDictionaryRecord[] ---@type UINode[] self._previewNodes = {} self._hkHelper = RawHotkeyUIHelper.new(self) self:_initContent() end function NeiUI:_initContent() self._baseInfoPanel.visible = false self._baseTabNode.visible = false self._searchBaseCell.visible = false self.root:addTouchUpListener({ function(self) self:closeWindow() end, self }) self._btnSearchMode.visible = SettingsData.isMobileOperation self._btnSearchMode:addTouchUpListener({ NeiUI._onSearchModeBtnClicked, self }) self._btnBackHistory:addTouchUpListener({ NeiUI._onBackHistoryClicked, self }) self:initUpdateFunc({ NeiUI._onUpdateTick, self }) self.root:getChild("panel_search.btn_next"):addTouchUpListener({ NeiUI._onSearchListNextPageClicked, self }) self.root:getChild("panel_search.btn_prev"):addTouchUpListener({ NeiUI._onSearchListPrevPageClicked, self }) self:_refreshSearchListData() end function NeiUI:_onUpdateTick() if self._oreDictionaryFlushTicks > 0 then self._oreDictionaryFlushTicks = self._oreDictionaryFlushTicks - 1 end if self._oreDictionaryFlushTicks == 0 then self._oreDictionaryFlushTicks = ORE_DICTIONARY_FLUSH_TICKS self:flushOreDictionaryItems(self._previewOreDictionaryRecords, self._previewInventory) self:flushOreDictionaryItems(self._detailOreDictionaryRecords, self._detailInventory) end if self._detailData ~= nil and self._detailData.onUpdateTick ~= nil then self._detailData:onUpdateTick() end if self._nextSearchRequestStack ~= nil then local stack = self._nextSearchRequestStack self._nextSearchRequestStack = nil self:_checkPCSearchOperation() self:_trySearch(stack, self._isCurrentSearchFromOutput, true) end end function NeiUI:_onBackHistoryClicked() local historyEntity = self._history:pop() if historyEntity == nil then return end self:_trySearch(historyEntity.itemStack, historyEntity.fromOutput, false) self:_onInfoTabClicked(historyEntity.tabIndex) self:_onPreviewItemClicked(historyEntity.recipeIndexInTab) self.manager:playClickSound() end function NeiUI:flushOreDictionaryItems(records, inventory) for _, record in ipairs(records) do record:nextCursor() local slot = inventory:GetSlot(record.slotIndex) local itemID = record:getCurrentItemID() local stack = ItemStack.new(ItemRegistry.GetItemByID(itemID), record.stackSize) slot:PushStack(stack) end end ---_initInputSlot ---@param node UINode ---@param records TC.OreDictionaryRecord[] ---@param inventory Inventory ---@param slotIndex int ---@param type int ---@param id int ---@param stackSize int function NeiUI:_initInputSlot(node, records, inventory, slotIndex, type, id, stackSize) local slot = inventory:GetSlot(slotIndex) if type == RecipeInputSlotType.Empty then slot:ClearStack() else local itemID if type == RecipeInputSlotType.OreDictionary then local record = OreDictionaryRecord.new(id, stackSize, slotIndex) table.insert(records, record) itemID = record:getCurrentItemID() else itemID = id end local stack = ItemStack.new(ItemRegistry.GetItemByID(itemID), stackSize) slot:PushStack(stack) end UIUtil.hookSlotView(node, slot, true) node:addTouchUpListener({ NeiUI._onDetailCellClicked, self, slot }) end ---_initOutputSlot ---@param node UINode ---@param slot Slot function NeiUI:_initOutputSlot(node, slot) UIUtil.hookSlotView(node, slot, true) node:addTouchUpListener({ NeiUI._onDetailCellClicked, self, slot }) end ---_onDetailCellClicked ---@param slot Slot function NeiUI:_onDetailCellClicked(slot) if slot.hasStack then self.manager:playClickSound() self._nextSearchRequestStack = slot:GetStack() end end function NeiUI:_onSearchModeBtnClicked() self.manager:playClickSound() self._isCurrentSearchFromOutput = not self._isCurrentSearchFromOutput local name if self._isCurrentSearchFromOutput then name = Locale.SEARCH_FROM_OUTPUT else name = Locale.SEARCH_FROM_INPUT end UIText.cast(self._btnSearchMode:getChild("lb_caption")).text = name end function NeiUI:_checkPCSearchOperation() if not SettingsData.isMobileOperation then self._isCurrentSearchFromOutput = not Input.mouse.isRightButtonInstantUp end end function NeiUI:_onSearchListNextPageClicked() self.manager:playClickSound() self._currentPageIndex = self._currentPageIndex + 1 if self._currentPageIndex >= self._totalPageCnt then self._currentPageIndex = 0 end self:_resetSearchListUI() end function NeiUI:_onSearchListPrevPageClicked() self.manager:playClickSound() if self._currentPageIndex == 0 then self._currentPageIndex = self._totalPageCnt - 1 else self._currentPageIndex = self._currentPageIndex - 1 end self:_resetSearchListUI() end function NeiUI:_refreshSearchListData() local width, height = self._searchPanelCells.width, self._searchPanelCells.height local cellWidth, cellHeight = self._searchBaseCell.width, self._searchBaseCell.height self._displayCntPreLine = math.max(1, math.floor(width / cellWidth)) self._displayLines = math.max(1, math.floor(height / cellHeight)) self._displayCellCntPrePage = self._displayLines * self._displayCntPreLine local groupIDs = ItemUtils.GetGroupIDsFromRootID(self._currentItemRootGroupID) self._searchTotalDisplayCnt = 0 for _, groupID in each(groupIDs) do self._searchTotalDisplayCnt = self._searchTotalDisplayCnt + ItemUtils.GetGroupItemIDs(groupID).count end self._searchListInventory:SetSlotCount(self._searchTotalDisplayCnt) local index = 0 for _, groupID in each(groupIDs) do local itemIDs = ItemUtils.GetGroupItemIDs(groupID) for _, itemID in each(itemIDs) do local item = ItemRegistry.GetItemByID(itemID) self._searchListInventory:GetSlot(index):PushStack(ItemStack.new(item)) index = index + 1 end end self._totalPageCnt = math.ceil(self._searchTotalDisplayCnt / self._displayCellCntPrePage) self._currentPageIndex = 0 print("Total:", self._searchTotalDisplayCnt, "Pages:", self._totalPageCnt) self:_resetSearchListUI() end function NeiUI:_resetSearchListUI() local cellWidth, cellHeight = self._searchBaseCell.width, self._searchBaseCell.height self._searchPanelCells:removeAllChildren() local itemSlotIndexStart = self._currentPageIndex * self._displayCellCntPrePage for index = 0, self._displayCellCntPrePage - 1 do local slotIndex = itemSlotIndexStart + index if slotIndex >= self._searchTotalDisplayCnt then break end local slot = self._searchListInventory:GetSlot(slotIndex) node = self._searchBaseCell:clone() node.name = string.format("cell_%d", index) self._searchPanelCells:addChild(node, index) node.visible = true local xi = index % self._displayCntPreLine local yi = math.floor(index / self._displayCntPreLine) node:setPosition(xi * cellWidth, yi * cellHeight) UIUtil.hookSlotView(node, slot) node:addTouchUpListener({ NeiUI._onSearchCellClicked, self, slotIndex }) end self._lbSearchListPage.text = string.format("%d/%d", self._currentPageIndex + 1, self._totalPageCnt) end function NeiUI:_onSearchCellClicked(slotIndex) if slotIndex >= self._searchListInventory.slotCount then return end local slot = self._searchListInventory:GetSlot(slotIndex) if not slot.hasStack then return end local stack = slot:GetStack() self:_checkPCSearchOperation() self:_trySearch(stack, self._isCurrentSearchFromOutput, true) self.manager:playClickSound() end function NeiUI:_resetInfoUI() if next(self._currentSearchData) == nil then self._baseInfoPanel.visible = false return end self._baseInfoPanel.visible = true self._tabRecipeConfigs = {} self._tabsNode:removeAllChildren() self._currentTabIndex = 0 local tabIndex = 0 for configID, _ in pairs(self._currentSearchData) do local tabNode = self._baseTabNode:clone() self._tabRecipeConfigs[tabIndex + 1] = configID self._tabsNode:addChild(tabNode, tabIndex) tabNode:setPosition(tabIndex * tabNode.width, 0) tabNode.visible = true tabNode:addTouchUpListener({ NeiUI._onInfoTabClicked, self, tabIndex }) tabIndex = tabIndex + 1 end self._tabCount = tabIndex self._tabInventory:SetSlotCount(self._tabCount) for i = 0, self._tabCount - 1 do local configID = self._tabRecipeConfigs[i + 1] local config = RecipeUtils.GetConfig(configID) if config.iconItemID > 0 then local tabNode = self._tabsNode:getChildByTag(i) local item = ItemRegistry.GetItemByID(config.iconItemID) local slot = self._tabInventory:GetSlot(i) slot:PushStack(ItemStack.new(item)) UIUtil.hookSlotView(tabNode, slot, false) end end self:_resetTabState() self:_resetInfoPanel() end function NeiUI:_onInfoTabClicked(tabIndex) if tabIndex == self._currentTabIndex then return end self.manager:playClickSound() self._currentTabIndex = tabIndex self:_resetTabState() self:_resetInfoPanel() end function NeiUI:_resetTabState() local UISpritePool = require("ui.UISpritePool") for i = 0, self._tabCount - 1 do local tabNode = UIPanel.cast(self._tabsNode:getChildByTag(i)) local spriteName = "tc:tab" if i == self._currentTabIndex then spriteName = "tc:tab_clicked" end tabNode.sprite = UISpritePool.getInstance():get(spriteName) end end function NeiUI:_resetInfoPanel() local configID = self._tabRecipeConfigs[self._currentTabIndex + 1] local recipeIDs = self._currentSearchData[configID] local recipeCount = #recipeIDs ---@type TC.PreviewRecipeData[] local previews = {} for _, recipeID in ipairs(recipeIDs) do table.insert(previews, self:_getPreviewRecipeData(recipeID)) end local totalSlotCount = 0 for _, preview in ipairs(previews) do totalSlotCount = totalSlotCount + #preview.validInputCache end self._previewInventory:SetSlotCount(totalSlotCount) self._previewOreDictionaryRecords = {} self._currentRecipeIndexInTab = 0 self._previewNodes = {} ---@param preview TC.PreviewRecipeData local function _getPreviewLineData(preview) local inputLines = math.ceil(#preview.validInputCache / PREVIEW_INPUT_CNT_PRE_LINE) local outputLines = math.ceil(#preview.validOutputSlots / PREVIEW_OUTPUT_CNT_PRE_LINE) local maxLines = math.max(inputLines, outputLines) return inputLines, outputLines, maxLines end local slotCursor = 0 local proxy = { _getTableElementCount = function() return recipeCount end, _getTableElementSize = function(_, index) local _, _, maxLines = _getPreviewLineData(previews[index]) local height = 16 + maxLines * UIDefault.CellSize return Size.new(self._previewPanelList.width, height) end, _setTableElement = function(_, node, index) local preview = previews[index] local inputLines, outputLines, maxLines = _getPreviewLineData(preview) local inputX = 8 local outputX = inputX + (PREVIEW_INPUT_CNT_PRE_LINE + 1) * UIDefault.CellSize local inputY = 8 + (maxLines - inputLines) * UIDefault.CellSize / 2 local outputY = 8 + (maxLines - outputLines) * UIDefault.CellSize / 2 ---@type UINode local baseCellNode = node:getChild("panel_preview_cell") baseCellNode.visible = false ---@type UINode local imgArrow = node:getChild("img_arrow") imgArrow:setPosition( inputX + PREVIEW_INPUT_CNT_PRE_LINE * UIDefault.CellSize + (UIDefault.CellSize - 32) / 2, (node.height - 24) / 2 ) for i, cache in ipairs(preview.validInputCache) do local cellNode = baseCellNode:clone() cellNode.visible = true node:addChild(cellNode) cellNode:setPosition( inputX + ((i - 1) % PREVIEW_INPUT_CNT_PRE_LINE) * UIDefault.CellSize, inputY + math.floor((i - 1) / PREVIEW_INPUT_CNT_PRE_LINE) * UIDefault.CellSize ) cellNode.touchable = false local type, id, stackSize = cache[1], cache[2], cache[3] self:_initInputSlot(cellNode, self._previewOreDictionaryRecords, self._previewInventory, slotCursor, type, id, stackSize) slotCursor = slotCursor + 1 end for i, e in ipairs(preview.validOutputSlots) do local cellNode = baseCellNode:clone() cellNode.visible = true node:addChild(cellNode) cellNode:setPosition( outputX + ((i - 1) % PREVIEW_OUTPUT_CNT_PRE_LINE) * UIDefault.CellSize, outputY + math.floor((i - 1) / PREVIEW_OUTPUT_CNT_PRE_LINE) * UIDefault.CellSize ) cellNode.touchable = false self:_initOutputSlot(cellNode, e) end node:addTouchUpListener({ NeiUI._onPreviewItemClicked, self, index }) table.insert(self._previewNodes, node) end } UIUtil.setTable(self._previewPanelList, proxy, true, 1) self:_setDetailPanel(1) end function NeiUI:_resetPreviewBg(index) local UISpritePool = require("ui.UISpritePool") for i, node in ipairs(self._previewNodes) do local panel = UIPanel.cast(node) local spriteName if i == index then spriteName = "tc:base_list_cell_highlight" else spriteName = "tc:base_list_cell" end panel.sprite = UISpritePool.getInstance():get(spriteName) end end function NeiUI:_onPreviewItemClicked(index) if index == self._currentRecipeIndexInTab then return end self.manager:playClickSound() self:_setDetailPanel(index) end function NeiUI:_setDetailPanel(index) if index == self._currentRecipeIndexInTab then return end local configID = self._tabRecipeConfigs[self._currentTabIndex + 1] local recipeIDs = self._currentSearchData[configID] if index > #recipeIDs then return end self:_resetPreviewBg(index) self._currentRecipeIndexInTab = index local recipeID = recipeIDs[index] local config = RecipeUtils.GetConfig(configID) local recipe = RecipeUtils.GetRecipe(recipeID) local data = self._dataProxy:getData(configID) self._detailData = data self._panelDetail:removeAllChildren() self._detailOreDictionaryRecords = {} if data.getPanelSize == nil then self._panelDetail:setSize(self._positionPanelDetail.width, self._positionPanelDetail.height) else self._panelDetail.size = data:getPanelSize() end self._panelDetail:applyMargin(false) if data.getTitle == nil then self._lbInfoTitle.text = "" else self._lbInfoTitle.text = data:getTitle() end data:createUI(self._panelDetail, recipeID) local inputs = recipe.inputs local outputs = recipe.outputs self._detailInventory:SetSlotCount(config.inputCount + config.outputCount) local slotIndex = 0 for i = 0, config.inputCount - 1 do local node = self._panelDetail:getChildByTag(i) if node:valid() then local e = inputs[i + 1] local type, id = self._currentSearchRequest:_fixInputTypeAndID(e.type, e.id) self:_initInputSlot(node, self._detailOreDictionaryRecords, self._detailInventory, slotIndex, type, id, e.stackSize) end slotIndex = slotIndex + 1 end for i = 0, config.outputCount - 1 do local node = self._panelDetail:getChildByTag(config.inputCount + i) if node:valid() then local e = outputs[i + 1] self:_initOutputSlot(node, e) end slotIndex = slotIndex + 1 end end function NeiUI:_getPreviewRecipeData(recipeID) local recipe = RecipeUtils.GetRecipe(recipeID) local inputCache = {} local outputValidCells = {} ---@param e RecipeInputSlot for _, e in each(recipe.inputs) do if e.type ~= RecipeInputSlotType.Empty then local type, id = self._currentSearchRequest:_fixInputTypeAndID(e.type, e.id) local isExistInCache = false for _, c in ipairs(inputCache) do if c[1] == type and c[2] == id then c[3] = c[3] + e.stackSize isExistInCache = true break end end if not isExistInCache then table.insert(inputCache, { type, id, e.stackSize }) end end end ---@param e Slot for _, e in each(recipe.outputs) do if e.hasStack then table.insert(outputValidCells, e) end end return PreviewRecipeData.new(inputCache, outputValidCells) end function NeiUI:trySearch(itemStack, fromOutput) self:_trySearch(itemStack, fromOutput, true) end ---_trySearch ---@param itemStack ItemStack ---@param fromOutput boolean ---@param saveHistory boolean function NeiUI:_trySearch(itemStack, fromOutput, saveHistory) if self._currentSearchRequest then if itemStack:GetItem().id == self._currentSearchRequest.itemID and fromOutput == self._currentSearchRequest.fromOutput then return end end local data = NeiUI.doSearch(itemStack, fromOutput) if next(data) == nil then return end if saveHistory and self._currentSearchRequest then local historyEntity = NeiHistoryEntity.new( self._currentSearchRequest.itemStack, self._currentSearchRequest.fromOutput, self._currentTabIndex, self._currentRecipeIndexInTab ) self._history:push(historyEntity) end self._currentSearchRequest = SearchRequest.new(itemStack, itemStack:GetItem().id, fromOutput) self._currentSearchData = data self:_resetInfoUI() end function NeiUI.doSearch(itemStack, fromOutput) local res = {} local maxConfigID = Reg.MaxRecipeConfigID() for configID = 1, maxConfigID do local recipeIDs = NeiUI.doSearchByRecipeConfig(configID, itemStack, fromOutput) if #recipeIDs > 0 then res[configID] = recipeIDs end end return res end function NeiUI.doSearchByRecipeConfig(recipeConfigID, itemStack, fromOutput) if fromOutput then return RecipeUtils.SearchRecipeHasOutputItem(recipeConfigID, itemStack, 0) else return RecipeUtils.SearchRecipeHasInputItem(recipeConfigID, itemStack) end end function NeiUI:onWindowResize() NeiUI.super.onWindowResize(self) self:_refreshSearchListData() end function NeiUI:closeWindow() self._hkHelper:destroy() NeiUI.super.closeWindow(self) end return NeiUI ================================================ FILE: ui/recipe_book/RecipeBookServer.lua ================================================ ---@class TC.RecipeBookServer local RecipeBookServer = class("RecipeBookServer") ---@param player Player ---@param inputInventory Inventory ---@param inputInventorySlotStartIndex int ---@param inputInventorySlotSize int function RecipeBookServer:__init(recipeConfigID, player, inputInventory, inputInventorySlotStartIndex, inputInventorySlotSize) self._recipeConfigID = recipeConfigID self._playerIndex = player.entityIndex self._inputInventory = inputInventory self._inputInventorySlotStartIndex = inputInventorySlotStartIndex self._inputInventorySlotSize = inputInventorySlotSize end function RecipeBookServer:FlushValidRecipe(recipeID) if recipeID == nil then return end local player = PlayerUtils.Get(self._playerIndex) if player == nil then return end print("Valid:", recipeID) if recipeID <= 0 or recipeID > Reg.MaxRecipeID() then return end -- all input slots are empty, move directly if self:_IsInputSlotsAllEmpty() then self:_InitSendRecipeInputItems(player, recipeID) else -- has input slots local lastRecipeID = RecipeUtils.SearchRecipe(self._recipeConfigID, self._inputInventory, self._inputInventorySlotStartIndex, self._inputInventorySlotSize) if lastRecipeID ~= recipeID then self:_SendBackAllInputItems(player) self:_InitSendRecipeInputItems(player, recipeID) else self:_SendSameInputItems(player) end end end function RecipeBookServer:_SendSameInputItems(player) local layouts = self:_GetBackpackLayouts(player) if not self:_CanPeekSameInputs(layouts) then return end for i = 1, self._inputInventorySlotSize do self:_TryPeekAndAdd(i, player) end end function RecipeBookServer:_CanPeekSameInputs(layouts) local cache = {} for i = self._inputInventorySlotStartIndex, self._inputInventorySlotStartIndex + self._inputInventorySlotSize - 1 do local slot = self._inputInventory:GetSlot(i) if slot.hasStack then local stack = slot:GetStack() local item = stack:GetItem() local size = stack.stackSize if size >= item.maxStackSize then return false end local id = item.id if cache[id] == nil then cache[id] = 1 else cache[id] = cache[id] + 1 end end end for id, size in pairs(cache) do if layouts[id] == nil then return false end local sizeOwned = layouts[id][1] if sizeOwned < size then return false end end return true end ---@param player Player ---@param recipeID int function RecipeBookServer:_InitSendRecipeInputItems(player, recipeID) local recipe = RecipeUtils.GetRecipe(recipeID) ---@param ie RecipeInputSlot for i, ie in each(recipe.inputs) do if i <= self._inputInventorySlotSize then if ie.type == RecipeInputSlotType.Item then self:_TryPeekAndPushStack(i, player,{ ie.id }, ie.stackSize) end end end ---@param ie RecipeInputSlot for i, ie in each(recipe.inputs) do if i <= self._inputInventorySlotSize then if ie.type == RecipeInputSlotType.OreDictionary then local ids = ItemUtils.GetOreDictionaryItemIDs(ie.id) local peekItemIDs = {} for _, id in each(ids) do table.insert(peekItemIDs, id) end self:_TryPeekAndPushStack(i, player, peekItemIDs, ie.stackSize) end end end end ---_SendBackAllInputItems ---@param player Player function RecipeBookServer:_SendBackAllInputItems(player) local inventory = player.backpackInventory for i = self._inputInventorySlotStartIndex, self._inputInventorySlotStartIndex + self._inputInventorySlotSize - 1 do local slot = self._inputInventory:GetSlot(i) if slot.hasStack then local stack = slot:GetStack() slot:ClearStack() local remain = inventory:AddItemStack(stack) if remain:Valid() then player:DropItem(remain) end end end end function RecipeBookServer:_TryPeekAndPushStack(i, player, peekItemIDs, stackSize) local layouts = self:_GetBackpackLayouts(player) --print(layouts) local stack = self:_PeekStackFromBackpackLayouts(layouts, peekItemIDs, stackSize) if stack ~= nil then local slot = self._inputInventory:GetSlot(self._inputInventorySlotStartIndex + i - 1) slot:PushStack(stack) end end function RecipeBookServer:_TryPeekAndAdd(i, player) local layouts = self:_GetBackpackLayouts(player) local slot = self._inputInventory:GetSlot(self._inputInventorySlotStartIndex + i - 1) if slot.hasStack then local originalStack = slot:GetStack() local stack = self:_PeekStackFromBackpackLayouts(layouts, { originalStack:GetItem().id }, 1) if stack ~= nil then originalStack:SetStackSize(originalStack.stackSize + 1) end end end -- key: item id, value: { total size, list of {slot, count}} ---@param player Player function RecipeBookServer:_GetBackpackLayouts(player) local res = {} local inventory = player.backpackInventory for i = 0, 49 do local slot = inventory:GetSlot(i) if slot.hasStack then local stack = slot:GetStack() local itemID = stack:GetItem().id local info = { slot, stack.stackSize } if res[itemID] == nil then res[itemID] = { stack.stackSize, { info } } else local data = res[itemID] data[1] = data[1] + stack.stackSize table.insert(data[2], info) end end end return res end function RecipeBookServer:_PeekStackFromBackpackLayouts(layouts, peekItemIDs, peekCount) assert(#peekItemIDs > 0 and peekCount > 0) for i, itemID in ipairs(peekItemIDs) do local data = layouts[itemID] if data ~= nil then if data[1] >= peekCount then data[1] = data[1] - peekCount local slots = data[2] local remainPeekCount = peekCount local resStack for j = #slots, 1, -1 do local info = slots[j] local slot = info[1] ---@type Slot local slotSize = info[2] if resStack == nil then resStack = slot:GetStack():Clone(peekCount) end if slotSize > remainPeekCount then slot:DecrStackSize(remainPeekCount) remainPeekCount = 0 else slot:ClearStack() remainPeekCount = remainPeekCount - slotSize end if remainPeekCount == 0 then return resStack end end end end end return nil end function RecipeBookServer:_IsInputSlotsAllEmpty() for i = self._inputInventorySlotStartIndex, self._inputInventorySlotStartIndex + self._inputInventorySlotSize - 1 do local slot = self._inputInventory:GetSlot(i) if slot.hasStack then return false end end return true end return RecipeBookServer ================================================ FILE: ui/recipe_book/RecipeBookUI.lua ================================================ ---@class TC.RecipeBookUI:TC.UIWindow local RecipeBookUI = class("RecipeBookUI", require("ui.UIWindow")) local UIUtil = require("ui.UIUtil") local UIDefault = require("ui.UIDefault") ---__init ---@param recipeConfigID int ---@param attachFrameworkNode UINode ---@param showing boolean ---@param listenedSlots Slot[] ---@param onClickedCallback table ---@param searchMask string function RecipeBookUI:__init(recipeConfigID, attachFrameworkNode, showing, listenedSlots, onClickedCallback, searchMask) RecipeBookUI.super.__init(self, require("ui.UIDesign").getRecipeBookUI()) self.DISPLAY_CNT_PRE_LINE = 5 self._recipeConfigID = recipeConfigID self._rootLayer = self.root self._panelList = self._rootLayer:getChild("panel_list") self._itemOffsetSize = Size.new(UIDefault.CellHugeOffset, UIDefault.CellHugeOffset) self.uiSize = self._rootLayer.size self._itemIDExistDict = {} self._recipeShowInventory = Inventory.new(0) self._onRecipeShowChangedListener = {} self._recipeCacheItemData = {} self._validItemCount = 0 self._invalidItemCount = 0 self._totalItemCount = 0 self._attachFrameworkNode = attachFrameworkNode self._listenedSlots = listenedSlots self._onClickedCallback = onClickedCallback self._searchMask = searchMask self.showing = showing self:_initContent() end function RecipeBookUI:_initContent() local player = PlayerUtils.GetCurrentClientPlayer() require("player.GPlayer").GetInstance(player).recipeBookHookUI = self self:RefreshDisplayState() end function RecipeBookUI:SetDisplayState(showing) self.showing = showing self:RefreshDisplayState() end function RecipeBookUI:RefreshDisplayState() self._rootLayer.visible = self.showing if self.showing then local OFFSET = 8 local totalWidth = self._attachFrameworkNode.width + self.uiSize.width + OFFSET self._rootLayer.positionX = GameWindow.displayResolution.width / 2 - totalWidth / 2 self._attachFrameworkNode.positionX = self._rootLayer.positionX + self.uiSize.width + OFFSET self:_refreshData() self:_resetTable() else self._attachFrameworkNode.positionX = GameWindow.displayResolution.width / 2 - self._attachFrameworkNode.width / 2 end end function RecipeBookUI:SetOnRecipeChangedListener(callback, caller) self._onRecipeShowChangedListener = { callback, caller } end function RecipeBookUI:_resetTable() UIUtil.setTable(self._panelList, self, true, self.DISPLAY_CNT_PRE_LINE) end function RecipeBookUI:_getTableElementCount() return self._recipeShowInventory.slotCount end function RecipeBookUI:_getTableElementPositionOffset() return self._itemOffsetSize end ---_setTableElement ---@param node UINode ---@param index number function RecipeBookUI:_setTableElement(node, index) node.tag = index if index <= self._recipeShowInventory.slotCount then local slot = self._recipeShowInventory:GetSlot(index - 1) if slot.hasStack then local itemID = slot:GetStack():GetItem().id local data = self._recipeCacheItemData[itemID] local validRecipeID = 0 if data ~= nil and #data.validRecipeIDs > 0 then validRecipeID = data.validRecipeIDs[1] end UIUtil.setSlotStyle(node, validRecipeID > 0 and 4 or 3) UIUtil.hookSlotView(node, slot) if validRecipeID > 0 then node:addTouchUpListener({ RecipeBookUI._OnValidRecipeClicked, self, validRecipeID }) else node:addTouchUpListener({ RecipeBookUI._OnInvalidRecipeClicked, self, slot }) end end end end function RecipeBookUI:_OnValidRecipeClicked(recipeID) self.manager:playClickSound() print("Valid:", recipeID) if self._onClickedCallback ~= nil and #self._onClickedCallback == 2 then local func = self._onClickedCallback[1] local obj = self._onClickedCallback[2] func(obj, recipeID) end end ---_OnInvalidRecipeClicked ---@param slot Slot function RecipeBookUI:_OnInvalidRecipeClicked(slot) self.manager:playClickSound() if slot.hasStack then local stack = slot:GetStack() local nei = require("ui.nei.NeiUI").new() nei:trySearch(stack, true) end end function RecipeBookUI:OnUpdate() --print("BackpackUI:OnUpdate!!") end function RecipeBookUI:OnClose() require("player.GPlayer").GetInstance().recipeBookHookUI = nil self.ui:closeWindow() end function RecipeBookUI:_refreshData() local tempItemIDAndSizes = {} ---@param slot Slot for _, slot in ipairs(self._listenedSlots) do if slot.hasStack then local itemID = slot:GetStack():GetItem().id if tempItemIDAndSizes[itemID] == nil then tempItemIDAndSizes[itemID] = slot:GetStack().stackSize else tempItemIDAndSizes[itemID] = tempItemIDAndSizes[itemID] + slot:GetStack().stackSize end end end local needToSearch = false local tempCount = 0 local oldCount = 0 for _, _ in pairs(tempItemIDAndSizes) do tempCount = tempCount + 1 end for _, _ in pairs(self._itemIDExistDict) do oldCount = oldCount + 1 end if tempCount ~= oldCount then needToSearch = true else for id, size in pairs(tempItemIDAndSizes) do if not self._itemIDExistDict[id] then needToSearch = true break elseif self._itemIDExistDict[id] ~= size then needToSearch = true break end end end if needToSearch then self._validItemCount = 0 self._invalidItemCount = 0 self._totalItemCount = 0 self._recipeCacheItemData = {} self._itemIDExistDict = tempItemIDAndSizes local allRecipeIDExists = {} -- search all recipe by every slot local configID = self._recipeConfigID ---@param slot Slot for _, slot in ipairs(self._listenedSlots) do if slot.hasStack then local results = RecipeUtils.SearchRecipeHasInputItem(configID, slot:GetStack()) for _, recipeID in pairs(results) do local recipe = RecipeUtils.GetRecipe(recipeID) if recipe:IsValidByMask(self._searchMask) then allRecipeIDExists[recipeID] = true end end end end local validRecipeIDs = {} local invalidRecipeIDs = {} for recipeID, _ in pairs(allRecipeIDExists) do local temps = clone(self._itemIDExistDict) local recipe = RecipeUtils.GetRecipe(recipeID) local valid = true -- first, check the fix item input ---@param ie RecipeInputSlot for _, ie in each(recipe.inputs) do if ie.type == RecipeInputSlotType.Item then local itemID = ie.itemStack:GetItem().id local size = ie.itemStack.stackSize local tempSize = temps[itemID] if tempSize == nil then valid = false break elseif tempSize > size then temps[itemID] = tempSize - size elseif tempSize == size then temps[itemID] = nil else valid = false break end end end if valid then -- second, check the ore dictionary ---@param ie RecipeInputSlot for _, ie in each(recipe.inputs) do if ie.type == RecipeInputSlotType.OreDictionary then local ids = ItemUtils.GetOreDictionaryItemIDs(ie.id) local checkSize = ie.stackSize for _, subItemID in each(ids) do local tempSize = temps[subItemID] if tempSize ~= nil then if tempSize > checkSize then temps[subItemID] = tempSize - checkSize checkSize = 0 elseif tempSize == checkSize then temps[subItemID] = nil checkSize = 0 else checkSize = checkSize - tempSize temps[subItemID] = nil end end if checkSize <= 0 then break end end if checkSize > 0 then valid = false break end end end end if valid then table.insert(validRecipeIDs, recipeID) else local canDisplay = false -- check if contains recipe important input element ---@param ie RecipeInputSlot for _, ie in each(recipe.inputs) do if ie.isImportant then if ie.type == RecipeInputSlotType.Item then local itemID = ie.itemStack:GetItem().id if self._itemIDExistDict[itemID] ~= nil then canDisplay = true break end elseif ie.type == RecipeInputSlotType.OreDictionary then local ids = ItemUtils.GetOreDictionaryItemIDs(ie.id) for _, subItemID in each(ids) do if self._itemIDExistDict[subItemID] ~= nil then canDisplay = true break end end if canDisplay then break end end end end if canDisplay then table.insert(invalidRecipeIDs, recipeID) end end end local validItemStacks = {} local validItemCount = 0 local invalidItemStacks = {} local invalidItemCount = 0 local function doCacheData(recipeID, isCacheValidItem) local recipe = RecipeUtils.GetRecipe(recipeID) local stack = recipe.outputs[1]:GetStack() local itemID = stack:GetItem().id if self._recipeCacheItemData[itemID] == nil then local resStack = stack:Clone() resStack:SetStackSize(1) if isCacheValidItem then validItemStacks[itemID] = resStack validItemCount = validItemCount + 1 else invalidItemStacks[itemID] = resStack invalidItemCount = invalidItemCount + 1 end self._recipeCacheItemData[itemID] = { itemStack = resStack, validRecipeIDs = {}, invalidRecipeIDs = {} } end if isCacheValidItem then table.insert(self._recipeCacheItemData[itemID].validRecipeIDs, recipeID) else table.insert(self._recipeCacheItemData[itemID].invalidRecipeIDs, recipeID) end end for _, recipeID in pairs(validRecipeIDs) do doCacheData(recipeID, true) end for _, recipeID in pairs(invalidRecipeIDs) do doCacheData(recipeID, false) end self._recipeShowInventory:SetSlotCount(validItemCount + invalidItemCount) local index = 0 for _, itemStack in pairs(validItemStacks) do self._recipeShowInventory:GetSlot(index):PushStack(itemStack) index = index + 1 end self._recipeShowInventory:Sort(0, validItemCount) for _, itemStack in pairs(invalidItemStacks) do self._recipeShowInventory:GetSlot(index):PushStack(itemStack) index = index + 1 end self._recipeShowInventory:Sort(validItemCount, invalidItemCount) self._validItemCount = validItemCount self._invalidItemCount = invalidItemCount self._totalItemCount = self._validItemCount + self._invalidItemCount --self._recipeShowInventory:Sort(0, self._totalItemCount) if #self._onRecipeShowChangedListener == 2 then local caller = self._onRecipeShowChangedListener[2] local callback = self._onRecipeShowChangedListener[1] callback(caller) end print("Valid:", validItemCount, "Invalid:", invalidItemCount) end end return RecipeBookUI ================================================ FILE: ui/repair/RepairContainerClient.lua ================================================ ---@class TC.RepairContainerClient:Container local RepairContainerClient = class("RepairContainerClient", Container) local ContainerHelper = require("ui.ContainerHelper") function RepairContainerClient:__init(player, xi, yi) RepairContainerClient.super.__init(self) self.TOTAL_SLOT = 50 + 3 self.tempSlots = Inventory.new(self.TOTAL_SLOT) ContainerHelper.ContainerClientInitSlots(self, self.tempSlots) self.dataChangedCallback = nil self.needExpLevel = 0 end function RepairContainerClient:OnReceiveChange(id, value) if id == 0 then self.needExpLevel = value end end return RepairContainerClient ================================================ FILE: ui/repair/RepairContainerServer.lua ================================================ ---@class TC.RepairContainerServer:Container local RepairContainerServer = class("RepairContainerServer", Container) local ContainerHelper = require("ui.ContainerHelper") local UIData = require("RepairUIData") local RecipeBookServer = require("ui.recipe_book.RecipeBookServer") local REPAIR_SLOT_COUNT = 3 local REPAIR_OUTPUT_INDEX = 2 ---__init ---@param player Player ---@param xi int ---@param yi int function RepairContainerServer:__init(player, xi, yi) RepairContainerServer.super.__init(self) self.playerIndex = player.entityIndex self.inventory = player.backpackInventory self.xi = xi self.yi = yi -- 0-49 inventory ContainerHelper.ContainerServerAddBackpack(player, self) self._tempSlots = Inventory.new(REPAIR_SLOT_COUNT) self._toolSlot = self._tempSlots:GetSlot(0) self._sourceSlot = self._tempSlots:GetSlot(1) self._outputSlot = self._tempSlots:GetSlot(2) self._needExpLevel = 0 for i = 0, REPAIR_SLOT_COUNT - 1 do local slot = self._tempSlots:GetSlot(i) self:AddSlotToContainer(self._tempSlots, i) if i ~= REPAIR_OUTPUT_INDEX then slot:AddOnPickListener({ RepairContainerServer.OnChanged, self }) slot:AddOnPushListener({ RepairContainerServer.OnChanged, self }) end end self.recipeBookServer = RecipeBookServer.new( Reg.RecipeConfigID("Repair"), player, self._tempSlots, 0, 2) end function RepairContainerServer:OnChanged() self:_OnFlushData() end function RepairContainerServer:_OnFlushData() self._outputSlot:ClearStack() if self._toolSlot.hasStack and self._sourceSlot.hasStack then local toolStack = self._toolSlot:GetStack() local toolItem = toolStack:GetItem() if toolItem.isTool then local sourceStack = self._sourceSlot:GetStack() local sourceItem = sourceStack:GetItem() -- repair by an enchantment book if sourceItem.id == Reg.ItemID("enchanted_book") then local wasteLevel = 0.0 for i = 0, toolStack.enchantmentCount - 1 do local enchantment = toolStack:GetEnchantmentByIndex(i) local enchantmentData = EnchantmentUtils.GetData(enchantment.id) wasteLevel = wasteLevel + (enchantmentData.minCreatingLevel + enchantment.level) * 0.25 end self._needExpLevel = math.max(1, math.ceil(wasteLevel)) else local recipeID = RecipeUtils.SearchRecipe(Reg.RecipeConfigID("Repair"), self._tempSlots, 0, 2) if recipeID > 0 then local recipe = RecipeUtils.GetRecipe(recipeID) local recipeOutputSlot = recipe.outputs[1] if recipeOutputSlot.hasStack then local recipeInputToolElement = recipe.inputs[1] local isFixDurable = false local isCrafting = false if recipeInputToolElement.type == RecipeInputSlotType.Item and recipeInputToolElement.id == recipeOutputSlot:GetStack():GetItem().id then isFixDurable = true else isCrafting = true end local outputStack if isFixDurable then local repairRate = recipe.exData.repairRate outputStack = toolStack:Clone() outputStack:AddDurable(toolItem.maxDurable * repairRate) elseif isCrafting then outputStack = recipeOutputSlot:GetStack():Clone() local outputItem = outputStack:GetItem() local rate if toolItem.maxDurable > 0 then rate = toolStack.durable / toolItem.maxDurable else rate = 1.0 end outputStack:SetDurable(outputItem.maxDurable * rate) end self._outputSlot:PushStack(outputStack) end end end end end self:_SendData() end function RepairContainerServer:_SendData() self:DetectAndSendChangeInteger(0, self._needExpLevel) end function RepairContainerServer:OnEvent(eventId, eventString) if eventId == UIData.EventID.PickOutput then self:TryPickOutput() elseif eventId == UIData.EventID.RecipeBookRequest then local recipeID = tonumber(eventString) self.recipeBookServer:FlushValidRecipe(recipeID) end end function RepairContainerServer:TryPickOutput() if not PlayerUtils.IsAlive(self.playerIndex) then return end local player = PlayerUtils.Get(self.playerIndex) local inventory = player.backpackInventory if self._outputSlot.hasStack then local outStack = inventory:AddItemStack(self._outputSlot:GetStack()) if outStack:Valid() then player:DropItem(outStack) end self._outputSlot:ClearStack() end self._toolSlot:DecrStackSize(1) self._sourceSlot:DecrStackSize(1) self:OnChanged() end function RepairContainerServer:CanInteractWith(player) local ok = ContainerHelper.InInteractDistance(player, self.xi, self.yi) return ok end function RepairContainerServer:OnClose() ContainerHelper.CloseSendBackItems(self.playerIndex, self.xi, self.yi, self._tempSlots, { 0, 1 }) self._outputSlot:ClearStack() end return RepairContainerServer ================================================ FILE: ui/repair/RepairUI.lua ================================================ ---@class TC.RepairUI:GuiContainer local RepairUI = class("RepairUI", GuiContainer) local UIUtil = require("ui.UIUtil") local GuiID = require("ui.GuiID") local UIData = require("RepairUIData") local HotkeyUIHelper = require("ui.HotkeyUIHelper") ---@param container TC.RepairContainerClient function RepairUI:__init(container) RepairUI.super.__init(self, container) self.repairContainer = container self.repairContainer.dataChangedCallback = { self._OnDataChanged, self } self.ui = require("ui.UIWindow").new(require("ui.UIDesign").getRepairUI(), require("ui.UIDefault").GROUP_GAME_WINDOW) self.rootLayer = self.ui.root:getChild("layer") local listenSlots = {} for i = 0, 49 do table.insert(listenSlots, self.repairContainer.tempSlots:GetSlot(i)) end for i = 50, 51 do table.insert(listenSlots, self.repairContainer.tempSlots:GetSlot(i)) end table.insert(listenSlots, PlayerUtils.GetCurrentClientPlayer().mouseInventory:GetSlot(0)) self.recipeBookUI = require("ui.recipe_book.RecipeBookUI").new( Reg.RecipeConfigID("Repair"), self.rootLayer, false, listenSlots, { self._onValidRecipeClicked, self }, "11" ) self._hkHelper = HotkeyUIHelper.new(Mod.current, GuiID.Repair) self:_initContent() end function RepairUI:_initContent() local maxSlots = self.container:GetSlotCount() for i = 1, maxSlots do local tag = i - 1 if tag == 52 then local outputNode = self.rootLayer:getChildByTag(tag) local outputSlot = self.repairContainer.tempSlots:GetSlot(tag) UIUtil.hookSlotView(outputNode, outputSlot, true) outputNode:addTouchUpListener({ self._onOutputClicked, self, outputSlot }) else UIUtil.hookSlot(self.rootLayer:getChildByTag(tag), self, tag) end end self.rootLayer:getChild("btn_recipe"):addTouchUpListener({ self._onRecipeTriggerClicked, self }) self.ui.root:addTouchUpListener({ self.OnBgClicked, self }) end function RepairUI:_onValidRecipeClicked(recipeID) self:TriggerServerEvent(UIData.EventID.RecipeBookRequest, tostring(recipeID)) end function RepairUI:_onRecipeTriggerClicked() self.recipeBookUI:SetDisplayState(not self.recipeBookUI.showing) self.ui.manager:playClickSound() end ---@param slot Slot function RepairUI:_onOutputClicked(slot) if slot.hasStack then self.ui.manager:playClickSound() self:TriggerServerEvent(UIData.EventID.PickOutput) end end function RepairUI:_OnDataChanged() end function RepairUI:OnBgClicked() if require("ui.UISlotOp").onCheckPCDropOutItem() then return end local player = PlayerUtils.GetCurrentClientPlayer() if player then player:CloseGui(Mod.current, GuiID.Repair) end end function RepairUI:OnClose() self._hkHelper:destroy() self.ui:closeWindow() self.recipeBookUI:closeWindow() end ---checkSlotShiftMove ---@param slotIndex int ---@param itemStack ItemStack function RepairUI:checkSlotShiftMove(slotIndex, itemStack) if slotIndex < 10 then -- shortcut to backpack return self.container, 10, 40 elseif slotIndex < 50 then -- backpack to shortcut return self.container, 0, 10 end end return RepairUI ================================================ FILE: ui/repair/RepairUIData.lua ================================================ local RepairUIData = { EventID = { PickOutput = 1, RecipeBookRequest = 2, }, } return RepairUIData ================================================ FILE: ui/shooter/IShooterContainerClient.lua ================================================ ---@class TC.IShooterContainerClient:Container local IShooterContainerClient = class("IShooterContainerClient", Container) local ContainerHelper = require("ui.ContainerHelper") function IShooterContainerClient:__init(slotCount, player, xi, yi) IShooterContainerClient.super.__init(self) self.TOTAL_SLOT = slotCount + 50 self.tempSlots = Inventory.new(self.TOTAL_SLOT) ContainerHelper.ContainerClientInitSlots(self, self.tempSlots) end return IShooterContainerClient ================================================ FILE: ui/shooter/IShooterContainerServer.lua ================================================ ---@class TC.IShooterContainerServer:Container local IShooterContainerServer = class("IChestContainerServer", Container) local ContainerHelper = require("ui.ContainerHelper") ---__init ---@param slotCount int ---@param blockEntityName string ---@param player Player ---@param xi int ---@param yi int function IShooterContainerServer:__init(slotCount, blockEntityName, player, xi, yi) IShooterContainerServer.super.__init(self) self.playerIndex = player.entityIndex self.backpackInventory = player.backpackInventory self.xi = xi self.yi = yi -- 0-49 inventory ContainerHelper.ContainerServerAddBackpack(player, self) self.slotCount = slotCount self.blockEntityName = blockEntityName ---@type Inventory self.shooterInventory = self:GetMyEntity().inventory for i = 1, slotCount do self:AddSlotToContainer(self.shooterInventory, i - 1) end end function IShooterContainerServer:GetMyEntity() local blockEntity = MapUtils.GetBlockEntity(Reg.BlockEntityID(self.blockEntityName), self.xi, self.yi) if blockEntity == nil then return nil end ---@type TC.IShooterEntity local modEntity = blockEntity:GetModBlockEntity() return modEntity end function IShooterContainerServer:CanInteractWith(player) if self:GetMyEntity() == nil then return false end return ContainerHelper.InInteractDistance(player, self.xi, self.yi) end return IShooterContainerServer ================================================ FILE: ui/shooter/IShooterUI.lua ================================================ ---@class TC.IShooterUI:GuiContainer local IShooterUI = class("IShooterUI", GuiContainer) local UIUtil = require("ui.UIUtil") local GuiID = require("ui.GuiID") local HotkeyUIHelper = require("ui.HotkeyUIHelper") ---@param container TC.IChestContainerClient function IShooterUI:__init(rootNode, container) IShooterUI.super.__init(self, container) self.ui = require("ui.UIWindow").new(rootNode, require("ui.UIDefault").GROUP_GAME_WINDOW) self.rootLayer = self.ui.root:getChild("layer") self._hkHelper = HotkeyUIHelper.new(Mod.current, GuiID.Shooter9) self:_innerInitContent() end function IShooterUI:_innerInitContent() local maxSlots = self.container:GetSlotCount() for i = 1, maxSlots do UIUtil.hookSlot(self.rootLayer:getChildByTag(i - 1), self, i - 1) end end function IShooterUI:OnClose() self._hkHelper:destroy() self.ui:closeWindow() end return IShooterUI ================================================ FILE: ui/shooter/Shooter9ContainerClient.lua ================================================ ---@class TC.Shooter9ContainerClient:TC.IShooterContainerClient local Shooter9ContainerClient = class("Shooter9ContainerClient", require("IShooterContainerClient")) function Shooter9ContainerClient:__init(player, xi, yi) Shooter9ContainerClient.super.__init(self, 9, player, xi, yi) end return Shooter9ContainerClient ================================================ FILE: ui/shooter/Shooter9ContainerServer.lua ================================================ ---@class TC.Shooter9ContainerServer:TC.IShooterContainerServer local Shooter9ContainerServer = class("Shooter9ContainerServer", require("IShooterContainerServer")) ---__init ---@param player Player ---@param xi int ---@param yi int function Shooter9ContainerServer:__init(player, xi, yi) Shooter9ContainerServer.super.__init(self, 9, "Shooter9Entity", player, xi, yi) end return Shooter9ContainerServer ================================================ FILE: ui/shooter/Shooter9UI.lua ================================================ ---@class TC.Shooter9UI:TC.IShooterUI local Shooter9UI = class("Shooter9UI", require("IShooterUI")) ---@param container TC.Shooter9ContainerClient function Shooter9UI:__init(container) Shooter9UI.super.__init(self, require("ui.UIDesign").getShooter9UI(), container) end return Shooter9UI ================================================ FILE: ui/smelt/SmeltContainerClient.lua ================================================ ---@class TC.SmeltContainerClient:Container local SmeltContainerClient = class("SmeltContainerClient", Container) local ContainerHelper = require("ui.ContainerHelper") function SmeltContainerClient:__init(player, xi, yi) SmeltContainerClient.super.__init(self) self.cookProgress = 0 self.burnProgress = 0 self.TOTAL_SLOT = 54 self.tempSlots = Inventory.new(self.TOTAL_SLOT) ContainerHelper.ContainerClientInitSlots(self, self.tempSlots) end function SmeltContainerClient:OnEvent(eventId, eventString) end function SmeltContainerClient:OnUpdate() end function SmeltContainerClient:OnClose() end function SmeltContainerClient:OnReceiveChange(id, value) if id == 0 then self.cookProgress = value elseif id == 1 then self.burnProgress = value end end function SmeltContainerClient:CanInteractWith(player) return true end return SmeltContainerClient ================================================ FILE: ui/smelt/SmeltContainerServer.lua ================================================ ---@class TC.SmeltContainerServer:Container local SmeltContainerServer = class("SmeltContainerServer", Container) local UIData = require("SmeltUIData") local ContainerHelper = require("ui.ContainerHelper") local RecipeBookServer = require("ui.recipe_book.RecipeBookServer") ---__init ---@param player Player ---@param xi int ---@param yi int function SmeltContainerServer:__init(player, xi, yi) SmeltContainerServer.super.__init(self) self.playerIndex = player.entityIndex self.xi = xi self.yi = yi -- 0-49 inventory ContainerHelper.ContainerServerAddBackpack(player, self) local smeltEntity = self:GetSmeltEntity() for i = 0, 3 do local slot = smeltEntity.inventory:GetSlot(i) self:AddSlotToContainer(smeltEntity.inventory, i) if i ~= 2 then slot:AddOnPickListener({ SmeltContainerServer.OnChanged, self }) slot:AddOnPushListener({ SmeltContainerServer.OnChanged, self }) end end self.recipeBookServer = RecipeBookServer.new( Reg.RecipeConfigID("Smelt"), player, smeltEntity.inventory, 0, 1) end function SmeltContainerServer:GetSmeltEntity() local blockEntity = MapUtils.GetBlockEntity(Reg.BlockEntityID("SmeltEntity"), self.xi, self.yi) if blockEntity == nil then return nil end ---@type TC.SmeltEntity local smeltEntity = blockEntity:GetModBlockEntity() return smeltEntity end function SmeltContainerServer:OnChanged() local smeltEntity = self:GetSmeltEntity() if smeltEntity then smeltEntity:FlushRecipeData() end end function SmeltContainerServer:OnDetectChange() local smeltEntity = self:GetSmeltEntity() if smeltEntity then local cookProgress = 0 local burnProgress = 0 if smeltEntity.totalCookTime > 0 then cookProgress = math.ceil(smeltEntity.cookedTime * 16.0 / smeltEntity.totalCookTime) cookProgress = math.min(math.max(cookProgress, 0), 16) end if smeltEntity.burnTotalTime > 0 then burnProgress = math.ceil(smeltEntity.burnTime * 16.0 / smeltEntity.burnTotalTime) burnProgress = math.min(math.max(burnProgress, 0), 16) end self:DetectAndSendChangeInteger(0, cookProgress) self:DetectAndSendChangeInteger(1, burnProgress) end end function SmeltContainerServer:OnEvent(eventId, eventString) if eventId == UIData.EventID.RecipeBookRequest then local recipeID = tonumber(eventString) self.recipeBookServer:FlushValidRecipe(recipeID) elseif eventId == UIData.EventID.PickOutput then self:TryPickOutput() end end function SmeltContainerServer:TryPickOutput() if not PlayerUtils.IsAlive(self.playerIndex) then return end local player = PlayerUtils.Get(self.playerIndex) local smeltEntity = self:GetSmeltEntity() if smeltEntity == nil then return end local inventory = player.backpackInventory local outputSlot = smeltEntity.inventory:GetSlot(2) if outputSlot.hasStack then local outStack = inventory:AddItemStack(outputSlot:GetStack()) if outStack:Valid() then player:DropItem(outStack) end outputSlot:ClearStack() end self:OnChanged() end function SmeltContainerServer:CanInteractWith(player) if self:GetSmeltEntity() == nil then return false end local ok = ContainerHelper.InInteractDistance(player, self.xi, self.yi) return ok end return SmeltContainerServer ================================================ FILE: ui/smelt/SmeltUI.lua ================================================ ---@class TC.SmeltUI:GuiContainer local SmeltUI = class("SmeltUI", GuiContainer) local UIUtil = require("ui.UIUtil") local GuiID = require("ui.GuiID") local UIData = require("SmeltUIData") local HotkeyUIHelper = require("ui.HotkeyUIHelper") ---@param container TC.SmeltContainerClient function SmeltUI:__init(container) SmeltUI.super.__init(self, container) self.smeltContainer = container self.ui = require("ui.UIWindow").new(require("ui.UIDesign").getSmeltUI(), require("ui.UIDefault").GROUP_GAME_WINDOW) self.rootLayer = self.ui.root:getChild("layer") local listenSlots = {} for i = 0, 49 do table.insert(listenSlots, self.smeltContainer.tempSlots:GetSlot(i)) end table.insert(listenSlots, self.smeltContainer.tempSlots:GetSlot(50)) table.insert(listenSlots, PlayerUtils.GetCurrentClientPlayer().mouseInventory:GetSlot(0)) self.recipeBookUI = require("ui.recipe_book.RecipeBookUI").new( Reg.RecipeConfigID("Smelt"), self.rootLayer, false, listenSlots, { self._onValidRecipeClicked, self }, "1" ) self._hkHelper = HotkeyUIHelper.new(Mod.current, GuiID.Smelt) self:_initContent() end function SmeltUI:_initContent() local maxSlots = self.container:GetSlotCount() for i = 1, maxSlots do local tag = i - 1 if tag == 52 then local outputNode = self.rootLayer:getChildByTag(tag) local outputSlot = self.smeltContainer.tempSlots:GetSlot(tag) UIUtil.hookSlotView(outputNode, outputSlot, true) outputNode:addTouchUpListener({ self._onOutputClicked, self, outputSlot }) else UIUtil.hookSlot(self.rootLayer:getChildByTag(tag), self, tag) end end self.rootLayer:getChild("img_cook"):getPostDrawLayer(0):addListener({ SmeltUI.OnRenderCookProgress, self }) self.rootLayer:getChild("img_burn"):getPostDrawLayer(0):addListener({ SmeltUI.OnRenderBurnProgress, self }) self.rootLayer:getChild("btn_recipe"):addTouchUpListener({ self._onRecipeTriggerClicked, self }) self.ui.root:addTouchUpListener({ self.OnBgClicked, self }) end ---@param slot Slot function SmeltUI:_onOutputClicked(slot) if slot.hasStack then self.ui.manager:playClickSound() self:TriggerServerEvent(UIData.EventID.PickOutput) end end function SmeltUI:_onValidRecipeClicked(recipeID) self:TriggerServerEvent(UIData.EventID.RecipeBookRequest, tostring(recipeID)) end function SmeltUI:_onRecipeTriggerClicked() self.recipeBookUI:SetDisplayState(not self.recipeBookUI.showing) self.ui.manager:playClickSound() end ---OnRenderCookProgress ---@param node UINode ---@param canvasPos Vector2 function SmeltUI:OnRenderCookProgress(node, canvasPos) UIUtil.renderProgress("tc:process_01", node.positionInCanvas + canvasPos, self.smeltContainer.cookProgress, 16, 1, 0) end --- ---@param node UINode ---@param canvasPos Vector2 function SmeltUI:OnRenderBurnProgress(node, canvasPos) UIUtil.renderProgress("tc:burn_01", node.positionInCanvas + canvasPos, self.smeltContainer.burnProgress, 16, 0, -1) end function SmeltUI:OnBgClicked() if require("ui.UISlotOp").onCheckPCDropOutItem() then return end local player = PlayerUtils.GetCurrentClientPlayer() if player then player:CloseGui(Mod.current, GuiID.Smelt) end end function SmeltUI:OnUpdate() end function SmeltUI:OnClose() self._hkHelper:destroy() self.ui:closeWindow() self.recipeBookUI:closeWindow() end ---checkSlotShiftMove ---@param slotIndex int ---@param itemStack ItemStack function SmeltUI:checkSlotShiftMove(slotIndex, itemStack) if slotIndex < 10 then -- shortcut to backpack return self.container, 10, 40 elseif slotIndex < 50 then -- backpack to shortcut return self.container, 0, 10 end end return SmeltUI ================================================ FILE: ui/smelt/SmeltUIData.lua ================================================ local BackpackUIData = { EventID = { RecipeBookRequest = 1, PickOutput = 2, }, } return BackpackUIData ================================================ FILE: ui_res/advance_tip.json ================================================ { "textureInfo": { "name": "tc:advance_tip" }, "style": "Slices9", "slices9": { "left": 20, "right": 20, "top": 20, "bottom": 20 } } ================================================ FILE: ui_res/advancement_cell.json ================================================ { "textureInfo": { "name": "tc:advancement_cell" }, "style": "Slices9", "slices9": { "left": 8, "right": 8, "top": 8, "bottom": 8 } } ================================================ FILE: ui_res/base.json ================================================ { "textureInfo": { "name": "tc:base" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/base2.json ================================================ { "textureInfo": { "name": "tc:base2" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/base3.json ================================================ { "textureInfo": { "name": "tc:base3" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/base_list_cell.json ================================================ { "textureInfo": { "name": "tc:base_list_cell" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/base_list_cell_highlight.json ================================================ { "textureInfo": { "name": "tc:base_list_cell_highlight" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/base_list_cell_highlight_2.json ================================================ { "textureInfo": { "name": "tc:base_list_cell_highlight" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/black.json ================================================ { "textureInfo": { "name": "tc:black" }, "style": "Filled" } ================================================ FILE: ui_res/button_disabled.json ================================================ { "textureInfo": { "name": "tc:button_disabled" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/button_highlight.json ================================================ { "textureInfo": { "name": "tc:button_highlight" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/button_normal.json ================================================ { "textureInfo": { "name": "tc:button_normal" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/button_pressed.json ================================================ { "textureInfo": { "name": "tc:button_pressed" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/cell_empty.json ================================================ { "textureInfo": { "name": "tc:cell_empty" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/cell_empty_2.json ================================================ { "textureInfo": { "name": "tc:cell_empty_2" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/cell_empty_3.json ================================================ { "textureInfo": { "name": "tc:cell_empty_3" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/cell_empty_4.json ================================================ { "textureInfo": { "name": "tc:cell_empty_4" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/cell_normal.json ================================================ { "textureInfo": { "name": "tc:cell_normal" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/cell_selected.json ================================================ { "textureInfo": { "name": "tc:cell_selected" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/cell_selected_2.json ================================================ { "textureInfo": { "name": "tc:cell_selected_2" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/cell_selected_3.json ================================================ { "textureInfo": { "name": "tc:cell_selected_3" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/cell_selected_4.json ================================================ { "textureInfo": { "name": "tc:cell_selected_4" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/round_rect_white.json ================================================ { "textureInfo": { "name": "tc:round_rect_white" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/tab.json ================================================ { "textureInfo": { "name": "tc:tab" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/tab_clicked.json ================================================ { "textureInfo": { "name": "tc:tab_clicked" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/tipbox.json ================================================ { "textureInfo": { "name": "tc:tipbox" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: ui_res/white.json ================================================ { "textureInfo": { "name": "tc:white" }, "style": "Filled" } ================================================ FILE: ui_res/white_circle.json ================================================ { "textureInfo": { "name": "tc:white_circle" }, "style": "Filled" } ================================================ FILE: ui_res/window_frame_01.json ================================================ { "textureInfo": { "name": "tc:window_frame_01" }, "style": "Slices9", "slices9": { "left": 16, "right": 16, "top": 16, "bottom": 16 } } ================================================ FILE: util/Algorithm.lua ================================================ local Algorithm = class("Algorithm") --- make an array random order function Algorithm.Shuffle(array) --print("in", array) local n = #array for i = 1, n do local j = math.random(1, n) if i ~= j then local temp = array[i] array[i] = array[j] array[j] = temp end end --print("out", array) end function Algorithm.isRectTouch(x1, y1, w1, h1, x2, y2, w2, h2) if x1 < x2 + w2 and x1 + w1 > x2 and y1 + h1 > y2 and y1 < y2 + h2 then return true end end function Algorithm.isPointInPolygon(x, y, poly) -- poly is a Lua list of pairs like {x1, y1, x2, y2, ... xn, yn} -- see: https://love2d.org/forums/viewtopic.php?t=89699 local x1, y1, x2, y2 local len = #poly x2, y2 = poly[len - 1], poly[len] local wn = 0 for idx = 1, len, 2 do x1, y1 = x2, y2 x2, y2 = poly[idx], poly[idx + 1] if y1 > y then if (y2 <= y) and (x1 - x) * (y2 - y) < (x2 - x) * (y1 - y) then wn = wn + 1 end else if (y2 > y) and (x1 - x) * (y2 - y) > (x2 - x) * (y1 - y) then wn = wn - 1 end end end return wn % 2 ~= 0 -- even/odd rule end return Algorithm ================================================ FILE: util/DictUtil.lua ================================================ local DictUtils = class("DictUtils") return DictUtils ================================================ FILE: util/MiscHelper.lua ================================================ local MiscHelper = class("MiscHelper") local s_dirt = Reg.BlockID("dirt") local s_coarse_dirt = Reg.BlockID("coarse_dirt") local s_farmland = Reg.BlockID("farmland") local s_cow = Reg.NpcID("cow") local s_brown_mushroom_cow = Reg.NpcID("brown_mushroom_cow") local s_red_mushroom_cow = Reg.NpcID("red_mushroom_cow") local s_bone_meal = Reg.ItemID("bone_meal") local s_bowl = Reg.ItemID("bowl") local s_mushroom_stew = Reg.ItemID("mushroom_stew") local s_glass_bottle = Reg.ItemID("glass_bottle") local s_bucket_empty = Reg.ItemID("bucket_empty") local s_bucket_milk = Reg.ItemID("bucket_milk") local s_liquid_to_bucket_item_names = { { "water", "bucket_water" }, { "lava", "bucket_lava" }, } local s_liquid_2_buckets = {} for _, v in ipairs(s_liquid_to_bucket_item_names) do s_liquid_2_buckets[Reg.LiquidID(v[1])] = Reg.ItemID(v[2]) end local s_bucket_2_liquids = {} for _, v in ipairs(s_liquid_to_bucket_item_names) do s_bucket_2_liquids[Reg.ItemID(v[2])] = Reg.LiquidID(v[1]) end function MiscHelper.GetBucketIDFromLiquidID(liquidID) local res = s_liquid_2_buckets[liquidID] if res ~= nil then return res end return 0 end function MiscHelper.GetLiquidIDFromBucket(itemID) local res = s_bucket_2_liquids[itemID] if res ~= nil then return res end return 0 end function MiscHelper.GetMilkBucketID() return s_bucket_milk end function MiscHelper.GetEmptyBucketID() return s_bucket_empty end function MiscHelper.GetEmptyGrassBottleID() return s_glass_bottle end function MiscHelper.IsPullableBucket(itemID) return MiscHelper.GetLiquidIDFromBucket(itemID) > 0 end function MiscHelper.IsEmptyGrassBottle(itemID) return itemID == s_glass_bottle end function MiscHelper.IsEmptyBucket(itemID) return itemID == s_bucket_empty end function MiscHelper.IsMushroomCow(npcID) return npcID == s_brown_mushroom_cow or npcID == s_red_mushroom_cow end function MiscHelper.IsCow(npcID) return npcID == s_cow or MiscHelper.IsMushroomCow(npcID) end function MiscHelper.IsEmptyBowl(itemID) return itemID == s_bowl end function MiscHelper.GetMushroomBowl() return s_mushroom_stew end function MiscHelper.IsBoneMeal(itemID) return s_bone_meal == itemID end function MiscHelper.CanTransformToFramland(blockID) return blockID == s_dirt or blockID == s_coarse_dirt end function MiscHelper.GetFarmlandID() return s_farmland end function MiscHelper.OpenURL(url) print("open url:", url) if not App.isPC then require("tc.ui.InfoPopupUI").new(url) return end os.execute("start " .. url) end return MiscHelper ================================================ FILE: util/OrderedArray.lua ================================================ local OrderedArray = class("OrderedArray") function OrderedArray:__init() self.indices = {} self._elements = {} self._frees = {} end function OrderedArray:add(element) local index = 0 if #self._frees ~= 0 then index = self._frees[#self._frees] table.remove(self._frees, #self._frees) self._elements[index] = element else table.insert(self._elements, element) index = #self._elements end table.insert(self.indices, index) return index end function OrderedArray:remove(index) table.insert(self._frees, index) self._elements[index] = false for i, ii in ipairs(self.indices) do if ii == index then table.remove(self.indices, i) break end end end function OrderedArray:get(index) return self._elements[index] end function OrderedArray:clear() self.indices = {} self._elements = {} self._frees = {} end return OrderedArray ================================================ FILE: util/PhysicsUtil.lua ================================================ local PhysicsUtil = class("PhysicsUtil") function PhysicsUtil.SightChaseSpeed2D(spx, spy, force, forceAngle, maxSpeed) local PI = math.pi local oldAngle = Utils.FixAngle(Utils.GetAngle(spx, spy)) forceAngle = Utils.FixAngle(forceAngle) local moveAngle = forceAngle - oldAngle if math.abs(moveAngle) > PI then moveAngle = moveAngle + 2 * PI * (moveAngle > 0 and -1 or 1) end moveAngle = Utils.FixAngle(moveAngle) if math.abs(moveAngle) > PI / 2 then forceAngle = oldAngle + PI / 2 * (moveAngle < 0 and -1 or 1) end return Utils.ForceSpeed2D(spx, spy, force, forceAngle, maxSpeed) end return PhysicsUtil ================================================ FILE: util/SnakeModel.lua ================================================ local SnakeMass = class("SnakeMass") function SnakeMass:__init(x, y, nextDistance) self.x = x self.y = y self.nextDistance = nextDistance self.resAngle = 0 self.resCenterX = 0 self.resCenterY = 0 end function SnakeMass:setData(x, y, nextDistance) self.x = x self.y = y if nextDistance ~= nil then self.nextDistance = nextDistance end end local SnakeModel = class("SnakeModel") function SnakeModel:__init() self.m_masses = {} end function SnakeModel:clear() self.m_masses = {} end function SnakeModel:addHead(centerX, centerY, angle, jointLength) if #self.m_masses ~= 0 then return end table.insert(self.m_masses, SnakeMass.new(0, 0, 0)) table.insert(self.m_masses, SnakeMass.new(0, 0, 0)) self:setHead(centerX, centerY, angle, jointLength) end function SnakeModel:setHead(centerX, centerY, angle, jointLength) if #self.m_masses < 2 then return end local headLength = jointLength if headLength == nil then headLength = self.m_masses[1].nextDistance end local c = math.cos(angle + math.pi) * headLength * 0.5 local s = math.sin(angle + math.pi) * headLength * 0.5 if jointLength == nil then self.m_masses[1]:setData(centerX - c, centerY - s) self.m_masses[2]:setData(centerX + c, centerY + s) else self.m_masses[1]:setData(centerX - c, centerY - s, jointLength) self.m_masses[2]:setData(centerX + c, centerY + s, 0) end end function SnakeModel:addBody(angle, jointLength) if #self.m_masses < 2 then return end local lastMass = self.m_masses[#self.m_masses] lastMass.nextDistance = jointLength table.insert(self.m_masses, SnakeMass.new( lastMass.x + math.cos(angle) * jointLength, lastMass.y + math.sin(angle) * jointLength, 0 )) end function SnakeModel:getRes(index) if not (index >= 1 and index < #self.m_masses) then return 0.0, 0.0, 0.0 end local mass = self.m_masses[index] return mass.resCenterX, mass.resCenterY, mass.resAngle end function SnakeModel:update(headX, headY, headSpx, headSpy, headAngle) if #self.m_masses > 0 then self:setHead(headX, headY, headAngle) end local sqrt = math.sqrt local sin = math.sin local cos = math.cos local total = #self.m_masses local spx, spy = headSpx, headSpy for i = 1, total do local mass = self.m_masses[i] mass.x = mass.x + spx mass.y = mass.y + spy if i < total then local nextMass = self.m_masses[i + 1] local dx = nextMass.x - mass.x local dy = nextMass.y - mass.y local newDistance = sqrt(dx * dx + dy * dy) local newAngle = Utils.GetAngle(mass.x - nextMass.x, mass.y - nextMass.y) local moveDistance = newDistance - mass.nextDistance spx = cos(newAngle) * moveDistance spy = sin(newAngle) * moveDistance end end for i = 1, total - 1 do local mass = self.m_masses[i] local nextMass = self.m_masses[i + 1] mass.resAngle = Utils.FixAngle(Utils.GetAngle(nextMass.x - mass.x, nextMass.y - mass.y) + math.pi) mass.resCenterX = (mass.x + nextMass.x) * 0.5 mass.resCenterY = (mass.y + nextMass.y) * 0.5 end end return SnakeModel ================================================ FILE: util/StringUtil.lua ================================================ local StringUtils = class("StringUtils") local STR_ROMANS = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" } local ROMAN_VALUES = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 } function StringUtils.NumberToRoman(n) local result = "" for i = 1, 13 do while n - ROMAN_VALUES[i] >= 0 do result = result .. STR_ROMANS[i] n = n - ROMAN_VALUES[i] end end return result end function StringUtils.TicksToTimeFormat(ticks) local seconds = math.ceil(ticks / 60) local m = math.floor(seconds / 60) local s = seconds % 60 return string.format("%02d:%02d", m, s) end return StringUtils ================================================ FILE: util/ValidChecker.lua ================================================ local ValidChecker = class("ValidChecker") function ValidChecker.checkValidFileName(s) local last = "" for i, sub, b in utf8string.chars(s) do ---@type string local c = sub if c:len() ~= 1 then return false end if c ~= "_" and c ~= " " and c:match("%W") then return false end last = c end -- blank cannot locate at the end if last == " " then return false end return true end return ValidChecker ================================================ FILE: world/Portals.lua ================================================ local PortalEntity = class("PortalEntity") function PortalEntity:__init(xi, yi) self.xi = xi self.yi = yi end local Portals = class("Portals") function Portals:__init() self._dataList = {} end function Portals:Register(xi, yi) if self:IsExist(xi, yi) then return end table.insert(self._dataList, PortalEntity.new(xi, yi)) end function Portals:IsExist(xi, yi) return self:GetData(xi, yi) ~= nil end function Portals:GetList() return self._dataList end function Portals:GetData(xi, yi) for _, e in ipairs(self._dataList) do if e.xi == xi and e.yi == yi then return e end end return nil end function Portals:Save() local resList = {} for _, e in ipairs(self._dataList) do local elementData = { xi = e.xi, yi = e.yi, } table.insert(resList, elementData) end return { list = resList } end function Portals:Load(data) if data.list ~= nil then local resList = data.list for _, e in ipairs(resList) do local xi, yi = e.xi, e.yi self:Register(xi, yi) end end end return Portals ================================================ FILE: world/TCModWorldData.lua ================================================ ---@class TC.TCModWorldData local TCModWorldData = class("TCModWorldData") local Portals = require("Portals") local s_instance ---@return TC.TCModWorldData function TCModWorldData.getInstance() if s_instance == nil then s_instance = TCModWorldData.new() end return s_instance end function TCModWorldData:__init() self.portals = Portals.new() end function TCModWorldData:Save() local resPortals = self.portals:Save() return { portals = resPortals } end function TCModWorldData:Load(data) if data.portals ~= nil then self.portals:Load(data.portals) end end return TCModWorldData ================================================ FILE: world_gen/ChunkGenerator.lua ================================================ --- This is the main world generation code --- --- 世界生成代码,有些复杂,英文中文注释都补上 ---@class TC.ChunkGenerator local ChunkGenerator = class("ChunkGenerator") local TerrainProxies = require("TerrainProxies") local SpecialTerrainProxies = require("SpecialTerrainProxies") local TransitionProxies = require("TransitionProxies") local ModChunkGenerator = require("ModChunkGenerator") local Algorithm = require("util.Algorithm") local WorldGenDefine = require("WorldGenDefine") local BiomeType_Surface = Reg.BiomeTypeID("Surface") local BiomeType_Underground = Reg.BiomeTypeID("Underground") local BiomeType_Nether = Reg.BiomeTypeID("Nether") local DEFAULT_SURFACE_BIOME_ID = Reg.BiomeID("forest") local DEFAULT_UNDERGROUND_BIOME_ID = Reg.BiomeID("normal_cave") local UNDERGROUND_PERLIN_GEN_RATE = 0.36 local DEFAULT_UNDERGROUND_BIOME_AREAS = { { 0, 1024, Reg.BiomeID("normal_cave") }, { 1024, 1536, Reg.BiomeID("mud_cave") }, { 1536, 2048, Reg.BiomeID("stone_cave") }, { 2048, 2176, Reg.BiomeID("lava_cave") }, { 2176, 2560, Reg.BiomeID("magma_cave") }, } -- ======================================== -- AIR 空气层 -- ======================================== -- SURFACE 地表层 -- ======================================== -- UNDERGROUND 地下层 -- ---------------------------------------- -- DIRT/MUD (地下泥土层) -- ---------------------------------------- -- STONE (地下岩石层) -- ---------------------------------------- -- LAVA ZONE (地下熔岩层) -- ======================================== -- NETHER 地狱层 -- ======================================== -- TWILIGHT FOREST 暮色森林层 -- ======================================== local SURFACE_LINE = WorldGenDefine.SURFACE_LINE local UNDERGROUND_LINE = WorldGenDefine.UNDERGROUND_LINE local NETHER_LINE = WorldGenDefine.NETHER_LINE local NETHER_LAVA_LINE = WorldGenDefine.NETHER_LAVA_LINE local NETHER_LAVE_CAVE_HEIGHT = WorldGenDefine.NETHER_LAVE_CAVE_HEIGHT local UNDERGROUND_LAKE_LINE = WorldGenDefine.UNDERGROUND_LAKE_LINE local BEDROCK_CHUNK_YI = WorldGenDefine.BEDROCK_CHUNK_YI ---__init ---@param chunkXi int ---@param chunkYi int ---@param noise WorldGenNoise ---@param buffer WorldGenChunkBuffer function ChunkGenerator:__init(chunkXi, chunkYi, noise, buffer) self.chunkXi = chunkXi self.chunkYi = chunkYi self.chunkXiInMap = self.chunkXi * 1024 self.chunkYiInMap = self.chunkYi * 1024 self.noise = noise self.buffer = buffer self.isBedrockOnly = false self.isGenSurface = false self.isGenUnderground = false self.isGenNether = false self.isGenTwilightForest = false -- surface cache self.surfaceBiomeID = 0 self.surfaceBiomeID_Left = 0 self.surfaceBiomeID_Right = 0 local function _initMatrix(size, value) local temp = {} for i = 1, size * size do temp[i] = value end return temp end -- underground cache -- 34x34 matrix, 1-32: in current chunk, 0,33: adjust chunk self.undergroundBiomeIDMatrix = _initMatrix(34) local function _initBoundary(precise) local temp = {} if precise then for i = 1, 1024 do temp[i] = 0.0 end else for i = 1, 1024 do temp[i] = 0 end end return temp end -- All boundary array are using world coordinate system, -- you need to sub chunkYiInMap to get position in chunk coordinate system. -- -- 分界线数组都使用世界坐标系,你需要减掉chunkYiInMap来得到区间坐标系 self.surfacePreciseBoundary = _initBoundary(true) self.surfaceBoundary = _initBoundary(false) self.undergroundBoundary = _initBoundary(false) self.netherBoundary = _initBoundary(false) self.surfaceBiomeIDArray = _initBoundary(false) self.surfaceBoundaryID = 0 self.undergroundBoundaryID = 0 self.terrainProxies = TerrainProxies.new() self.specialTerrainProxies = SpecialTerrainProxies.new(buffer, noise, self.chunkYiInMap) self.transitionProxies = TransitionProxies.new(chunkXi, chunkYi, noise, buffer) self._pendingSortableBuildingList = {} self._modChunkGenerators = {} ---@type TC.ModChunkGenerator[] for _, c in ipairs(ModChunkGenerator.getProxy()) do local instance = c.new(self) table.insert(self._modChunkGenerators, instance) end end function ChunkGenerator:start() local timeDiff = TimeDiff.new() print("==> Init Layer") self:initLayer() print("==> Calculate Layer Boundary") self:calculateLayerBoundary() print("==> Process Layer") self:processLayer() print("==> Put Sub Blocks") self:putSubBlocks() print("==> Generate Sub Biomes") self:generateSubBiomes() print("==> Generate Caves") self:generateCaves() print("==> Generate Special Group") self:generateSpecialGroup() print("==> Generate Special Terrains") self:generateSpecialTerrains() print("==> Generate Underground Lake") self:generateUnderLake() self:generateSurfaceGrassCover() print("==> Settle All Element By Biomes") self.buffer:SettleAllElementByBiomes() print("==> Generate Ores") self:generateOres() print("==> Generate Trees") self:generateTrees() print("==> Generate Mushrooms") self:generateMushrooms() print("==> Generate Placeable") self:generatePlaceable() print("==> Generate Cobwebs") self:generateCobwebs() print("==> Generate Buildings") self:generateBuildings() if self.isBedrockOnly then return end print("==> Finish Chunk Generating in", timeDiff:diff(), "ms") end function ChunkGenerator:destroy() end --- decide what base layer will be generated (surface, underground, nether ...) --- --- 决定哪些层会被生成。(比如地表、地下、地狱) function ChunkGenerator:initLayer() if self.chunkYi >= BEDROCK_CHUNK_YI then self.isBedrockOnly = true return end if self.chunkYi == 0 then self.isGenSurface = true self.isGenUnderground = true elseif self.chunkYi == 1 then self.isGenUnderground = true elseif self.chunkYi == 2 then self.isGenUnderground = true self.isGenNether = true end for _, modChunkGenerator in ipairs(self._modChunkGenerators) do modChunkGenerator:onInitLayer() end end function ChunkGenerator:_getUndergroundYiAreaInChunk() if not self.isGenUnderground then return 0, 0 end local yi = 0 local yi2 = 1024 if self.isGenSurface then yi = UNDERGROUND_LINE - self.chunkYiInMap end if self.isGenNether then yi2 = NETHER_LINE - self.chunkYiInMap end yi = math.min(1024, math.max(0, yi)) yi2 = math.min(1024, math.max(yi, yi2)) return yi, yi2 - yi end --- Save boundary data between every layers. --- --- 计算层与层之间的边界。 function ChunkGenerator:calculateLayerBoundary() local max = math.max local min = math.min local defaultSurfaceBiomeID = DEFAULT_SURFACE_BIOME_ID local defaultUndergroundBiomeID = DEFAULT_UNDERGROUND_BIOME_ID local chunkXiInMap = self.chunkXiInMap local chunkYiInMap = self.chunkYiInMap local surfacePreciseBoundary = self.surfacePreciseBoundary local surfaceBoundary = self.surfaceBoundary local undergroundBoundary = self.undergroundBoundary local netherBoundary = self.netherBoundary local noise = self.noise local buffer = self.buffer local mapXi = 0 local perlinRes = 0 noise:SetData(0.5, 8) if self.isGenSurface and self.isGenUnderground then -- Current chunk has boundary between surface and underground. -- 当前区块有地表层和地下层的分界线。 for xi = 0, 1023 do mapXi = chunkXiInMap + xi -- surface line perlinRes = noise:Perlin1D(mapXi * 0.02) surfacePreciseBoundary[xi + 1] = SURFACE_LINE + perlinRes * 10.0 -- underground line perlinRes = noise:Perlin1D(mapXi * 0.33) undergroundBoundary[xi + 1] = UNDERGROUND_LINE + perlinRes * 8.0 end self:_fixSurfaceBoundary() self:_genSurfaceBiomeIDInfo() self:_genSurfaceTerrains() self:_fixSurfaceBoundary() self.surfaceBoundaryID = buffer:AddBoundaryArray(self.surfaceBoundary) self.undergroundBoundaryID = buffer:AddBoundaryArray(self.undergroundBoundary) -- Apply boundary to buffer. -- 应用分界。 for xi = 0, 1023 do local top = max(surfaceBoundary[xi + 1] - chunkYiInMap, 0) local bottom = min(undergroundBoundary[xi + 1] - chunkYiInMap, 1024) -- Surface layer buffer:SetBiomeArea(xi, top, 1, bottom - top, BiomeType_Surface, defaultSurfaceBiomeID, true, true) -- Underground layer buffer:SetBiomeArea(xi, bottom, 1, 1024 - bottom, BiomeType_Underground, defaultUndergroundBiomeID, true, true) end elseif self.isGenUnderground and self.isGenNether then -- Current chunk has boundary between underground and nether. -- 当前区块有地下层和地狱的分界线。 local netherBiomeID = Reg.BiomeID("nether") for xi = 0, 1023 do mapXi = chunkXiInMap + xi perlinRes = noise:Perlin1D(mapXi * 0.125) netherBoundary[xi + 1] = math.floor(NETHER_LINE + perlinRes * 20.0) end for xi = 0, 1023 do local bottom = min(netherBoundary[xi + 1] - chunkYiInMap, 1024) -- Underground layer buffer:SetBiomeArea(xi, 0, 1, bottom, BiomeType_Underground, defaultUndergroundBiomeID, true, true ) -- Nether layer buffer:SetBiomeArea(xi, bottom, 1, 1024 - bottom, BiomeType_Nether, netherBiomeID, true, true ) end elseif self.isGenUnderground then -- Underground layer only, there is no boundary in current chunk. -- 只有地下层,没有分界线。 buffer:SetBiomeArea(0, 0, 1024, 1024, BiomeType_Underground, defaultUndergroundBiomeID, true, true) end end function ChunkGenerator:_fixSurfaceBoundary() local surfacePreciseBoundary = self.surfacePreciseBoundary local surfaceBoundary = self.surfaceBoundary local floor = math.floor -- Transform to real surface boundary data. (double -> int) for xi = 0, 1023 do -- floor(a + 0.5) => round(a) surfaceBoundary[xi + 1] = floor(surfacePreciseBoundary[xi + 1] + 0.5) end end function ChunkGenerator:_genSurfaceBiomeIDInfo() local noise = self.noise noise:SetData(0.5, 8) for i = -1, 1 do local checkChunkXi = self.chunkXi + i local biomeID = self:getSurfaceMainBiomeID(checkChunkXi) if i == 0 then self.surfaceBiomeID = biomeID elseif i == -1 then self.surfaceBiomeID_Left = biomeID else self.surfaceBiomeID_Right = biomeID end end local surfaceBiomeID = self.surfaceBiomeID for xi = 0, 1023 do self.surfaceBiomeIDArray[xi + 1] = surfaceBiomeID end end function ChunkGenerator:_genSurfaceTerrains() local abs = math.abs local floor = math.floor local ceil = math.ceil local noise = self.noise local chunkXi = self.chunkXi local chunkYi = self.chunkYi local terrainProxies = self.terrainProxies local surfacePreciseBoundary = self.surfacePreciseBoundary noise:SetData(0.5, 8) local biomeData = BiomeUtils.GetData(self.surfaceBiomeID) local terrains = biomeData.terrains.terrains -- add terrains, just modify boundary array. -- 添加地形,只是修改边界数组的数据。 for i = 1, terrains.count do local terrain = terrains[i] local terrainTimes = terrain.times local times = 0 if terrainTimes < 1 then -- less than 1, use possibility -- 小于1就使用概率 local ranRate = noise:GetDoubleFromInt1D(chunkXi * 7 + terrain.size * 13 + terrain.height * 7) if abs(ranRate) < terrainTimes then times = 1 end else times = ceil(terrainTimes) end if times > 0 then for j = 1, times do local terrainName = terrain.name local locateRateX = abs(noise:GetDoubleFromInt2D(terrain.size + j, chunkYi * 7 + j + terrain.height)) local xi = floor(locateRateX * 1024) terrainProxies:calculateBoundaryFromTerrain(terrainName, surfacePreciseBoundary, xi, terrain.size, terrain.height) end end end end --- Write biome data into buffer for every layer. --- --- 根据不同层,初步填入群系数据。 function ChunkGenerator:processLayer() if self.isBedrockOnly then self:_genBedrockLayer() return end if self.isGenSurface then self:_genSurfaceBiomes() end if self.isGenUnderground then self:_genUndergroundBiomes() end if self.isGenNether then self:_genNetherBiomes() end end function ChunkGenerator:_genBedrockLayer() end --- Write surface biome data into buffer. --- --- 保存地表群落数据到缓冲区。 function ChunkGenerator:_genSurfaceBiomes() local leftTransition local rightTransition local currentTransition = BiomeUtils.GetData(self.surfaceBiomeID).terrains.transition if self.surfaceBiomeID > self.surfaceBiomeID_Left then leftTransition = currentTransition end if self.surfaceBiomeID > self.surfaceBiomeID_Right then rightTransition = currentTransition end if leftTransition ~= nil or rightTransition ~= nil then self.transitionProxies:doTransition(leftTransition, rightTransition, 0, 1024, self.surfaceBoundary, self.undergroundBoundary, { { BiomeType_Surface, self.surfaceBiomeID_Left }, { BiomeType_Surface, self.surfaceBiomeID }, { BiomeType_Surface, self.surfaceBiomeID_Right }, }, false, false) else local surfaceBoundary = self.surfaceBoundary local undergroundBoundary = self.undergroundBoundary local buffer = self.buffer local chunkYiInMap = self.chunkYiInMap local max = math.max local min = math.min for xi = 0, 1023 do local top = max(surfaceBoundary[xi + 1] - chunkYiInMap, 0) local bottom = min(undergroundBoundary[xi + 1] - chunkYiInMap, 1024) -- Surface layer buffer:SetBiomeArea(xi, top, 1, bottom - top, BiomeType_Surface, self.surfaceBiomeID, true, true) end end end function ChunkGenerator:generateSurfaceGrassCover() local buffer = self.buffer for xi = 0, 1023 do local yi = self.surfaceBoundary[xi + 1] if yi >= 0 and yi < 1023 then local bu = buffer:GetUnit(xi, yi) bu.isGrassCoverPreset = true end end end function ChunkGenerator:_genNetherBiomes() local chunkXiInMap = self.chunkXiInMap local chunkYiInMap = self.chunkYiInMap local netherBoundary = self.netherBoundary local min = math.min local max = math.max local buffer = self.buffer local sampleIf = buffer:GetSample(1) local maskIf = buffer:GetMask(1) sampleIf.biomeType = BiomeType_Underground maskIf.biomeType = true local sampleApply = buffer:GetSample(2) local maskApply = buffer:GetMask(2) sampleApply.biomeType = BiomeType_Nether maskApply.biomeType = true for xi = 0, 1023 do local netherYi = min(1023, max(0, netherBoundary[xi + 1] - chunkYiInMap)) local topCaveYi = min(1023, max(0, netherYi - 120)) buffer:ApplySampleByMaskByCondition(xi, topCaveYi, 1, 120, 2, 2, 1, 1) end buffer:ClearSample(1) buffer:ClearMask(1) buffer:ClearSample(2) buffer:ClearMask(2) end --- Write underground biome data into buffer. --- --- 保存地下群落数据到缓冲区。 function ChunkGenerator:_genUndergroundBiomes() self:_genUndergroundBiomeMatrix() for _, modChunkGenerator in ipairs(self._modChunkGenerators) do modChunkGenerator:onGenerateUndergroundMatrix() end self.buffer:SetBiomeIDFromMatrixByBiomeType(BiomeType_Underground, self.undergroundBiomeIDMatrix) end function ChunkGenerator:_genUndergroundBiomeMatrix() local defaultUndergroundBiomeID = DEFAULT_UNDERGROUND_BIOME_ID local defaultUndergroundBiomeAreas = DEFAULT_UNDERGROUND_BIOME_AREAS local noise = self.noise local matrix = self.undergroundBiomeIDMatrix local chunkYiInMap = self.chunkYiInMap noise:SetData(0.6, 2) for i = 0, 33 do local ii = i * 34 for j = 0, 33 do local biomeID = defaultUndergroundBiomeID local sourceY = chunkYiInMap + (j - 1) * 32 - 16 for _, data in ipairs(defaultUndergroundBiomeAreas) do if sourceY >= data[1] and sourceY < data[2] then biomeID = data[3] break end end matrix[ii + j + 1] = biomeID end end self:_randomUndergroundBiome() self:_specialGenUndergroundBiome() end function ChunkGenerator:_testInMatrixArea(globalXi, globalYi, width, height) return Algorithm.isRectTouch(globalXi, globalYi, width, height, self.chunkXiInMap - 32, self.chunkYiInMap - 32, 1024 + 64, 1024 + 64) end function ChunkGenerator:_getPolyArea(poly) local minX = 99999999 local maxX = -99999999 local minY = 99999999 local maxY = -99999999 local min = math.min local max = math.max local len = #poly for idx = 1, len, 2 do local x, y = poly[idx], poly[idx + 1] minX = min(x, minX) minY = min(y, minY) maxX = max(x, maxX) maxY = max(y, maxY) end return minX, minY, maxX, maxY end function ChunkGenerator:writeBiomeMatrixRect(globalXi, globalYi, width, height, matrixData, biomeID) if not self:_testInMatrixArea(globalXi, globalYi, width, height) then return end local globalXi2 = globalXi + width local globalYi2 = globalYi + height local chunkXiInMap = self.chunkXiInMap local chunkYiInMap = self.chunkYiInMap local matrix = matrixData for i = 0, 33 do local ii = i * 34 local sourceX = chunkXiInMap + (i - 1) * 32 - 16 if sourceX >= globalXi and sourceX < globalXi2 then for j = 0, 33 do local sourceY = chunkYiInMap + (j - 1) * 32 - 16 if sourceY >= globalYi and sourceY < globalYi2 then matrix[ii + j + 1] = biomeID end end end end end function ChunkGenerator:writeBiomeMatrixPolygon(poly, matrixData, biomeID) local minX, minY, maxX, maxY = self:_getPolyArea(poly) if not self:_testInMatrixArea(minX, minY, maxX - minX, maxY - minY) then return end local chunkXiInMap = self.chunkXiInMap local chunkYiInMap = self.chunkYiInMap local matrix = matrixData local isPointInPolygon = Algorithm.isPointInPolygon for i = 0, 33 do local ii = i * 34 local sourceX = chunkXiInMap + (i - 1) * 32 - 16 if sourceX >= minX and sourceX < maxX then for j = 0, 33 do local sourceY = chunkYiInMap + (j - 1) * 32 - 16 if sourceY >= minY and sourceY < maxY then if isPointInPolygon(sourceX, sourceY, poly) then matrix[ii + j + 1] = biomeID end end end end end end function ChunkGenerator:_randomUndergroundBiome() local noise = self.noise local matrix = self.undergroundBiomeIDMatrix noise:SetData(0.6, 2) local chunkXiInMap = self.chunkXiInMap local chunkYiInMap = self.chunkYiInMap local allBiomeIDs = { Reg.BiomeID("andesite_cave"), Reg.BiomeID("blue_mushroom_cave"), Reg.BiomeID("desert_cave"), Reg.BiomeID("flesh_cave"), Reg.BiomeID("granite_cave"), Reg.BiomeID("tainted_cave"), Reg.BiomeID("waste_cave"), Reg.BiomeID("diorite_cave"), Reg.BiomeID("jungle_cave"), } -- use perlin noise to decide every underground biome areas (old generate algorithm) -- 使用柏林噪声来决定每一个群系位置 for _, biomeID in ipairs(allBiomeIDs) do local biomeData = BiomeUtils.GetData(biomeID) local limitRate = UNDERGROUND_PERLIN_GEN_RATE * biomeData.scale local ddx = (biomeID) * 13217 local ddy = (biomeID) * 14537 for i = 0, 33 do local ii = i * 34 local perlinOffsetX = (chunkXiInMap + (i - 1) * 32 + ddx) * 0.0015625 for j = 0, 33 do local perlinOffsetY = (chunkYiInMap + (j - 1) * 32 + ddy) * 0.0015625 local rate = noise:Perlin2D( perlinOffsetX, perlinOffsetY ) * 0.5 + 0.5 if rate < limitRate then matrix[ii + j + 1] = biomeID end end end end end --- Set sub blocks to buffer. --- --- 把子方块写入到缓冲区。 function ChunkGenerator:putSubBlocks() local buffer = self.buffer local noise = self.noise noise:SetData(0.6, 2) buffer:PushAllSubBlocks() end --- function ChunkGenerator:generateCaves() self:_makeCaveHorizontal() self:_makeCaveRandomDirection() self:_makeCavePerlin() self:_specialMakeCave() for _, modChunkGenerator in ipairs(self._modChunkGenerators) do modChunkGenerator:onPostGenerateCaves() end end function ChunkGenerator:makeCaveHorizontalPoly( poly, randomKey, elementWidthMin, elementWidthMax, elementHeightMin, elementHeightMax, density, scaleX, persistence, octaves, amplitude, scaleXTop, persistenceTop, octavesTop, amplitudeTop, scaleXBottom, persistenceBottom, octavesBottom, amplitudeBottom) local minX, minY, maxX, maxY = self:_getPolyArea(poly) if not Algorithm.isRectTouch(minX, minY, maxX - minX, maxY - minY, self.chunkXiInMap, self.chunkYiInMap, 1024, 1024) then return end local buffer = self.buffer local wga = WorldGenArea.new(self.chunkXiInMap, self.chunkYiInMap, 1024, 1024) local areas = buffer:GetRandomAreas(randomKey, wga, elementWidthMin, elementWidthMax, elementHeightMin, elementHeightMax, density ) ---@param area WorldGenArea for _, area in ipairs(areas) do local x, y = area.xi + area.wi / 2, area.yi + area.hi / 2 if Algorithm.isPointInPolygon(x, y, poly) then buffer:PerlinMakeCaveHorizontal( area.xi - self.chunkXiInMap, area.yi - self.chunkYiInMap, area.wi, area.hi, scaleX, persistence, octaves, amplitude, scaleXTop, persistenceTop, octavesTop, amplitudeTop, scaleXBottom, persistenceBottom, octavesBottom, amplitudeBottom ) end end end function ChunkGenerator:_makeCaveHorizontal() local buffer = self.buffer local noise = self.noise noise:SetData(0.3, 4) -- generate horizontal cave -- 生成横向洞穴 local wga = WorldGenArea.new(self.chunkXiInMap, self.chunkYiInMap, 1024, 1024) local areas = buffer:GetRandomAreas(123, wga, 30, 250, 10, 13, 120.0 ) ---@param area WorldGenArea for _, area in ipairs(areas) do buffer:PerlinMakeCaveHorizontal( area.xi - self.chunkXiInMap, area.yi - self.chunkYiInMap, area.wi, area.hi, 0.01, 0.5, 8, 60.0, 0.15, 0.3, 4, 10.0, 0.3, 0.3, 4, 2.0 ) end local largeAreas = buffer:GetRandomAreas(777, wga, 100, 250, 13, 15, 26.0 ) ---@param area WorldGenArea for _, area in ipairs(largeAreas) do buffer:PerlinMakeCaveHorizontal( area.xi - self.chunkXiInMap, area.yi - self.chunkYiInMap, area.wi, area.hi, 0.022, 0.5, 8, 30.0, 0.15, 0.3, 4, 18.0, 0.25, 0.3, 4, 3.0 ) end end function ChunkGenerator:_makeCaveRandomDirection() local chunkYiInMap = self.chunkYiInMap local buffer = self.buffer local noise = self.noise noise:SetData(0.3, 4) local pc = 4 local cc = 1024 / pc for i = 0, pc - 1 do for j = 0, pc - 1 do local xi = i * cc + noise:GetByteFromInt2D(i, j, cc) local yi = j * cc + noise:GetByteFromInt2D(j + i, i, cc) local sourceY = chunkYiInMap + yi if sourceY > SURFACE_LINE + 30 then buffer:MakeCaveRandomDirection(xi, yi) end end end end function ChunkGenerator:_makeCavePerlin() local chunkYiInMap = self.chunkYiInMap local buffer = self.buffer local noise = self.noise noise:SetData(0.3, 4) buffer:PerlinMakeCave(0, 0, 1024, 1024, 0.03125, 0.041, 0.18, 1.0, SURFACE_LINE - chunkYiInMap + 100, 100, NETHER_LINE - chunkYiInMap, 50 ) end function ChunkGenerator:_testCode() local buffer = self.buffer local noise = self.noise noise:SetData(0.3, 4) local code = buffer:GetCode() --int testInt = (xi + 123) * 0.456 + 7 / 8.0 > 77 and true and 3 > 2 or false; --double testDouble = 0.333; local rawCode = [[ double testDouble = (xi+123*xi*(yi*0.6+666)); if testDouble<2 then int a = 1; elseif true then int aa = 2233; aa = aa + 1; elseif xi < 20 then testDouble = 2; else int b = 2; endif ]] code:CompileCode(rawCode) end function ChunkGenerator:_testMakeCave() local buffer = self.buffer local chunkXiInMap = self.chunkXiInMap local chunkYiInMap = self.chunkYiInMap local noise = self.noise noise:SetData(0.3, 4) local timeDiff = TimeDiff.new() for xi = 0, 1023 do local mapXi = chunkXiInMap + xi for yi = 0, 1023 do local bu = buffer:GetUnit(xi, yi) if bu.isFrontPreset then local mapYi = chunkYiInMap + yi local res = noise:Perlin2D(mapXi * 0.03125, mapYi * 0.041) * 0.5 + 0.5 if res < 0.41 then buffer:ClearFrontAndWall(xi, yi) end end end end print("LUA GEN CAVE TIME:", timeDiff:diff(), "ms") end --- Generate underground lake. --- --- 生成地下湖泊。 function ChunkGenerator:generateUnderLake() local buffer = self.buffer local chunkXiInMap = self.chunkXiInMap local chunkYiInMap = self.chunkYiInMap local noise = self.noise local surfaceLine = SURFACE_LINE local undergroundLakeLine = UNDERGROUND_LAKE_LINE local netherLine = NETHER_LINE noise:SetData(0.3, 4) local SAMPLE_TIMES = 1 local LIQUID_ID_LAVA = Reg.LiquidID("lava") for i = 0, 31 do for j = 0, 31 do for t = 0, SAMPLE_TIMES - 1 do local xi = i * 32 + noise:GetByteFromInt2D(i * 2 + t * 233, j, 32) local yi = j * 32 + noise:GetByteFromInt2D(j + i, i - j + t * 233, 32) if xi >= 0 and xi < 1024 and yi >= 0 and yi < 1024 then local mapYi = chunkYiInMap + yi if mapYi > surfaceLine and mapYi < undergroundLakeLine then local bu = buffer:GetUnit(xi, yi) local biomeData = BiomeUtils.GetData(bu.biomeID) local liquidInfo = biomeData.liquidInfo if liquidInfo.liquidID > 0 and liquidInfo.maxAllowCount > 0 then buffer:GenerateLake(xi, yi, liquidInfo.liquidID, liquidInfo.maxAllowCount) end elseif mapYi >= undergroundLakeLine and mapYi < netherLine then buffer:GenerateLake(xi, yi, LIQUID_ID_LAVA, 250) end end end end end -- nether lava if self.isGenNether then local lavaID = Reg.LiquidID("tc:lava") local lavaYi = NETHER_LAVA_LINE - chunkYiInMap local sampleIf = buffer:GetSample(1) local maskIf = buffer:GetMask(1) sampleIf.isFrontPreset = false maskIf.isFrontPreset = true buffer:SetLiquidAreaByCondition(0, lavaYi, 1024, 1024 - lavaYi, lavaID, 63, 1, 1) buffer:ClearSample(1) buffer:ClearMask(1) -- fill lava to make many levels for i = 0, 63 do local xi = 16 * i local yi = lavaYi - math.floor(math.abs(noise:GetDoubleFromInt1D(chunkXiInMap + chunkYiInMap + i)) * 48) buffer:GenerateLake(xi, yi, lavaID, 1000) end end end function ChunkGenerator:generateOres() local buffer = self.buffer local chunkXiInMap = self.chunkXiInMap local chunkYiInMap = self.chunkYiInMap local oreGroups = BlockUtils.oreGroups for i = 1, oreGroups.count do local oreGroup = oreGroups[i] local groupName = oreGroup.name local dataList = oreGroup.dataList for j = 1, dataList.count do local data = dataList[j] --print(groupName, data.oreID, data.radius, data.density) local oreID = data.oreID local r = data.radius local r2 = r * 2 local density = data.density local areaYi = math.max(chunkYiInMap, data.startYi) local areaYi2 = math.min(chunkYiInMap + 1024, data.endYi) if areaYi < areaYi2 then local mainArea = WorldGenArea.new(chunkXiInMap, areaYi, 1024, areaYi2 - areaYi) local areas = buffer:GetRandomAreas(data.oreID, mainArea, r2, r2, r2, r2, density) local lastBiomeID = -1 local canPlace = false ---@param area WorldGenArea for _, area in ipairs(areas) do local xi = area.xi - chunkXiInMap + r local yi = area.yi - chunkYiInMap + r if xi >= 0 and xi < 1024 and yi >= 0 and yi < 1024 then local bu = buffer:GetUnit(xi, yi) local biomeID = bu.biomeID if biomeID ~= lastBiomeID then local biomeData = BiomeUtils.GetData(biomeID) canPlace = (biomeData.oreGroupName == groupName) end if canPlace then buffer:AddBlockRandomOval( oreID, xi - r, yi - r, r2, r2, true, false, false ) end end end end end end end function ChunkGenerator:generateCobwebs() if not self.isGenUnderground then return end local buffer = self.buffer local chunkXiInMap = self.chunkXiInMap local chunkYiInMap = self.chunkYiInMap local cobwebID = Reg.BlockID("tc:cobweb") local r = 6 local r2 = r * 2 local r_half = math.ceil(r / 2) local density = 1000 local mainArea = WorldGenArea.new(chunkXiInMap, chunkYiInMap, 1024, 1024) local areas = buffer:GetRandomAreas(chunkXiInMap + chunkYiInMap + 233, mainArea, r2, r2, r2, r2, density ) ---@param area WorldGenArea for _, area in ipairs(areas) do local mapYi = area.yi if mapYi > UNDERGROUND_LINE and mapYi < NETHER_LINE then local mapXi = area.xi local xi = mapXi - chunkXiInMap local yi = mapYi - chunkYiInMap local hasSolid = buffer:IsAreaHasSolid(xi, yi, r, r_half) if hasSolid then buffer:AddBlockRandomOval( cobwebID, xi, yi, r2, r2, false, false, true) end end end end function ChunkGenerator:generateBuildings() for _, modChunkGenerator in ipairs(self._modChunkGenerators) do modChunkGenerator:onGenerateBuildings() end self:_onGenerateBuildings() -- sort by key and add all pending building to map. table.sort(self._pendingSortableBuildingList, function(a, b) return a.sizeAsSortKey > b.sizeAsSortKey end) for _, pendingBuilding in ipairs(self._pendingSortableBuildingList) do self.buffer:CreateBuilding(pendingBuilding.buildingID, pendingBuilding.xi, pendingBuilding.yi) end self.buffer:ApplyBuildings() end function ChunkGenerator:generateTrees() if self.isGenSurface then self:_genSurfaceTrees() end if self.isGenUnderground then self:_genUndergroundTrees() end end function ChunkGenerator:generateMushrooms() if self.isGenSurface then self:_genSurfaceMushrooms() end end function ChunkGenerator:_genSurfaceTrees() local abs = math.abs local buffer = self.buffer local lastBiomeID = 0 local biomeData ---@type BiomeData local noise = self.noise local rate = 0 local styles = 0 local totalStyles = 0 for xi = 4, 1019 do local biomeID = self.surfaceBiomeIDArray[xi + 1] if biomeData == nil or biomeID ~= lastBiomeID then lastBiomeID = biomeID biomeData = BiomeUtils.GetData(biomeID) rate = biomeData.treeInfo.density styles = biomeData.treeInfo.styles totalStyles = styles.count end if totalStyles > 0 and abs(noise:GetDoubleFromInt1D(xi * 32)) < rate then -- random pick a tree block to generate local yi = self.surfaceBoundary[xi + 1] local index = noise:GetByteFromInt2D(xi, xi * 32, totalStyles) + 1 local blockID = styles[index] local ok = buffer:GenerateTree(xi, yi, blockID) if ok then -- two trees must has at least 7 distance -- 两棵树必须距离至少7个格子 xi = xi + 6 end end end end function ChunkGenerator:_genSurfaceMushrooms() local abs = math.abs local buffer = self.buffer local lastBiomeID = 0 local biomeData ---@type BiomeData local noise = self.noise local rate = 0 local styles = 0 local totalStyles = 0 local stemID = Reg.BlockID("tc:mushroom_stem") for xi = 4, 1019 do local biomeID = self.surfaceBiomeIDArray[xi + 1] if biomeData == nil or biomeID ~= lastBiomeID then lastBiomeID = biomeID biomeData = BiomeUtils.GetData(biomeID) rate = biomeData.mushroomInfo.density styles = biomeData.mushroomInfo.styles totalStyles = styles.count end if totalStyles > 0 and abs(noise:GetDoubleFromInt1D(xi * 32)) < rate then -- random pick a tree block to generate local yi = self.surfaceBoundary[xi + 1] local index = noise:GetByteFromInt2D(xi, xi * 3, totalStyles) + 1 local blockID = styles[index] local ok = buffer:GenerateLargeMushroom(xi, yi, blockID, stemID) if ok then xi = xi + 6 end end end end function ChunkGenerator:_genUndergroundTrees() local abs = math.abs local buffer = self.buffer local noise = self.noise local SAMPLE_TIMES = 1024 * 8 local startYi, yiSize = self:_getUndergroundYiAreaInChunk() local posList = buffer:GetAllFloors(0, startYi, 1024, yiSize) local totalPos = posList.count local sampleStep = math.floor(totalPos / SAMPLE_TIMES) if sampleStep <= 0 then return end local lastBiomeID = -1 local treeInfo local styles local styleCount for step = 0, SAMPLE_TIMES - 1 do local index = step * sampleStep + 1 if index <= totalPos then local pos = posList[index] local xi = pos.xi local yi = pos.yi local bu = buffer:GetUnit(xi, yi) if bu.biomeID ~= lastBiomeID then lastBiomeID = bu.biomeID local biomeData = BiomeUtils.GetData(lastBiomeID) treeInfo = biomeData.treeInfo styles = treeInfo.styles styleCount = styles.count end if treeInfo ~= nil and styles.count > 0 then local rate = treeInfo.density * sampleStep local curRate = abs(noise:GetDoubleFromInt1D(xi * 32 + yi * 128)) if curRate < rate then local styleIndex = noise:GetByteFromInt2D(xi, xi * 32, styleCount) + 1 local blockID = styles[styleIndex] buffer:GenerateTree(xi, yi, blockID) end end end end end function ChunkGenerator:generatePlaceable() local buffer = self.buffer if self.isGenSurface then buffer:CreateAllPlaceableByBiomeType( 0, 0, 1024, 1024, BiomeType_Surface, self.surfaceBoundaryID) end if self.isGenUnderground then buffer:CreateAllPlaceableByBiomeType( 0, 0, 1024, 1024, BiomeType_Underground) end if self.isGenNether then buffer:CreateAllPlaceableByBiomeType( 0, 0, 1024, 1024, BiomeType_Nether ) end end function ChunkGenerator:getRandomTimes(rawTimes, randomKey) local times = 0 if rawTimes < 1 then if self:inChance(rawTimes, randomKey) then times = 1 end else times = math.ceil(rawTimes) end return times end function ChunkGenerator:inChance(rate, randomKey) return math.abs(self.noise:GetDoubleFromInt1D(randomKey)) < rate end function ChunkGenerator:_ranGenSurfaceSpecialTerrains(randomKey, rawTimes, size, height, cb, ignoreAreas, notAllowPaintSubBiome, currentBiomeID, biomeIDArray) if notAllowPaintSubBiome == nil then notAllowPaintSubBiome = false end local times = self:getRandomTimes(rawTimes, self.chunkXi * 223 + size + height * 7 + randomKey, 77) for t = 1, times do for k = 1, 5 do local xi = math.floor(1024 * math.abs(self.noise:GetDoubleFromInt2D(self.chunkXi * 19 + size + t + 123 + k, self.chunkXi * 223 + t * 2 + randomKey + k * 53))) local x1 = math.max(0, xi - size / 2) local x2 = math.min(1024, xi + size / 2) local ignore = false if ignoreAreas ~= nil then for _, area in ipairs(ignoreAreas) do if x1 >= area[1] and x2 <= area[2] then ignore = true break end end end if not ignore and notAllowPaintSubBiome and biomeIDArray ~= nil then for _xi = x1, x2 - 1 do if biomeIDArray[_xi + 1] ~= currentBiomeID then ignore = true break end end end if not ignore then cb(x1, x2) break end end end end function ChunkGenerator:_randGenSurfaceLake(rawTimes, size, height, liquidID, ignoreAreas) local function cb(x1, x2) self.specialTerrainProxies:createSurfaceLake(x1, x2, liquidID, height) end self:_ranGenSurfaceSpecialTerrains(self.chunkXi * 3 + 114, rawTimes, size, height, cb, ignoreAreas, true, self.surfaceBiomeID, self.surfaceBiomeIDArray) end function ChunkGenerator:_randGenSurfaceCave(rawTimes, size, ignoreAreas) local function cb(x1, x2) self.specialTerrainProxies:createSurfaceCave(x1, x2) end self:_ranGenSurfaceSpecialTerrains(self.chunkXi * 7 + 514, rawTimes, size, 0, cb, ignoreAreas, true, self.surfaceBiomeID, self.surfaceBiomeIDArray) end function ChunkGenerator:createSubBiomes(boundaryTop, x1, x2, depth, subBiomeID, maskedBiomeType, maskedBiomeID, biomeIDArray) x1 = math.max(0, x1) x2 = math.min(1024, x2) local size = (x2 - x1) local halfSize = math.floor(size / 2) if size <= 0 or halfSize <= 0 then return end local buffer = self.buffer local chunkYiInMap = self.chunkYiInMap local centerXi = math.ceil((x1 + x2) / 2) local sampleIf = buffer:GetSample(1) local maskIf = buffer:GetMask(1) sampleIf.biomeType = maskedBiomeType sampleIf.biomeID = maskedBiomeID maskIf.biomeType = true maskIf.biomeID = true local sampleApply = buffer:GetSample(2) local maskApply = buffer:GetMask(2) sampleApply.biomeID = subBiomeID maskApply.biomeID = true for xi = x1, x2 - 1 do local offsetX = 0 if xi < centerXi then offsetX = xi - x1 else offsetX = x2 - xi end local depthRate = offsetX / halfSize local currentDepth = math.ceil(depth * depthRate) if currentDepth > 0 then local topYi = boundaryTop[xi + 1] - chunkYiInMap buffer:ApplySampleByMaskByCondition(xi, topYi, 1, currentDepth, 2, 2, 1, 1) end biomeIDArray[xi + 1] = subBiomeID end buffer:ClearSample(1) buffer:ClearSample(2) buffer:ClearMask(1) buffer:ClearMask(2) end function ChunkGenerator:generateSpecialTerrains() if self.isGenSurface then self.specialTerrainProxies.biomeType1 = BiomeType_Surface self.specialTerrainProxies.biomeID1 = self.surfaceBiomeID self.specialTerrainProxies.boundary = self.surfaceBoundary local proxy = {} proxy[Reg.BiomeID("tc:forest")] = self.genSpecialTerrains_Forest proxy[Reg.BiomeID("tc:jungle")] = self.genSpecialTerrains_Jungle proxy[Reg.BiomeID("tc:desert")] = self.genSpecialTerrains_Desert proxy[Reg.BiomeID("tc:soft_snow_land")] = self.genSpecialTerrains_SoftSnowLand proxy[Reg.BiomeID("tc:super_volcano")] = self.genSpecialTerrains_SuperVolcano proxy[Reg.BiomeID("tc:mushroom_fields")] = self.genSpecialTerrains_MushroomFields local func = proxy[self.surfaceBiomeID] if func ~= nil then func(self) end end end function ChunkGenerator:genSpecialTerrains_Forest() local ignoreAreas = {} if self.chunkXi == 0 then table.insert(ignoreAreas, { 450, 550 }) end -- lakes self:_randGenSurfaceLake(0.5, 60, 10, Reg.LiquidID("water"), ignoreAreas) self:_randGenSurfaceLake(1.0, 40, 15, Reg.LiquidID("water"), ignoreAreas) -- surface caves self:_randGenSurfaceCave(1.0, 60, ignoreAreas) self:_randGenSurfaceCave(3.0, 40, ignoreAreas) end function ChunkGenerator:genSpecialTerrains_Jungle() -- lakes --self:_randGenSurfaceLake(1.0, 150, 20, Reg.LiquidID("water")) self:_randGenSurfaceLake(3.0, 60, 10, Reg.LiquidID("water")) self:_randGenSurfaceLake(2.0, 40, 30, Reg.LiquidID("water")) -- surface caves --self:_randGenSurfaceCave(3.0, 50) --self:_randGenSurfaceCave(2.0, 80) --self:_randGenSurfaceCave(2.0, 40) end function ChunkGenerator:genSpecialTerrains_SoftSnowLand() -- lakes self:_randGenSurfaceLake(0.5, 60, 10, Reg.LiquidID("water")) self:_randGenSurfaceLake(1.0, 40, 15, Reg.LiquidID("water")) -- surface caves self:_randGenSurfaceCave(1.0, 60) self:_randGenSurfaceCave(2.0, 50) self:_randGenSurfaceCave(4.0, 40) end function ChunkGenerator:genSpecialTerrains_SuperVolcano() -- lakes self:_randGenSurfaceLake(0.5, 60, 10, Reg.LiquidID("lava")) self:_randGenSurfaceLake(1.0, 40, 15, Reg.LiquidID("lava")) -- surface caves self:_randGenSurfaceCave(1.0, 60) self:_randGenSurfaceCave(2.0, 50) self:_randGenSurfaceCave(3.0, 40) end function ChunkGenerator:genSpecialTerrains_MushroomFields() -- lakes self:_randGenSurfaceLake(1.5, 40, 10, Reg.LiquidID("water")) self:_randGenSurfaceLake(2.0, 20, 10, Reg.LiquidID("water")) -- surface caves self:_randGenSurfaceCave(2.0, 60) self:_randGenSurfaceCave(3.0, 50) self:_randGenSurfaceCave(4.0, 40) end function ChunkGenerator:getSurfaceMainIndexAtLoop(chunkXi) return math.abs(chunkXi) % WorldGenDefine.SURFACE_CHUNK_XI_LOOP_TOTALS end local SURFACE_MAIN_INDEX_TO_BIOME_MAPPINGS = { [WorldGenDefine.SURFACE_CHUNK_XI_NEW_GUIDE_FOREST] = Reg.BiomeID("tc:forest"), [WorldGenDefine.SURFACE_CHUNK_XI_JUNGLE] = Reg.BiomeID("tc:jungle"), [WorldGenDefine.SURFACE_CHUNK_XI_SNOW] = Reg.BiomeID("tc:soft_snow_land"), [WorldGenDefine.SURFACE_CHUNK_XI_DUNGEON] = Reg.BiomeID("tc:forest"), [WorldGenDefine.SURFACE_CHUNK_XI_DESERT] = Reg.BiomeID("tc:desert"), [WorldGenDefine.SURFACE_CHUNK_XI_TAINTED] = Reg.BiomeID("tc:tainted_land"), [WorldGenDefine.SURFACE_CHUNK_XI_ICE_DUNGEON] = Reg.BiomeID("tc:flesh"), [WorldGenDefine.SURFACE_CHUNK_XI_VOLCANO] = Reg.BiomeID("tc:super_volcano"), [WorldGenDefine.SURFACE_CHUNK_XI_MUSHROOM] = Reg.BiomeID("tc:mushroom_fields"), [WorldGenDefine.SURFACE_CHUNK_XI_OCEAN] = Reg.BiomeID("tc:ocean"), } function ChunkGenerator:getSurfaceMainBiomeID(chunkXi) local mainIndex = self:getSurfaceMainIndexAtLoop(chunkXi) local resBiome = SURFACE_MAIN_INDEX_TO_BIOME_MAPPINGS[mainIndex] if resBiome ~= nil then return resBiome end -- random pick local maxSurfaceCount = BiomeUtils.GetBiomeCountByType(BiomeType_Surface) local index = self.noise:GetByteFromInt2D(chunkXi * 233, chunkXi * 73, maxSurfaceCount) return BiomeUtils.GetBiomeIDByType(BiomeType_Surface, index) end function ChunkGenerator:generateSpecialGroup() if self.surfaceBiomeID == Reg.BiomeID("ocean") then self:createOceanGroup() end end function ChunkGenerator:createOceanGroup() local chunkXiInMap = self.chunkXiInMap local chunkYiInMap = self.chunkYiInMap local floor = math.floor local sin = math.sin local max = math.max local pi = math.pi local buffer = self.buffer local noise = self.noise local surfaceBoundary = self.surfaceBoundary local sampleIf = buffer:GetSample(1) local maskIf = buffer:GetMask(1) sampleIf.isFrontPreset = true maskIf.isFrontPreset = true local sampleApply = buffer:GetSample(2) local maskApply = buffer:GetMask(2) sampleApply.isFrontPreset = true sampleApply.isWallPreset = true maskApply.isFrontPreset = true maskApply.isWallPreset = true local sandID = Reg.BlockID("tc:sand") for xi = 0, 1023 do local sands = 15 if xi < 40 then sands = xi elseif xi > 1024 - 40 then sands = 1024 - xi end sands = sands + floor(sin(xi / 8.0 * 3.0)) local surfaceYi = surfaceBoundary[xi + 1] - chunkYiInMap buffer:SetTileAreaByCondition(xi, surfaceYi, 1, sands, sandID, 0, true, 1, 1) buffer:ApplySampleByMask(xi, surfaceYi + sands, 1, 120 - sands, 2, 2) end local x1, x2 = 100, 900 local size, depth = 800, 80 local maxSurfaceYi = -99999999 for xi = x1, x2 - 1 do local surfaceYi = surfaceBoundary[xi + 1] - chunkYiInMap maxSurfaceYi = max(maxSurfaceYi, surfaceYi) local offset = floor(sin((xi - x1) / size * pi) * depth) buffer:ClearFrontAndWallArea(xi, surfaceYi, 1, offset) local deepSands = 10 + floor(sin(xi / 2)) buffer:SetTileAreaByCondition(xi, surfaceYi + offset, 1, deepSands, sandID, 0, true, 1, 1) end buffer:ClearSample(1) buffer:ClearMask(1) buffer:ClearSample(2) buffer:ClearMask(2) -- fill water buffer:GenerateLake((x1 + x2) / 2, maxSurfaceYi, Reg.LiquidID("tc:water"), 9999999) for i = 0, 2 do self:createSmallIsland(300 + i * 200 + noise:GetByteFromInt2D(chunkXiInMap, chunkYiInMap + i * 3, 50), maxSurfaceYi, 100) end end function ChunkGenerator:createSmallIsland(x, y, size) if size <= 0 then return end local abs = math.abs local floor = math.floor local max = math.max local sin = math.sin local buffer = self.buffer local noise = self.noise local surfaceBoundary = self.surfaceBoundary local size_2 = max(1, floor(size / 2)) local size_4 = max(1, floor(size / 4)) local size_4_3 = max(1, floor(size / 4 * 3)) local size_pi = math.pi / size local x1 = x - size_2 local oceanY = y local sandID = Reg.BlockID("tc:sand") local baseID = Reg.BlockID("tc:prismarine_mud") for i = 0, size - 1 do local xi = x1 + i local offsetY = abs(surfaceBoundary[xi + 1] - oceanY) if i < size_4 then offsetY = floor(offsetY * i / size_4) elseif i > size_4_3 then offsetY = floor(offsetY * (size - i) / size_4) end local surfaceY = oceanY - offsetY surfaceBoundary[xi + 1] = surfaceY local len = floor(offsetY * 2 + sin(i * size_pi) * 10) len = len + floor(sin(i / 4.0) * 2) + noise:GetByteFromInt2D(offsetY + i, offsetY, 2) local lineY = surfaceY + floor(len / 2) local bottomY = surfaceY + len buffer:ClearLiquidArea(xi, surfaceY, 1, len) buffer:SetTileArea(xi, surfaceY, 1, lineY - surfaceY, sandID, 0, true) buffer:SetWallArea(xi, surfaceY, 1, lineY - surfaceY, sandID, true) buffer:SetTileArea(xi, lineY, 1, bottomY - lineY, baseID, 0, true) buffer:SetWallArea(xi, lineY, 1, bottomY - lineY, baseID, true) local exOffset = floor(-sin(i / 4.0) * 2) + 8 if i < size_4 then exOffset = floor(exOffset * i / size_4) elseif i > size_4_3 then exOffset = floor(exOffset * (size - i) / size_4) end buffer:SetWallArea(xi, bottomY, 1, exOffset, baseID, true) end end function ChunkGenerator:generateSubBiomes() if self.chunkYi == 0 then local mainIndex = self:getSurfaceMainIndexAtLoop(self.chunkXi) if mainIndex == WorldGenDefine.SURFACE_CHUNK_XI_JUNGLE then self:createSubBiomes( self.surfaceBoundary, 100, 300, 150, Reg.BiomeID("tc:desert"), BiomeType_Surface, self.surfaceBiomeID, self.surfaceBiomeIDArray ) elseif mainIndex == WorldGenDefine.SURFACE_CHUNK_XI_DUNGEON then self:createSubBiomes( self.surfaceBoundary, 120, 400, 150, Reg.BiomeID("tc:tainted_land"), BiomeType_Surface, self.surfaceBiomeID, self.surfaceBiomeIDArray ) elseif mainIndex == WorldGenDefine.SURFACE_CHUNK_XI_DESERT then self:createSubBiomes( self.surfaceBoundary, 550, 900, 150, Reg.BiomeID("tc:badland"), BiomeType_Surface, self.surfaceBiomeID, self.surfaceBiomeIDArray ) elseif mainIndex == WorldGenDefine.SURFACE_CHUNK_XI_TAINTED then self:createSubBiomes( self.surfaceBoundary, 300, 600, 200, Reg.BiomeID("tc:jungle"), BiomeType_Surface, self.surfaceBiomeID, self.surfaceBiomeIDArray ) elseif mainIndex == WorldGenDefine.SURFACE_CHUNK_XI_ICE_DUNGEON then self:createSubBiomes( self.surfaceBoundary, 300, 660, 250, Reg.BiomeID("tc:soft_snow_land"), BiomeType_Surface, self.surfaceBiomeID, self.surfaceBiomeIDArray ) end end end function ChunkGenerator:createPendingBuildings(buildingID, xi, yi, sizeAsSortKey) table.insert(self._pendingSortableBuildingList, { buildingID = buildingID, xi = xi, yi = yi, sizeAsSortKey = sizeAsSortKey, }) end function ChunkGenerator:_onGenerateBuildings() if self.chunkYi == 0 then local mainIndex = self:getSurfaceMainIndexAtLoop(self.chunkXi) if mainIndex == WorldGenDefine.SURFACE_CHUNK_XI_NEW_GUIDE_FOREST then -- new player area for ii = 0, 1 do -- create house for new player living local genRightHouse = ii == 0 local houseXi = genRightHouse and 700 or 300 local houseYi = self.surfaceBoundary[houseXi + 1] - self.chunkYiInMap self.buffer:CreateBuilding(Reg.BuildingID("tc:mini_house"), houseXi, houseYi) -- create underground houses local idNames = { "tc:under_dark_oak_cabin", "tc:under_jungle_cabin", "tc:under_oak_cabin", "tc:under_stone_cabin", } local UNDER_CABINS_START_YI = SURFACE_LINE + 100 local UNDER_CABINS_SIZE = 500 local CABINS_PRE_CNT = 8 for i, idName in ipairs(idNames) do local buildingID = Reg.BuildingID(idName) local mainArea = WorldGenArea.new(self.chunkXiInMap, UNDER_CABINS_START_YI, 1024, UNDER_CABINS_SIZE) local areas = self.buffer:GetRandomAreas(self.chunkXiInMap + self.chunkYiInMap + 11233 + i * 7, mainArea, 1, 1, 1, 1, CABINS_PRE_CNT ) ---@param area WorldGenArea for _, area in ipairs(areas) do local xi = area.xi - self.chunkXiInMap local yi = area.yi - self.chunkYiInMap self.buffer:CreateBuilding(buildingID, xi, yi) end end end elseif mainIndex == WorldGenDefine.SURFACE_CHUNK_XI_JUNGLE then -- jungle zone --local houseXi = 400 --local houseYi = self.surfaceBoundary[houseXi + 1] - self.chunkYiInMap --self.buffer:CreateBuilding(Reg.BuildingID("tc:jungle_temple"), houseXi, houseYi) elseif mainIndex == WorldGenDefine.SURFACE_CHUNK_XI_SNOW then local houseXi = 500 local houseYi = self.surfaceBoundary[houseXi + 1] - self.chunkYiInMap self.buffer:CreateBuilding(Reg.BuildingID("tc:aurora_palace"), houseXi, houseYi) elseif mainIndex == WorldGenDefine.SURFACE_CHUNK_XI_OCEAN then local houseXi = 500 local houseYi = self.surfaceBoundary[houseXi + 1] + 80 self.buffer:CreateBuilding(Reg.BuildingID("tc:monument_ocean"), houseXi, houseYi) end end if self.isGenNether then local genYi = NETHER_LAVA_LINE - 50 - self.chunkYiInMap self.buffer:CreateBuilding(Reg.BuildingID("tc:nether_fortress"), 500, genYi) end if self.isGenUnderground then -- create underground houses local idNames = { "tc:under_dark_oak_cabin", "tc:under_jungle_cabin", "tc:under_oak_cabin", "tc:under_stone_cabin", "tc:under_spruce_cabin", "tc:under_tainted_cabin", "tc:under_desert_cabin", } local UNDER_CABINS_START_YI = UNDERGROUND_LINE local UNDER_CABINS_SIZE = NETHER_LINE - UNDERGROUND_LINE local CABINS_PRE_CNT = 2 for i, idName in ipairs(idNames) do self:_genTargetBuilding(Reg.BuildingID(idName), UNDER_CABINS_START_YI, UNDER_CABINS_SIZE, CABINS_PRE_CNT, self.chunkXiInMap + self.chunkYiInMap + 657 + i * 7) end end -- health crystals self:_genTargetBuilding(Reg.BuildingID("heart"), SURFACE_LINE + 100, NETHER_LAVA_LINE - SURFACE_LINE, 30, self.chunkXiInMap + self.chunkYiInMap + 1785) -- fossils self:_genTargetBuilding(Reg.BuildingID("fossils"), SURFACE_LINE + 100, NETHER_LINE - SURFACE_LINE, 30, self.chunkXiInMap * 2 + self.chunkYiInMap + 131) end function ChunkGenerator:_genTargetBuilding(buildingID, startYiInMap, height, density, randomKey) local mainArea = WorldGenArea.new(self.chunkXiInMap, startYiInMap, 1024, height) local areas = self.buffer:GetRandomAreas(randomKey, mainArea, 1, 1, 1, 1, density ) ---@param area WorldGenArea for _, area in ipairs(areas) do local xi = area.xi - self.chunkXiInMap local yi = area.yi - self.chunkYiInMap self.buffer:CreateBuilding(buildingID, xi, yi) end end function ChunkGenerator:_specialMakeCave() self:makeCaveHorizontalPoly(self:getUndergroundRealPolygon(self:_getPolyJungle()), 654, 30, 250, 15, 23, 120.0, 0.01, 0.5, 8, 60.0, 0.15, 0.3, 4, 10.0, 0.3, 0.3, 4, 2.0 ) self:makeCaveHorizontalPoly(self:getUndergroundRealPolygon(self:_getPolyBlueMushroom()), 654, 30, 250, 15, 43, 290.0, 0.01, 0.5, 8, 60.0, 0.15, 0.3, 4, 10.0, 0.3, 0.3, 4, 2.0 ) self:makeCaveHorizontalPoly(self:getUndergroundRealPolygon(self:_getPolyBlueMushroom2()), 654, 30, 250, 15, 43, 290.0, 0.01, 0.5, 8, 60.0, 0.15, 0.3, 4, 10.0, 0.3, 0.3, 4, 2.0 ) self:makeCaveHorizontalPoly(self:getUndergroundRealPolygon(self:_getPolyDeepIce()), 654, 80, 180, 8, 12, 280.0, 0.01, 0.5, 8, 12.0, 0.15, 0.3, 4, 10.0, 0.3, 0.3, 4, 2.0 ) -- nether if self.isGenNether then self:_genNetherCave() end end function ChunkGenerator:_genNetherCave() local buffer = self.buffer local wga = WorldGenArea.new(self.chunkXiInMap, NETHER_LAVA_LINE - NETHER_LAVE_CAVE_HEIGHT, 1024, NETHER_LAVE_CAVE_HEIGHT) local areas = buffer:GetRandomAreas(155, wga, 130, 250, 15, 23, 320.0 ) ---@param area WorldGenArea for _, area in ipairs(areas) do buffer:PerlinMakeCaveHorizontal( area.xi - self.chunkXiInMap, area.yi - self.chunkYiInMap, area.wi, area.hi, 0.01, 0.5, 8, 12.0, 0.15, 0.3, 4, 10.0, 0.3, 0.3, 4, 2.0 ) end end function ChunkGenerator:_getPolyJungle() return { --400, 500, --200, 800, --600, 1300, --900, 700, 1024, 500, 800, 1200, 1400, 1600, 2000, 1400, 2200, 1000, 2048, 500 } end function ChunkGenerator:_getPolyDeepIce() return { 2048 + 100, 500, 2048 - 400, 1500, 3096 + 400, 1500, 3096 - 100, 500 } end function ChunkGenerator:_getPolyBlueMushroom() return { 400, 600, 300, 900, 700, 1000, 800, 800 } end function ChunkGenerator:_getPolyBlueMushroom2() local l, r = 1024 * 7, 1024 * 8 return { l + 400, 600, l + 100, 1800, l + 700, 1900, l + 800, 800 } end function ChunkGenerator:_getPolyTainted() local l, r = 1024 * 5, 1024 * 6 return { l, 500, r, 1800, r + 500, 1800, l + 500, 500 } end function ChunkGenerator:_getPolyFlesh() local l, r = 1024 * 6, 1024 * 7 return { l + 500, 500, l - 500, 1800, l, 1800, r, 500 } end function ChunkGenerator:getUndergroundRealPolygon(polys) local polyDir = 0 if self.chunkXi > 0 then polyDir = 1 elseif self.chunkXi < 0 then polyDir = -1 end local loopIndex = math.floor(math.abs(self.chunkXi) / WorldGenDefine.SURFACE_CHUNK_XI_LOOP_TOTALS) local fixSideMove = loopIndex * 1024 * WorldGenDefine.SURFACE_CHUNK_XI_LOOP_TOTALS local fixSidePolys = clone(polys) for i = 1, #fixSidePolys, 2 do fixSidePolys[i] = fixSidePolys[i] + fixSideMove end if polyDir == -1 then for i = 1, #fixSidePolys, 2 do fixSidePolys[i] = -fixSidePolys[i] end end return fixSidePolys end function ChunkGenerator:writeUndergroundPolygon(polys, biomeID) local fixSidePolys = self:getUndergroundRealPolygon(polys) self:writeBiomeMatrixPolygon(fixSidePolys, self.undergroundBiomeIDMatrix, biomeID) end function ChunkGenerator:_specialGenUndergroundBiome() self:writeUndergroundPolygon(self:_getPolyJungle(), Reg.BiomeID("tc:jungle_cave")) self:writeUndergroundPolygon(self:_getPolyDeepIce(), Reg.BiomeID("tc:deep_ice_cave")) self:writeUndergroundPolygon(self:_getPolyBlueMushroom(), Reg.BiomeID("tc:blue_mushroom_cave")) self:writeUndergroundPolygon(self:_getPolyBlueMushroom2(), Reg.BiomeID("tc:blue_mushroom_cave")) self:writeUndergroundPolygon(self:_getPolyTainted(), Reg.BiomeID("tc:tainted_cave")) self:writeUndergroundPolygon(self:_getPolyFlesh(), Reg.BiomeID("tc:flesh_cave")) end return ChunkGenerator ================================================ FILE: world_gen/ModChunkGenerator.lua ================================================ ---@class TC.ModChunkGenerator local ModChunkGenerator = class("ModChunkGenerator") local s_proxy = {} ---__init ---@param generator TC.ChunkGenerator function ModChunkGenerator:__init(generator) ---@type TC.ChunkGenerator self._generator = generator end function ModChunkGenerator.getProxy() return s_proxy end function ModChunkGenerator.register(modChunkGeneratorClass) table.insert(s_proxy, modChunkGeneratorClass) end function ModChunkGenerator.destroy() s_proxy = {} end function ModChunkGenerator:onInitLayer() end function ModChunkGenerator:onGenerateUndergroundMatrix() end function ModChunkGenerator:onGenerateBuildings() end function ModChunkGenerator:onPostGenerateCaves() end return ModChunkGenerator ================================================ FILE: world_gen/SpecialTerrainProxies.lua ================================================ ---@class TC.SpecialTerrainProxies ---Store all calculation about how to modify the map. --- ---维护所有通用改变地形的算法。 local SpecialTerrainProxies = class("SpecialTerrainProxies") ---@param buffer WorldGenChunkBuffer ---@param noise WorldGenNoise ---@param chunkYiInMap int function SpecialTerrainProxies:__init(buffer, noise, chunkYiInMap) self._proxies = { SurfaceCave = SpecialTerrainProxies.createSurfaceCave, } self.chunkYiInMap = chunkYiInMap self.boundary = nil self.boundary2 = nil self.boundary3 = nil self.biomeType1 = 0 self.biomeType2 = 0 self.biomeType3 = 0 self.biomeID1 = 0 self.biomeID2 = 0 self.biomeID3 = 0 self._buffer = buffer self._noise = noise end function SpecialTerrainProxies.checkXArea(x1, x2) x1 = math.max(0, x1) x2 = math.min(1023, x2) if x1 >= x2 then return x1, x2, false end return x1, x2, true end function SpecialTerrainProxies:createSurfaceCave(x1, x2) local valid = true x1, x2, valid = SpecialTerrainProxies.checkXArea(x1, x2) if not valid then return end local boundary = self.boundary local noise = self._noise local buffer = self._buffer local chunkYiInMap = self.chunkYiInMap local sample1 = buffer:GetSample(1) sample1.isFrontPreset = true sample1.isWallPreset = true sample1.biomeType = self.biomeType1 sample1.biomeID = self.biomeID1 local mask1 = buffer:GetMask(1) mask1.isFrontPreset = true mask1.isWallPreset = true mask1.biomeType = true mask1.biomeID = true local sample2 = buffer:GetSample(2) sample2.isWallPreset = true sample2.biomeType = self.biomeType1 sample2.biomeID = self.biomeID1 local mask2 = buffer:GetMask(2) mask2.isWallPreset = true mask2.biomeType = true mask2.biomeID = true for xi = x1, x2 - 1 do local surfaceYi = boundary[xi + 1] - chunkYiInMap local offset = math.floor(10 + math.sin((xi + surfaceYi) * 0.125) * 2) local length = 5 offset = offset + noise:GetByteFromInt2D(xi, offset, 1) length = length + noise:GetByteFromInt2D(xi + 2, length, 1) if xi < x1 + 6 then length = math.floor(length * (1 - (x1 + 6 - xi) / 6.0)) end if xi > x2 - 6 then length = math.floor(length * (1 - (xi - (x2 - 6)) / 6.0)) end local backLength = offset if xi < x1 + 4 then backLength = math.floor(backLength * (1 - (x1 + 4 - xi) / 4.0)) end if xi > x2 - 4 then backLength = math.floor(backLength * (1 - (xi - (x2 - 4)) / 4.0)) end local y0 = surfaceYi - offset -- fill solid buffer:ApplySampleByMask(xi, y0 - length, 1, length, 1, 1) -- fill wall buffer:ApplySampleByMask(xi, y0, 1, backLength, 2, 2) boundary[xi + 1] = y0 - length end buffer:ClearSample(1) buffer:ClearMask(1) buffer:ClearSample(2) buffer:ClearMask(2) end function SpecialTerrainProxies:createSurfaceLake(x1, x2, liquidID, depth) local valid = true x1, x2, valid = SpecialTerrainProxies.checkXArea(x1, x2) if not valid then return end local size = x2 - x1 local boundary = self.boundary local noise = self._noise local buffer = self._buffer local chunkYiInMap = self.chunkYiInMap local sample1 = buffer:GetSample(1) sample1.isLiquidPreset = true local mask1 = buffer:GetMask(1) mask1.isLiquidPreset = true local failed = false for xi = x1, x2 - 1 do local surfaceYi = boundary[xi + 1] - chunkYiInMap if buffer:HasAreaSameSampleByMask(xi, surfaceYi - 1, 1, depth + 1, 1, 1) then failed = true break end end if not failed then local maxSurfaceYi = -999999999 for xi = x1, x2 - 1 do local surfaceYi = boundary[xi + 1] - chunkYiInMap maxSurfaceYi = math.max(maxSurfaceYi, surfaceYi) local offset = math.floor(math.sin((xi - x1) / size * math.pi) * depth) buffer:ClearFrontAndWallArea(xi, surfaceYi, 1, offset) boundary[xi + 1] = surfaceYi + offset end buffer:GenerateLake((x1 + x2) / 2, maxSurfaceYi, liquidID, 10000) end buffer:ClearSample(1) buffer:ClearMask(1) end return SpecialTerrainProxies ================================================ FILE: world_gen/TerrainProxies.lua ================================================ ---@class TC.TerrainProxies ---Store all calculation about how to modify a boundary array. --- ---维护所有可以改变边界数组的算法。 local TerrainProxies = class("TerrainProxies") function TerrainProxies:__init() self._proxies = { FlatTerrain = TerrainProxies.calculateBoundary_FlatTerrain, MountainTerrain = TerrainProxies.calculateBoundary_MountainTerrain, HillTerrain = TerrainProxies.calculateBoundary_HillTerrain, BasinTerrain = TerrainProxies.calculateBoundary_BasinTerrain, PlateauTerrain = TerrainProxies.calculateBoundary_PlateauTerrain, } end --- Modify the boundary array by specify terrain function. ---@param terrainName string ---@param boundary double[] ---@param xi int ---@param size int ---@param height int function TerrainProxies:calculateBoundaryFromTerrain(terrainName, boundary, xi, size, height) if size > 1010 then -- too big, do nothing. return end local func = self._proxies[terrainName] if func == nil then return end local x1, x2 = xi - math.floor(size / 2), xi + math.floor(size / 2) if x1 < 0 then x1 = 0 x2 = x1 + size end if x2 >= 1024 then x2 = 1023 x1 = x2 - size end if x2 > x1 then func(self, boundary, x1, x2, height) end end --- Flat, do nothing. --- --- 平坦,什么都不做 function TerrainProxies:calculateBoundary_FlatTerrain(boundary, x1, x2, height) return end --- Mountain, a SIN function. --- --- 大山(坟包),长得像三角函数的样子 function TerrainProxies:calculateBoundary_MountainTerrain(boundary, x1, x2, height) local sin = math.sin local size = x2 - x1 local c = math.pi / size for x = x1, x2 - 1 do local res = sin((x - x1) * c) * height boundary[x + 1] = boundary[x + 1] - res end end --- 丘陵 function TerrainProxies:calculateBoundary_HillTerrain(boundary, x1, x2, height) local sin = math.sin local size = x2 - x1 local c = math.pi / 64 local offset = math.floor(size / 4) local invOffset = 1.0 / offset for x = x1, x2 - 1 do local res = sin((x - x1) * c) * height if x < x1 + offset then res = res * (1 - (x1 + offset - x) * invOffset) end if x > x2 - offset then res = res * (1 - (x - x2 + offset) * invOffset) end boundary[x + 1] = boundary[x + 1] - res end end --- 盆地 function TerrainProxies:calculateBoundary_BasinTerrain(boundary, x1, x2, height) local sin = math.sin local size = x2 - x1 local c = math.pi / size for x = x1, x2 - 1 do local res = sin((x - x1) * c) * height boundary[x + 1] = boundary[x + 1] + res end end --- 高原 function TerrainProxies:calculateBoundary_PlateauTerrain(boundary, x1, x2, height) local size = x2 - x1 local d = math.floor(size / 32) if d == 0 then return end local sin = math.sin local side = math.floor(size / 16) local halfSide = math.floor(size / 32) local leftSide = x1 + side local halfLeftSide = x1 + halfSide local rightSide = x2 - side local halfRightSide = x2 - halfSide local halfHeight = height * 0.5 local c = math.pi * 0.5 / d for x = x1, leftSide - 1 do local res = sin((x - halfLeftSide) * c) * halfHeight + halfHeight boundary[x + 1] = boundary[x + 1] - res end for x = leftSide, rightSide - 1 do boundary[x + 1] = boundary[x + 1] - height end for x = rightSide, x2 - 1 do local res = sin((halfRightSide - x) * c) * halfHeight + halfHeight boundary[x + 1] = boundary[x + 1] - res end end return TerrainProxies ================================================ FILE: world_gen/TransitionProxies.lua ================================================ ---@class TC.SurfaceTransitionProxies ---Store all algorithms of how to transition between surface biomes. --- ---维护地表结构的群系过渡算法。 local SurfaceTransitionProxies = class("TransitionProxies") ---__init ---@param chunkXi int ---@param chunkYi int ---@param noise WorldGenNoise ---@param buffer WorldGenChunkBuffer function SurfaceTransitionProxies:__init(chunkXi, chunkYi, noise, buffer) -- TODO:DiscreteTransition self._noise = noise self._buffer = buffer self._chunkXi = chunkXi self._chunkYi = chunkYi self._levelProxies = { LinerTransition = SurfaceTransitionProxies.getTransitionLevel_Liner, ParabolaTransition = SurfaceTransitionProxies.getTransitionLevel_Parabola, DiscreteTransition = SurfaceTransitionProxies.getTransitionLevel_Discrete, } end ---doTransition ---@param leftTransitionName string ---@param rightTransitionName string ---@param x1 int ---@param x2 int ---@param topBoundary int[] ---@param bottomBoundary int[] ---@param biomeInfo table ---@param checkFromChunkTop boolean ---@param checkFromChunkBottom boolean function SurfaceTransitionProxies:doTransition(leftTransitionName, rightTransitionName, x1, x2, topBoundary, bottomBoundary, biomeInfo, checkFromChunkTop, checkFromChunkBottom) if not (x1 >= 0 and x2 <= 1024 and x2 > x1) then return end local isLeftTransiting = (leftTransitionName ~= nil) local isRightTransiting = (rightTransitionName ~= nil) if not isLeftTransiting and not isRightTransiting then return end local leftFunc local rightFunc if isLeftTransiting then leftFunc = self._levelProxies[leftTransitionName] if leftFunc == nil then return end end if isRightTransiting then rightFunc = self._levelProxies[rightTransitionName] if rightFunc == nil then return end end local max = math.max local min = math.min local floor = math.floor local buffer = self._buffer local noise = self._noise local chunkXiInMap = self._chunkXi * 1024 local chunkYiInMap = self._chunkYi * 1024 local leftBiomeType = biomeInfo[1][1] local leftBiomeID = biomeInfo[1][2] local rightBiomeType = biomeInfo[3][1] local rightBiomeID = biomeInfo[3][2] local currentBiomeType = biomeInfo[2][1] local currentBiomeID = biomeInfo[2][2] local centerXi = floor((x1 + x2) / 2) if currentBiomeType ~= leftBiomeType or currentBiomeType ~= rightBiomeType then return end for xi = x1, x2 - 1 do local mapXi = chunkXiInMap + xi local usingLevelFlag = 0 local level = 0 local adjBiomeID = currentBiomeID local inLeftSide = xi < centerXi if inLeftSide then if isLeftTransiting then usingLevelFlag = 1 level = leftFunc(noise, mapXi, xi - x1) adjBiomeID = leftBiomeID end else if isRightTransiting then usingLevelFlag = 2 level = rightFunc(noise, mapXi, x2 - xi) adjBiomeID = rightBiomeID end end local top = 0 local bottom = 1024 local topBoundaryValue = topBoundary[xi + 1] local bottomBoundaryValue = bottomBoundary[xi + 1] if not checkFromChunkTop then top = max(topBoundaryValue - chunkYiInMap, 0) end if not checkFromChunkBottom then bottom = min(bottomBoundaryValue - chunkYiInMap, 1024) end if usingLevelFlag ~= 0 then local splitYi = math.max(0, topBoundaryValue - chunkYiInMap + level) buffer:SetBiomeIDAreaByBiomeType(xi, top, 1, splitYi, currentBiomeType, currentBiomeID) buffer:SetBiomeIDAreaByBiomeType(xi, splitYi, 1, bottom - splitYi, currentBiomeType, adjBiomeID) else buffer:SetBiomeIDAreaByBiomeType(xi, top, 1, bottom - top, currentBiomeType, currentBiomeID) end end end ---y=x function SurfaceTransitionProxies.getTransitionLevel_Liner(noise, mapXi, d) return noise:GetDoubleFromInt1D(mapXi) * 2 + d end ---y=x^2 function SurfaceTransitionProxies.getTransitionLevel_Parabola(noise, mapXi, d) return noise:GetDoubleFromInt1D(mapXi) * 2 + d * d * 0.01 end ---y=x function SurfaceTransitionProxies.getTransitionLevel_Discrete(noise, mapXi, d) return SurfaceTransitionProxies.getTransitionLevel_Liner(noise, mapXi, d) end return SurfaceTransitionProxies ================================================ FILE: world_gen/WorldGenDefine.lua ================================================ ---@class TC.WorldGenDefine local WorldGenDefine = { SURFACE_LINE = 400, -- line between surface layer and air layer UNDERGROUND_LINE = 600, -- line between surface layer and underground layer NETHER_LINE = 2560, -- line between underground layer and nether layer NETHER_LAVA_LINE = 2700, -- line to start generating nether large lava lake NETHER_LAVE_CAVE_HEIGHT = 60, -- the height of nether large cave UNDERGROUND_LAKE_LINE = 1536, -- line to start generating lava lake BEDROCK_CHUNK_YI = 3, -- bedrock layer chunk y index SURFACE_CHUNK_XI_NEW_GUIDE_FOREST = 0, -- new player's forest SURFACE_CHUNK_XI_JUNGLE = 1, -- jungle with small desert and ghost house SURFACE_CHUNK_XI_SNOW = 2, -- snow land with palace and danger caves SURFACE_CHUNK_XI_DUNGEON = 3, -- a terraria style dungeon area SURFACE_CHUNK_XI_DESERT = 4, -- a large desert area with pyramid dungeon and wasteland SURFACE_CHUNK_XI_TAINTED = 5, -- a large tainted area SURFACE_CHUNK_XI_ICE_DUNGEON = 6, -- snow land with ice dungeon SURFACE_CHUNK_XI_VOLCANO = 7, -- volcano with castle SURFACE_CHUNK_XI_MUSHROOM = 8, -- peaceful mushroom island SURFACE_CHUNK_XI_OCEAN = 9, -- ocean SURFACE_CHUNK_XI_LOOP_TOTALS = 10 } return WorldGenDefine ================================================ FILE: world_gen_init.lua ================================================ local TCWorldGen = class("TCWorldGen") local ChunkGenerator = require("world_gen.ChunkGenerator") local ModChunkGenerator = require("world_gen.ModChunkGenerator") function TCWorldGen:init() self.noise = nil ---@type WorldGenNoise end function TCWorldGen:exit() ModChunkGenerator.destroy() end function TCWorldGen:startGenChunk(chunkXi, chunkYi, noise, buffer) self.noise = noise local chunkGenerator = ChunkGenerator.new(chunkXi, chunkYi, noise, buffer) chunkGenerator:start() chunkGenerator:destroy() collectgarbage() end function TCWorldGen:onSetBlockEntityFormat(formatId, data, xi, yi) local function _randomIndices(totals) local arr = {} local out = {} for i = 1, totals do arr[i] = i end for i = 1, totals do local pickIndex = self.noise:GetByteFromInt2D(xi + 451 * i, yi + 23, #arr) + 1 table.insert(out, arr[pickIndex]) table.remove(arr, pickIndex) end return out end if formatId == "tc:common_rewards" then local res = {} local inventoryData = { slotCount = 30, stacks = {} } local index = 0 local function addReward(i, itemID, cnt) local out = { index = i, stack = { id = itemID, stackSize = cnt } } return out end local totalRares = #data.rares local ranIndices = _randomIndices(totalRares) for i = 1, math.min(#ranIndices, data.rareGenCount) do local rare = data.rares[ranIndices[i]] local out = addReward(index, rare.itemId, rare.count) table.insert(inventoryData.stacks, out) index = index + 1 end for i = 1, #data.normals do local normal = data.normals[i] local testRate = math.abs(self.noise:GetDoubleFromInt2D(xi + 33 * i, yi + 77)) if testRate < normal.rate then local cnt = normal.min + self.noise:GetByteFromInt2D(xi * 13, yi + 57, normal.max - normal.min) local itemID = normal.itemIds[ self.noise:GetByteFromInt2D(xi + 62, yi + 98, #normal.itemIds) + 1 ] local out = addReward(index, itemID, cnt) table.insert(inventoryData.stacks, out) index = index + 1 end end res = { inventory = inventoryData } return res elseif formatId == "tc:rewards" then return data elseif formatId == "tc:empty_furnace" then return {} end return data end return TCWorldGen