From c43a666aca98d1e4ce6b0387a78eeda9fe8cc2b4 Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sat, 27 Dec 2025 09:44:33 -0600 Subject: [PATCH 01/11] add advancement stuff to the API module --- Package.swift | 4 + Sources/API/ChatColor.swift | 84 +++++++++++++++++++ Sources/API/advancement/Advancement.swift | 5 ++ .../API/advancement/AdvancementDisplay.swift | 53 ++++++++++++ .../advancement/AdvancementDisplayType.swift | 20 +++++ .../API/advancement/AdvancementProgress.swift | 60 +++++++++++++ .../advancement/AdvancementRequirement.swift | 5 ++ .../advancement/AdvancementRequirements.swift | 4 + 8 files changed, 235 insertions(+) create mode 100644 Sources/API/ChatColor.swift create mode 100644 Sources/API/advancement/Advancement.swift create mode 100644 Sources/API/advancement/AdvancementDisplay.swift create mode 100644 Sources/API/advancement/AdvancementDisplayType.swift create mode 100644 Sources/API/advancement/AdvancementProgress.swift create mode 100644 Sources/API/advancement/AdvancementRequirement.swift create mode 100644 Sources/API/advancement/AdvancementRequirements.swift diff --git a/Package.swift b/Package.swift index ca0ff4cc..03d7c5d0 100644 --- a/Package.swift +++ b/Package.swift @@ -45,6 +45,10 @@ let package = Package( ] ), + .target( + name: "API" + ), + .target( name: "MinecraftUtilities", dependencies: [ diff --git a/Sources/API/ChatColor.swift b/Sources/API/ChatColor.swift new file mode 100644 index 00000000..1e830d46 --- /dev/null +++ b/Sources/API/ChatColor.swift @@ -0,0 +1,84 @@ + +public enum ChatColor: String, CaseIterable, Sendable { + /// The special character that prefixes all chat color codes. + case specialChar + + case bold + case italic + case magic + case reset + case strikethrough + case underline + + case aqua + case black + case blue + case darkAqua + case darkBlue + case darkGray + case darkGreen + case darkPurple + case darkRed + case gold + case gray + case green + case lightPurple + case red + case white + case yellow +} + +// MARK: Char +extension ChatColor { + // TODO: support +} + +// MARK: Is format +extension ChatColor { + /// Whether this is a format code. + public var isFormat: Bool { + switch self { + case .specialChar, .bold, .italic, .magic, .reset, .strikethrough, .underline: + true + default: + false + } + } +} + +// MARK: Is color +extension ChatColor { + /// Whether this is a color code. + public var isColor: Bool { + !isFormat + } +} + +// MARK: Strip +extension ChatColor { + /// Strips the given input of all color codes. + /// + /// - Returns: A copy of the input excluding any coloring. + public static func strip(_ input: String) -> String { + // TODO: implement + return input + } +} + +// MARK: Translate +extension ChatColor { + /// Copies and translates the input using a color code character. + /// + /// - Parameters: + /// - char: Color code character to replace. Example: `&`. + /// - input: Text you want to translate using the given color code. + /// + /// - Warning: The color code character will only be replaced if it is immediately followed by 0-9, A-F, a-f, K-O, k-o, R or r. + public static func translate( + char: Character = "&", + input: String + ) -> String { + // TODO: implement + return input + } +} \ No newline at end of file diff --git a/Sources/API/advancement/Advancement.swift b/Sources/API/advancement/Advancement.swift new file mode 100644 index 00000000..1266dd2d --- /dev/null +++ b/Sources/API/advancement/Advancement.swift @@ -0,0 +1,5 @@ + +public struct Advancement: Sendable { + public let criteria:[String] + public let requirements:AdvancementRequirements +} \ No newline at end of file diff --git a/Sources/API/advancement/AdvancementDisplay.swift b/Sources/API/advancement/AdvancementDisplay.swift new file mode 100644 index 00000000..11091d3d --- /dev/null +++ b/Sources/API/advancement/AdvancementDisplay.swift @@ -0,0 +1,53 @@ + +/// Information about how an advancement is displayed. +public struct AdvancementDisplay: Sendable { + /// The X position of the advancement in the advancement screen. + public let x:Float + + /// The Y position of the advancement in the advancement screen. + public let y:Float + + /// Display type for the advancement. + public let type:AdvancementDisplayType + + /// Bit-packed boolean values. + var _flags:Flags.RawValue + + /// The `ItemStack` that is shown for the advancement. + //public let icon:ItemStack // TODO: support + + /// Title of the advancement without color codes. + public let title:String + + /// Description of the advancement without color codes. + public let description:String +} + +// MARK: Flags +extension AdvancementDisplay { + enum Flags: UInt8, Sendable { + case shouldShowToast = 1 + case shouldAnnounceChat = 2 + case isHidden = 4 + } + + func isFlag(_ flag: Flags) -> Bool { + _flags & flag.rawValue != 0 + } + + /// Whether to show a toast to the player when the advancement is completed. + public var shouldShowToast: Bool { + isFlag(.shouldShowToast) + } + + /// Whether to announce in the chat when the advancement is completed. + public var shouldAnnounceChat: Bool { + isFlag(.shouldAnnounceChat) + } + + /// Whether to hide the advancement and all its children from the advancement screen until the advancement has been completed. + /// Has no effect on root advancements, but still affects all their children. + public var isHidden: Bool { + isFlag(.isHidden) + } +} \ No newline at end of file diff --git a/Sources/API/advancement/AdvancementDisplayType.swift b/Sources/API/advancement/AdvancementDisplayType.swift new file mode 100644 index 00000000..99796c61 --- /dev/null +++ b/Sources/API/advancement/AdvancementDisplayType.swift @@ -0,0 +1,20 @@ + +public enum AdvancementDisplayType: String, CaseIterable, Sendable { + /// Challenge icons have a stylised icon frame. + case challenge + + /// Goal icons have a rounded icon frame. + case goal + + /// Normal icons have a square icon frame. + case normal +} + +// MARK: ChatColor +extension AdvancementDisplayType { + /// The `ChatColor` used by Minecraft for this advancement. + public var chatColor: ChatColor { + // TODO: fix + .gold + } +} \ No newline at end of file diff --git a/Sources/API/advancement/AdvancementProgress.swift b/Sources/API/advancement/AdvancementProgress.swift new file mode 100644 index 00000000..871fcab1 --- /dev/null +++ b/Sources/API/advancement/AdvancementProgress.swift @@ -0,0 +1,60 @@ + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +/// Status of an advancement for a player. +public struct AdvancementProgress: Sendable { + /// Criteria that has been awarded. + var _awardedCriteria:[String:Date] + + /// Criteria that has not been awarded. + var _remainingCriteria:[String] +} + +// MARK: Criteria +extension AdvancementProgress { + public var awardedCriteria: Dictionary { + _read { + yield _awardedCriteria + } + } + + /// - Returns: the `Date` the specified criteria was awarded. + public func dateAwardedForCriteria(_ criteria: String) -> Date? { + return _awardedCriteria[criteria] + } + + /// Marks the specified criteria as awarded at the current time. + /// + /// - Returns: `true` if awarded; `false` if criteria does not exist or already awarded. + @discardableResult + public mutating func awardCriteria(_ criteria: String) -> Bool { + if awardedCriteria[criteria] != nil { + return false + } + _awardedCriteria[criteria] = Date.now + return true + } + + /// Marks the specified criteria as uncompleted. + /// + /// - Returns: `true` if removed; `false` if criteria does not exist or not awarded. + public mutating func revokeCriteria(_ criteria: String) -> Bool { + if _awardedCriteria[criteria] == nil { + return false + } + _awardedCriteria[criteria] = nil + return true + } +} + +// MARK: Awarded Criteria +extension AdvancementProgress { + struct AwardedCriteria: Sendable { + let id:String + let timestamp:Date + } +} \ No newline at end of file diff --git a/Sources/API/advancement/AdvancementRequirement.swift b/Sources/API/advancement/AdvancementRequirement.swift new file mode 100644 index 00000000..e0dedbdd --- /dev/null +++ b/Sources/API/advancement/AdvancementRequirement.swift @@ -0,0 +1,5 @@ + +public struct AdvancementRequirement: Sendable { + public let requiredCriteria:[String] + public let isStrict:Bool +} \ No newline at end of file diff --git a/Sources/API/advancement/AdvancementRequirements.swift b/Sources/API/advancement/AdvancementRequirements.swift new file mode 100644 index 00000000..7e35fb72 --- /dev/null +++ b/Sources/API/advancement/AdvancementRequirements.swift @@ -0,0 +1,4 @@ + +public struct AdvancementRequirements: Sendable { + public let requirements:[AdvancementRequirement] +} \ No newline at end of file From 4f3e34c817f66adf7344cd5225180836fcd39b4d Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sat, 27 Dec 2025 10:48:07 -0600 Subject: [PATCH 02/11] add attributes to the API module --- Sources/API/attribute/Attribute.swift | 126 ++++++++++++++++++ Sources/API/attribute/AttributeInstance.swift | 69 ++++++++++ Sources/API/attribute/AttributeModifier.swift | 23 ++++ .../AttributeModifierOperation.swift | 11 ++ Sources/API/inventory/EquipmentSlot.swift | 24 ++++ .../API/inventory/EquipmentSlotGroup.swift | 21 +++ 6 files changed, 274 insertions(+) create mode 100644 Sources/API/attribute/Attribute.swift create mode 100644 Sources/API/attribute/AttributeInstance.swift create mode 100644 Sources/API/attribute/AttributeModifier.swift create mode 100644 Sources/API/attribute/AttributeModifierOperation.swift create mode 100644 Sources/API/inventory/EquipmentSlot.swift create mode 100644 Sources/API/inventory/EquipmentSlotGroup.swift diff --git a/Sources/API/attribute/Attribute.swift b/Sources/API/attribute/Attribute.swift new file mode 100644 index 00000000..df197953 --- /dev/null +++ b/Sources/API/attribute/Attribute.swift @@ -0,0 +1,126 @@ + +/// Unique attribute. +public struct Attribute: Sendable { + public let id:String + public let defaultValue:Double +} + +// MARK: Defaults +extension Attribute { + // TODO: implement default values for the default attributes + + private static func get( + _ id: String, + defaultValue: Double = 0 + ) -> Self { + Self( + id: id, + defaultValue: defaultValue + ) + } + + /// Armor bonus of an `Entity`. + public static let armor = get("minecraft.armor") + + /// Armor durability bonus of an `Entity`. + public static let armorToughness = get("minecraft.armorToughness") + + /// Attack damage of an `Entity`. + public static let attackDamage = get("minecraft.attackDamage") + + /// Attack knockback of an `Entity`. + public static let attackKnockback = get("minecraft.attackKnockback") + + /// Attack speed of an `Entity`. + public static let attackSpeed = get("minecraft.attackSpeed") + + /// Block break speed of a `Player`. + public static let blockBreakSpeed = get("minecraft.blockBreakSpeed") + + /// Block reach distance of a `Player`. + public static let blockInteractionRange = get("minecraft.blockInteractionRange") + + /// Duration, in ticks, an entity remains burning after ignition. + public static let burningTime = get("minecraft.burningTime") + + /// Distance at which the camera is placed away. + public static let cameraDistance = get("minecraft.cameraDistance") + + /// Entity reach distance of a `Player`. + public static let entityInteractionRange = get("minecraft.entityInteractionRange") + + /// Resistance of an `Entity` to knockback from explosions. + public static let explosionKnockbackResistance = get("minecraft.explosionKnockbackResistance") + + /// Fall damage multiplier of an `Entity`. + public static let fallDamageMultiplier = get("minecraft.fallDamageMultiplier") + + /// Flying speed of an `Entity`. + public static let flyingSpeed = get("minecraft.flyingSpeed") + + /// Range at which an `Entity` will follow others. + public static let followRange = get("minecraft.followRange") + + /// Gravity applies to an `Entity`. + public static let gravity = get("minecraft.gravity") + + /// Strength an `Entity` will jump. + public static let jumpStrength = get("minecraft.jumpStrength") + + /// Resistance of an `Entity` to knockback. + public static let knockbackResistance = get("minecraft.knockbackResistance") + + /// Luck bonus of an `Entity`. + public static let luck = get("minecraft.luck") + + /// Maximum absorption of an `Entity.` + public static let maxAbsorption = get("minecraft.maxAbsorption") + + /// Maximum health of an `Entity`. + public static let maxHealth = get("minecraft.maxHealth") + + /// Minving speed for correct tools. + public static let miningEfficiency = get("minecraft.miningEfficiency") + + /// Movement speed of an `Entity` through difficult terrain. + public static let movementEfficiency = get("minecraft.movementEfficiency") + + /// Movement speed of an `Entity`. + public static let movementSpeed = get("minecraft.movementSpeed") + + /// Oxygen use underwater. + public static let oxygenBonus = get("minecraft.oxygenBonus") + + /// Distance an `Entity` can fall without damage. + public static let safeFallDistance = get("minecraft.safeFallDistance") + + /// Relative scale of an `Entity`. + public static let scale = get("minecraft.scale") + + /// Sneaking speed of an `Entity`. + public static let sneakingSpeed = get("minecraft.sneakingSpeed") + + /// Chance of a `Zombie` to spawn reinforcements. + public static let spawnReinforcements = get("minecraft.spawnReinforcements") + + /// Height which an `Entity` can walk over. + public static let stepHeight = get("minecraft.stepHeight") + + /// Mining speed of an `Entity` underwater. + public static let submergedMiningSpeed = get("minecraft.submergedMiningSpeed") + + /// Sweeping damage. + public static let sweepingDamageRatio = get("minecraft.sweepingDamageRatio") + + /// Range mobs will be tempted by items. + public static let temptRange = get("minecraft.temptRange") + + /// Movement speed of an `Entity` through water. + public static let waterMovementEfficiency = get("minecraft.waterMovementEfficiency") + + /// Waypoint transmission range. + public static let waypointTransmitRange = get("minecraft.waypointTransmitRange") + + /// Waypoint receive range. + public static let waypointReceiveRange = get("minecraft.waypointReceiveRange") +} \ No newline at end of file diff --git a/Sources/API/attribute/AttributeInstance.swift b/Sources/API/attribute/AttributeInstance.swift new file mode 100644 index 00000000..217e7c74 --- /dev/null +++ b/Sources/API/attribute/AttributeInstance.swift @@ -0,0 +1,69 @@ + +/// Mutable instance of an attribute with its current modifiers and values. +public struct AttributeInstance: Sendable { + + /// The `Attribute` pertaining to this instance. + public let attribute:Attribute + + /// Base value of this instance before modifiers are applied. + public var baseValue: Double { + didSet { + _value = calculateValue() + } + } + + /// Value of this instance after all associated modifiers have been applied. + var _value:Double + + /// All modifiers present on this instance. + var _modifiers:Set +} + +// MARK: Value +extension AttributeInstance { + /// The default value of the `attribute`. + public var defaultValue: Double { + _read { + yield attribute.defaultValue + } + } + + /// Calculates the `_value` taking into account the `baseValue` and all modifiers. + private func calculateValue() -> Double { + return baseValue // TODO: fix + } +} + +// MARK: Modifiers +extension AttributeInstance { + /// All modifiers present on this instance. + public var modifiers: Set { + _read { + yield _modifiers + } + } + + /// Adds a modifier to this instance. + /// + /// - Complexity: O(1). + /// + /// - Warning: This method has no effect if a modifier of equal `id` is already present. + /// + /// - Returns: (`true`, `newMember`) if `newMember` was not contained in the set. + /// If an element equal to `newMember` was already contained in the set, the method returns (`false`, `oldMember`), where `oldMember` is the element that was equal to `newMember`. + /// In some cases, `oldMember` may be distinguishable from `newMember` by identity comparison or some other means. + @discardableResult + public mutating func addModifier(_ modifier: AttributeModifier) -> (inserted: Bool, memberAfterInsert: AttributeModifier) { + _modifiers.insert(modifier) + } + + /// Removes a modifier from this instance. + /// + /// - Complexity: O(1). + /// + /// - Returns: The modifier of the `modifier` parameter if it is present; otherwise, `nil`. + @discardableResult + public mutating func removeModifier(_ modifier: AttributeModifier) -> AttributeModifier? { + return _modifiers.remove(modifier) + } +} \ No newline at end of file diff --git a/Sources/API/attribute/AttributeModifier.swift b/Sources/API/attribute/AttributeModifier.swift new file mode 100644 index 00000000..94ef5f6c --- /dev/null +++ b/Sources/API/attribute/AttributeModifier.swift @@ -0,0 +1,23 @@ + +public struct AttributeModifier: Sendable { + public let id:String + + /// Amount this modifier will apply its `operation`. + public let amount:Double + + /// Name of this modifier. + public let name:String + + /// `AttributeModifierOperation` this modifier will apply. + public let operation:AttributeModifierOperation + + /// The `EquipmentSlotGroup` this modifier is active on. + public let slotGroup:EquipmentSlotGroup +} + +// MARK: Hashable +extension AttributeModifier: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } +} \ No newline at end of file diff --git a/Sources/API/attribute/AttributeModifierOperation.swift b/Sources/API/attribute/AttributeModifierOperation.swift new file mode 100644 index 00000000..72fbf0aa --- /dev/null +++ b/Sources/API/attribute/AttributeModifierOperation.swift @@ -0,0 +1,11 @@ + +public enum AttributeModifierOperation: CaseIterable, Hashable, Sendable { + /// Adds (or subtracts) the specified amount to the base value. + case addNumber + + /// Adds this scalar of amount to the base value. + case addScalar + + /// Multiply amount by this value, after adding 1 to it. + case multiplyScalar1 +} \ No newline at end of file diff --git a/Sources/API/inventory/EquipmentSlot.swift b/Sources/API/inventory/EquipmentSlot.swift new file mode 100644 index 00000000..79af217e --- /dev/null +++ b/Sources/API/inventory/EquipmentSlot.swift @@ -0,0 +1,24 @@ + +public enum EquipmentSlot: CaseIterable, Sendable { + /// Only for certain entities such as horses and wolves. + case body + + case chest + case feet + case hand + case head + case legs + case offhand + + /// Only for certain entities such as horses and pigs. + case saddle +} + +// MARK: Group +extension EquipmentSlot { + /// The `EquipmentSlotGroup` corresponding to this slot. + public var group: EquipmentSlotGroup { + // TODO: fix + .any + } +} \ No newline at end of file diff --git a/Sources/API/inventory/EquipmentSlotGroup.swift b/Sources/API/inventory/EquipmentSlotGroup.swift new file mode 100644 index 00000000..c56ed1c1 --- /dev/null +++ b/Sources/API/inventory/EquipmentSlotGroup.swift @@ -0,0 +1,21 @@ + +public enum EquipmentSlotGroup: CaseIterable, Hashable, Sendable { + case any + case armor + case chest + case feet + case hand + case head + case legs + case mainhand + case offhand + case saddle +} + +// MARK: Test +extension EquipmentSlotGroup { + public func test(_ slot: EquipmentSlot) -> Bool { + // TODO: fix + false + } +} \ No newline at end of file From 976d8c546dbef302326db920960fffaa42707ae1 Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sat, 27 Dec 2025 12:40:49 -0600 Subject: [PATCH 03/11] added API material, enchantment and item stack (+ some defaults) --- Sources/API/Material+Defaults.swift | 80 +++++++++++ Sources/API/Material.swift | 143 +++++++++++++++++++ Sources/API/enchantment/Enchantment.swift | 166 ++++++++++++++++++++++ Sources/API/inventory/ItemStack.swift | 38 +++++ 4 files changed, 427 insertions(+) create mode 100644 Sources/API/Material+Defaults.swift create mode 100644 Sources/API/Material.swift create mode 100644 Sources/API/enchantment/Enchantment.swift create mode 100644 Sources/API/inventory/ItemStack.swift diff --git a/Sources/API/Material+Defaults.swift b/Sources/API/Material+Defaults.swift new file mode 100644 index 00000000..5de2bc15 --- /dev/null +++ b/Sources/API/Material+Defaults.swift @@ -0,0 +1,80 @@ + +// TODO: finish +extension Material { + + // TODO: fix default values + private static func get( + _ id: String, + equipmentSlot: EquipmentSlot = .hand, + blastResistance: Float = 0, + hardness: Float = 0, + slipperiness: Float = 0.6, + flags: Flags.RawValue = 0 + ) -> Self { + Self( + id: id, + equipmentSlot: equipmentSlot, + blastResistance: blastResistance, + hardness: hardness, + slipperiness: slipperiness, + flags: flags + ) + } +} + +// MARK: A +extension Material { + public static let acaciaBoat = get("minecraft.acaciaBoat") + public static let acaciaButton = get("minecraft.acaciaButton") + public static let acaciaChestBoat = get("minecraft.acaciaChestBoat") + public static let acaciaDoor = get("minecraft.acaciaDoor") + public static let acaciaFence = get("minecraft.acaciaFence") + public static let acaciaFenceGate = get("minecraft.acaciaFenceGate") + public static let acaciaHangingSign = get("minecraft.acaciaHangingSign") + public static let acaciaLeaves = get("minecraft.acaciaLeaves") + public static let acaciaLog = get("minecraft.acaciaLog") + public static let acaciaPlanks = get("minecraft.acaciaPlanks") + public static let acaciaPressurePlate = get("minecraft.acaciaPressurePlate") + public static let acaciaSapling = get("minecraft.acaciaSapling") + public static let acaciaShelf = get("minecraft.acaciaShelf") + public static let acaciaSign = get("minecraft.acaciaSign") + public static let acaciaSlab = get("minecraft.acaciaSlab") + public static let acaciaStairs = get("minecraft.acaciaStairs") + public static let acaciaTrapdoor = get("minecraft.acaciaTrapdoor") + public static let acaciaWallHangingSign = get("minecraft.acaciaWallHangingSign") + public static let acaciaWallSign = get("minecraft.acaciaWallSign") + public static let acaciaWood = get("minecraft.acaciaWood") + + public static let activatorRail = get("minecraft.activatorRail") + public static let air = get("minecraft.air") + public static let allaySpawnEgg = get("minecraft.allaySpawnEgg") + public static let allium = get("minecraft.allium") + public static let amethystBlock = get("minecraft.amethystBlock") + public static let amethystCluster = get("minecraft.amethystCluster") + public static let amethystShard = get("minecraft.amethystShard") + public static let ancientDebris = get("minecraft.ancientDebris") + public static let andesite = get("minecraft.andesite") + public static let andesiteSlab = get("minecraft.andesiteSlab") + public static let andesiteStairs = get("minecraft.andesiteStairs") + public static let andesiteWall = get("minecraft.andesiteWall") + public static let anglerPotterySherd = get("minecraft.anglerPotterySherd") + public static let anvil = get("minecraft.anvil") + public static let apple = get("minecraft.apple") + public static let archeryPotterySherd = get("minecraft.archeryPotterySherd") + public static let armadilloScute = get("minecraft.armadilloScute") + public static let armadilloSpawnEgg = get("minecraft.armadilloSpawnEgg") + public static let armorStand = get("minecraft.armorStand") + public static let armsUpPotterySherd = get("minecraft.armsUpPotterySherd") + public static let arrow = get("minecraft.arrow") + public static let attachedMelonStem = get("minecraft.attachedMelonStem") + public static let attachedPumpkinStem = get("minecraft.attachedPumpkinStem") + public static let axolotlBucket = get("minecraft.axolotlBucket") + public static let axolotlSpawnEgg = get("minecraft.axolotlSpawnEgg") + public static let azalea = get("minecraft.azalea") + public static let azaleaLeaves = get("minecraft.azaleaLeaves") + public static let azureBluet = get("minecraft.azureBluet") +} + +// MARK: B + +// MARK: C \ No newline at end of file diff --git a/Sources/API/Material.swift b/Sources/API/Material.swift new file mode 100644 index 00000000..9e9201b3 --- /dev/null +++ b/Sources/API/Material.swift @@ -0,0 +1,143 @@ + +public struct Material: Sendable { + public let id:String + + /// Best suitable equipment slot for this material. For most items this will be `hand`. + public let equipmentSlot:EquipmentSlot + + /// Value representing its resistance to explosions. + /// + /// Used in explosions to calculate whether a block should be broken. + /// + /// - Warning: Only available when `isBlock`. + public let blastResistance:Float + + /// Value representing the strength of the block. + /// + /// Used to calculate the time required to break each block. + /// + /// - Note: Negative hardness means the block is unbreakable in survial and adventure mode. + /// + /// - Warning: Only available when `isBlock`. + /// + /// - Wiki: https://minecraft.wiki/w/Module:Hardness_values + public let hardness:Float + + /// Value representing how 'slippery' the block is. + /// Blocks with higher slipperiness, like `ice` can be slid on further by entities. + /// + /// Most blocks have a default slipperiness of `0.6`. + /// + /// - Warning: Only available when `isBlock`. + public let slipperiness:Float + + var flags:Flags.RawValue +} + +extension Material { + /// If this material is air (`id` is equal to `minecraft.air`). + public var isAir: Bool { + id == "minecraft.air" + } +} + +// MARK: Flags +extension Material { + enum Flags: UInt16, Sendable { + case block = 1 + case burnable = 2 + case compostable = 4 + case edible = 8 + case flammable = 16 + case fuel = 32 + case gravity = 64 + case interactable = 128 + case item = 256 + case occludes = 512 + case record = 1024 + case solid = 2048 + } + + private func isFlag(_ flag: Flags) -> Bool { + flags & flag.rawValue > 0 + } + + /// If this material is affected by gravity. + public var hasGravity: Bool { + isFlag(.gravity) + } + + /// If this material is a placable block. + public var isBlock: Bool { + isFlag(.block) + } + + /// If this material is a block and can burn away. + public var isBurnable: Bool { + isBlock && isFlag(.burnable) + } + + /// If this material is compostable (can be inserted into a composter). + public var isCompostable: Bool { + isFlag(.compostable) + } + + /// If this material is edible. + public var isEdible: Bool { + isFlag(.edible) + } + + /// If this material is a block and can catch fire. + public var isFlammable: Bool { + isBlock && isFlag(.flammable) + } + + /// If this material can be used as fuel in a furnace. + public var isFuel: Bool { + isFlag(.fuel) + } + + /// If this material can be interacted with. + /// + /// - Note: Interactability of some materials may be dependant on their state. + /// + /// - Returns: `true` if there is at least one state in which additional interact handling is performed for the material. + public var isInteractable: Bool { + isFlag(.interactable) + } + + /// If this material is an obtainable item. + public var isItem: Bool { + isFlag(.item) + } + + /// If this material is a block and occludes light in the lighting engine. + /// + /// Most full blocks will occlude light. + /// Non-full blocks are not occluding (anvils, chests, tall grass, stairs, etc.) nor are specific full blocks such as barriers or spawners which block light despite their texture. + /// + /// An occluding block with have the following effects (list is inconclusive; see full list [here](https://minecraft.wiki/w/Opacity)): + /// - chests cannot be opened if an occluding block is above it + /// - mobs cannot spawn inside of occluding blocks + /// - only occluding blocks can be 'powered' + public var isOccluding: Bool { + isBlock && isFlag(.occludes) + } + + /// If this material is a playable music disk. + public var isRecord: Bool { + isFlag(.record) + } + + /// If this material is a block and solid (can be built upon). + public var isSolid: Bool { + isBlock && isFlag(.solid) + } +} + +// MARK: Hashable +extension Material: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } +} \ No newline at end of file diff --git a/Sources/API/enchantment/Enchantment.swift b/Sources/API/enchantment/Enchantment.swift new file mode 100644 index 00000000..f4fd7fd7 --- /dev/null +++ b/Sources/API/enchantment/Enchantment.swift @@ -0,0 +1,166 @@ + +public struct Enchantment: Sendable { + public let id:String + public let name:String + public let maxLevel:Int + + public init( + id: String, + name: String, + maxLevel: Int + ) { + self.id = id + self.name = name + self.maxLevel = maxLevel + } +} + +// MARK: Hashable +extension Enchantment: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } +} + +// MARK: Defaults +extension Enchantment { + public static func create( + _ id: String, + maxLevel: Int + ) -> Self { + Self( + id: id, + name: String(stringLiteral: id), + maxLevel: maxLevel + ) + } + + /// Increases the speed an `Entity` mines underwater. + public static let aquaAffinity = create("minecraft.aquaAffinity", maxLevel: 1) + + /// Increases damage against arthropod entities. + public static let baneOfArthropods = create("minecraft.baneOfArthropods", maxLevel: 5) + + /// Item cannot be removed. + public static let bindingCurse = create("minecraft.bindingCurse", maxLevel: 1) + + /// Provides protection against explosive damage. + public static let blastProtection = create("minecraft.blastProtection", maxLevel: 4) + + /// Reduces armor effectiveness against maces. + public static let breach = create("minecraft.breach", maxLevel: 4) + + /// Strikes lightning when a mob is hit with a trident if conditions are stormy. + public static let channeling = create("minecraft.channeling", maxLevel: 1) + + /// Increases fall damage of maces. + public static let density = create("minecraft.density", maxLevel: 5) + + /// Increases walking speed while in water. + public static let depthStrider = create("minecraft.depthStrider", maxLevel: 3) + + /// Reduces the duration of destroying of blocks. + public static let efficiency = create("minecraft.efficiency", maxLevel: 5) + + /// Provides protection against fall damage. + public static let featherFalling = create("minecraft.featherFalling", maxLevel: 4) + + /// Chance to set the victim on fire when hit. + public static let fireAspect = create("minecraft.fireAspect", maxLevel: 2) + + /// Provides protection against fire damage. + public static let fireProtection = create("minecraft.fireProtection", maxLevel: 4) + + /// Sets the victim on fire when hit by an arrow shot from a bow. + public static let flame = create("minecraft.flame", maxLevel: 1) + + /// Chance of gaining extra loot when destroying blocks. + public static let fortune = create("minecraft.fortune", maxLevel: 3) + + /// Freezes still water adjacent to ice the `Entity` is walking on. + public static let frostWalker = create("minecraft.frostWalker", maxLevel: 2) + + /// Deals more damage to mobs that live in the ocean. + public static let impaling = create("minecraft.impaling", maxLevel: 5) + + /// Provides infinite arrows when shooting a bow. + public static let infinity = create("minecraft.infinity", maxLevel: 1) + + /// Damage to others will knock them back when hit. + public static let knockback = create("minecraft.knockback", maxLevel: 2) + + /// Chance of gaining extra loot when killing monsters. + public static let looting = create("minecraft.looting", maxLevel: 3) + + /// Causes a thrown trident to return to the thrower. + public static let loyalty = create("minecraft.loyalty", maxLevel: 3) + + /// Decreases chance of catching worthless junk. + public static let luckOfTheSea = create("minecraft.luckOfTheSea", maxLevel: 3) + + /// Lunges further forward when attacking. + public static let lunge = create("minecraft.lunge", maxLevel: 3) + + /// Increases rate of fish biting your hook. + public static let lure = create("minecraft.lure", maxLevel: 3) + + /// Repairs an item's durability when obtaining experience orbs. + public static let mending = create("minecraft.mending", maxLevel: 1) + + /// Shoot multiple arrows from crossbows. + public static let multishot = create("minecraft.multishot", maxLevel: 3) + + /// Crossbow projectiles pierce entities. + public static let piercing = create("minecraft.piercing", maxLevel: 5) + + /// Provides extra damage when shooting arrows from bows. + public static let power = create("minecraft.power", maxLevel: 5) + + /// Provides protection against projectile damage. + public static let projectileProtection = create("minecraft.projectileProtection", maxLevel: 4) + + /// Provides protection against environmental damage. + public static let protection = create("minecraft.protection", maxLevel: 4) + + /// Knockback the victim when hit by an arrow from a bow. + public static let punch = create("minecraft.punch", maxLevel: 2) + + /// Charges crossbows quicker. + public static let quickCharge = create("minecraft.quickCharge", maxLevel: 3) + + /// Decreases the rate of air loss when underwater. + public static let respiration = create("minecraft.respiration", maxLevel: 3) + + /// When raining, launches the player in the direction their trident is thrown. + public static let riptide = create("minecraft.riptide", maxLevel: 3) + + /// Increases damage against all targets. + public static let sharpness = create("minecraft.sharpness", maxLevel: 5) + + /// Allows blocks to drop themselves instead of fragments. + public static let silkTouch = create("minecraft.silkTouch", maxLevel: 1) + + /// increases damage against undead targets. + public static let smite = create("minecraft.smite", maxLevel: 5) + + /// Walk quicker on soul blocks. + public static let soulSpeed = create("minecraft.soulSpeed", maxLevel: 3) + + /// Increases damage against targets when using a sweep attack. + public static let sweepingEdge = create("minecraft.sweepingEdge", maxLevel: 3) + + /// Walk quicker while sneaking. + public static let swiftSneak = create("minecraft.swiftSneak", maxLevel: 3) + + /// Damages the attacker. + public static let thorns = create("minecraft.thorns", maxLevel: 4) + + /// Decreases the chance a tool loses durability. + public static let unbreaking = create("minecraft.unbreaking", maxLevel: 3) + + /// Item disappears instead of dropping. + public static let vanishingCurse = create("minecraft.vanishingCurse", maxLevel: 1) + + /// Emits wind burst upon hitting enemy. + public static let windBurst = create("minecraft.windBurst", maxLevel: 3) +} \ No newline at end of file diff --git a/Sources/API/inventory/ItemStack.swift b/Sources/API/inventory/ItemStack.swift new file mode 100644 index 00000000..9b67f7ba --- /dev/null +++ b/Sources/API/inventory/ItemStack.swift @@ -0,0 +1,38 @@ + +public struct ItemStack: Sendable { + + /// Number of items in this item stack. + public var amount:Int + + /// Dictionary containing all enchantments and their levels on this item stack. + public var enchantments:[Enchantment:Int] + + /// The `Material` of this item. + public var material:Material +} + +// MARK: Enchantments +extension ItemStack { + /// Removes all enchantments from this `ItemStack`. + public mutating func removeEnchantments() { + enchantments.removeAll(keepingCapacity: true) + } + + /// - Returns: level of the specified enchantment on this item stack. + public func enchantmentLevel(for enchantment: Enchantment) -> Int { + return enchantments[enchantment] ?? 0 + } + + /// - Returns: Whether this item stack contains the given enchantment. + public func contains(enchantment: Enchantment) -> Bool { + return enchantments[enchantment] != nil + } +} + +// MARK: Is similar +extension ItemStack { + /// - Returns: Whether the two item stacks are equal regardless of stack size (`amount`). + public func isSimilar(to itemStack: ItemStack) -> Bool { + return material == itemStack.material && enchantments == itemStack.enchantments + } +} \ No newline at end of file From 023c9e489d6aba4cb29ee2f15f64b2eb57d665b3 Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sat, 27 Dec 2025 16:22:54 -0600 Subject: [PATCH 04/11] added more stuff to the API module --- .../API/damage/DamageEffect+Defaults.swift | 20 ++ Sources/API/damage/DamageEffect.swift | 20 ++ Sources/API/damage/DamageType+Defaults.swift | 53 ++++ Sources/API/damage/DamageType.swift | 31 ++ .../damage/DeathMessageType+Defaults.swift | 11 + Sources/API/damage/DeathMessageType.swift | 15 + Sources/API/inventory/ItemFlag+Defaults.swift | 105 +++++++ Sources/API/inventory/ItemFlag.swift | 16 ++ .../API/inventory/ItemRarity+Defaults.swift | 14 + Sources/API/inventory/ItemRarity.swift | 15 + Sources/API/inventory/ItemStack.swift | 3 + Sources/API/inventory/meta/ItemMeta.swift | 52 ++++ .../{ => material}/Material+Defaults.swift | 0 Sources/API/{ => material}/Material.swift | 0 Sources/API/sound/Sound+Block.swift | 266 ++++++++++++++++++ Sources/API/sound/Sound+Defaults.swift | 52 ++++ Sources/API/sound/Sound.swift | 21 ++ 17 files changed, 694 insertions(+) create mode 100644 Sources/API/damage/DamageEffect+Defaults.swift create mode 100644 Sources/API/damage/DamageEffect.swift create mode 100644 Sources/API/damage/DamageType+Defaults.swift create mode 100644 Sources/API/damage/DamageType.swift create mode 100644 Sources/API/damage/DeathMessageType+Defaults.swift create mode 100644 Sources/API/damage/DeathMessageType.swift create mode 100644 Sources/API/inventory/ItemFlag+Defaults.swift create mode 100644 Sources/API/inventory/ItemFlag.swift create mode 100644 Sources/API/inventory/ItemRarity+Defaults.swift create mode 100644 Sources/API/inventory/ItemRarity.swift create mode 100644 Sources/API/inventory/meta/ItemMeta.swift rename Sources/API/{ => material}/Material+Defaults.swift (100%) rename Sources/API/{ => material}/Material.swift (100%) create mode 100644 Sources/API/sound/Sound+Block.swift create mode 100644 Sources/API/sound/Sound+Defaults.swift create mode 100644 Sources/API/sound/Sound.swift diff --git a/Sources/API/damage/DamageEffect+Defaults.swift b/Sources/API/damage/DamageEffect+Defaults.swift new file mode 100644 index 00000000..811d2289 --- /dev/null +++ b/Sources/API/damage/DamageEffect+Defaults.swift @@ -0,0 +1,20 @@ + +extension DamageEffect { + /// A single burn tick (fire, lava, etc.). + public static let burning = create("minecraft.burning") + + /// Drowning. + public static let drowning = create("minecraft.drowning") + + /// A single freeze tick (powder snow). + public static let freezing = create("minecraft.freezing") + + /// The default damage effect. + public static let hurt = create("minecraft.hurt") + + /// Poked by something (a berry bush). + public static let poking = create("minecraft.poking") + + /// Thorns. + public static let thorns = create("minecraft.thorns") +} \ No newline at end of file diff --git a/Sources/API/damage/DamageEffect.swift b/Sources/API/damage/DamageEffect.swift new file mode 100644 index 00000000..522ccd33 --- /dev/null +++ b/Sources/API/damage/DamageEffect.swift @@ -0,0 +1,20 @@ + +public struct DamageEffect: Sendable { + public let id:String + + /// Sound played for this `DamageEffect`. + public let sound:Sound +} + +// MARK: Create +extension DamageEffect { + public static func create( + _ id: String, + sound: Sound = Sound(id: "minecraft.unknown") + ) -> Self { + Self( + id: id, + sound: sound + ) + } +} \ No newline at end of file diff --git a/Sources/API/damage/DamageType+Defaults.swift b/Sources/API/damage/DamageType+Defaults.swift new file mode 100644 index 00000000..55b7077b --- /dev/null +++ b/Sources/API/damage/DamageType+Defaults.swift @@ -0,0 +1,53 @@ + +extension DamageType { + public static let arrow = create("minecraft.arrow") + public static let badRespawnPoint = create("minecraft.badRespawnPoint") + public static let cactus = create("minecraft.cactus") + public static let campfire = create("minecraft.campfire", damageEffect: .burning) + public static let cramming = create("minecraft.cramming") + public static let dragonBreath = create("minecraft.dragonBreath") + public static let drown = create("minecraft.drown", damageEffect: .drowning) + public static let dryOut = create("minecraft.dryOut") + public static let enderPearl = create("minecraft.enderPearl") + public static let explosion = create("minecraft.explosion") + public static let fall = create("minecraft.fall") + public static let fallingAnvil = create("minecraft.fallingAnvil") + public static let fallingBlock = create("minecraft.fallingBlock") + public static let fallingStalactite = create("minecraft.fallingStalactite") + public static let fireball = create("minecraft.fireball") + public static let fireworks = create("minecraft.fireworks") + public static let flyIntoWall = create("minecraft.flyIntoWall") + public static let freeze = create("minecraft.freeze", damageEffect: .freezing) + public static let generic = create("minecraft.generic") + public static let genericKill = create("minecraft.genericKill") + public static let hotFloor = create("minecraft.hotFloor") + public static let inFire = create("minecraft.inFire", damageEffect: .burning) + public static let inWall = create("minecraft.inWall") + public static let indirectMagic = create("minecraft.indirectMagic") + public static let lava = create("minecraft.lava", damageEffect: .burning) + public static let lightningBolt = create("minecraft.lightningBolt") + public static let maceSmash = create("minecraft.maceSmash") + public static let magic = create("minecraft.magic") + public static let mobAttack = create("minecraft.mobAttack") + public static let mobAttackNoAggro = create("minecraft.mobAttackNoAggro") + public static let mobProjectile = create("minecraft.mobProjectile") + public static let onFire = create("minecraft.onFire", damageEffect: .burning) + public static let outOfWorld = create("minecraft.outOfWorld") + public static let outsideBorder = create("minecraft.outsideBorder") + public static let playerAttack = create("minecraft.playerAttack") + public static let playerExplosion = create("minecraft.playerExplosion") + public static let sonicBoom = create("minecraft.sonicBoom") + public static let spear = create("minecraft.spear") + public static let spit = create("minecraft.spit") + public static let stalagmite = create("minecraft.stalagmite") + public static let starve = create("minecraft.starve") + public static let sting = create("minecraft.sting") + public static let sweetBerryBush = create("minecraft.sweetBerryBush", damageEffect: .poking) + public static let thorns = create("minecraft.thorns", damageEffect: .thorns) + public static let thrown = create("minecraft.thrown") + public static let trident = create("minecraft.trident") + public static let unattributedFireball = create("minecraft.unattributedFireball") + public static let windCharge = create("minecraft.windCharge") + public static let wither = create("minecraft.wither") + public static let witherSkull = create("minecraft.witherSkull") +} \ No newline at end of file diff --git a/Sources/API/damage/DamageType.swift b/Sources/API/damage/DamageType.swift new file mode 100644 index 00000000..4700bfa9 --- /dev/null +++ b/Sources/API/damage/DamageType.swift @@ -0,0 +1,31 @@ + +public struct DamageType: Sendable { + public let id:String + + /// Amount of hunger exhaustion caused by this damage type. + public let exhaustion:Float + + /// The `DamageEffect` for this damage type. + public let damageEffect:DamageEffect + + /// The `DeathMessageType` for this damage type. + public let deathMessageType:DeathMessageType +} + +// MARK: Create +extension DamageType { + // TODO: fix default values + public static func create( + _ id: String, + exhaustion: Float = 0, + damageEffect: DamageEffect = .hurt, + deathMessageType: DeathMessageType = .default + ) -> Self { + Self( + id: id, + exhaustion: exhaustion, + damageEffect: damageEffect, + deathMessageType: deathMessageType + ) + } +} \ No newline at end of file diff --git a/Sources/API/damage/DeathMessageType+Defaults.swift b/Sources/API/damage/DeathMessageType+Defaults.swift new file mode 100644 index 00000000..f4ce1614 --- /dev/null +++ b/Sources/API/damage/DeathMessageType+Defaults.swift @@ -0,0 +1,11 @@ + +extension DeathMessageType { + /// No special death message logic is applied + public static let `default` = create(id: "minecraft.default") + + // Shows a variant of fall damage death instead of a regular death message. + public static let fallVariants = create(id: "minecraft.fallVariants") + + /// Shows the intential game design death message instead of a regular death message. + public static let intentialGameDesign = create(id: "minecraft.intentialGameDesign") +} \ No newline at end of file diff --git a/Sources/API/damage/DeathMessageType.swift b/Sources/API/damage/DeathMessageType.swift new file mode 100644 index 00000000..c1b5716e --- /dev/null +++ b/Sources/API/damage/DeathMessageType.swift @@ -0,0 +1,15 @@ + +public struct DeathMessageType: Sendable { + public let id:String +} + +// MARK: Create +extension DeathMessageType { + public static func create( + id: String + ) -> Self { + Self( + id: id + ) + } +} \ No newline at end of file diff --git a/Sources/API/inventory/ItemFlag+Defaults.swift b/Sources/API/inventory/ItemFlag+Defaults.swift new file mode 100644 index 00000000..ae0e1d82 --- /dev/null +++ b/Sources/API/inventory/ItemFlag+Defaults.swift @@ -0,0 +1,105 @@ + +extension ItemFlag { + public static let hideAdditionalTooltip = create(id: "minecraft.hide.additionalTooltip") + public static let hideArmorTrim = create(id: "minecraft.hide.armorTrim") + public static let hideAttributeModifiers = create(id: "minecraft.hide.attributeModifiers") + public static let hideAttributes = create(id: "minecraft.hide.attributes") + public static let hideAxolotlVariant = create(id: "minecraft.hide.axolotlVariant") + public static let hideBannerPatterns = create(id: "minecraft.hide.bannerPatterns") + public static let hideBaseColor = create(id: "minecraft.hide.baseColor") + public static let hideBees = create(id: "minecraft.hide.bees") + public static let hideBlockEntityData = create(id: "minecraft.hide.blockEntityData") + public static let hideBlockState = create(id: "minecraft.hide.blockState") + public static let hideBlocksAttacks = create(id: "minecraft.hide.blocksAttacks") + public static let hideBreakSound = create(id: "minecraft.hide.breakSound") + public static let hideBucketEntityData = create(id: "minecraft.hide.bucketEntityData") + public static let hideBundleContents = create(id: "minecraft.hide.bundleContents") + public static let hideCanBreak = create(id: "minecraft.hide.canBreak") + public static let hideCanPlaceOn = create(id: "minecraft.hide.canPlaceOn") + public static let hideCatCollar = create(id: "minecraft.hide.catCollar") + public static let hideCatVariant = create(id: "minecraft.hide.catVariant") + public static let hideChargedProjectiles = create(id: "minecraft.hide.chargedProjectiles") + public static let hideChickenVariant = create(id: "minecraft.hide.chickenVariant") + public static let hideConsumable = create(id: "minecraft.hide.consumable") + public static let hideContainer = create(id: "minecraft.hide.container") + public static let hideCowVariant = create(id: "minecraft.hide.cowVariant") + public static let hideCreativeSlotLock = create(id: "minecraft.hide.creativeSlotLock") + public static let hideCustomData = create(id: "minecraft.hide.customData") + public static let hideCustomModelData = create(id: "minecraft.hide.customModelData") + public static let hideCustomName = create(id: "minecraft.hide.customName") + public static let hideDamage = create(id: "minecraft.hide.damage") + public static let hideDamageResistant = create(id: "minecraft.hide.damageResistant") + public static let hideDeathProtection = create(id: "minecraft.hide.deathProtection") + public static let hideDebugStickState = create(id: "minecraft.hide.debugStickState") + public static let hideDestroys = create(id: "minecraft.hide.destroys") + public static let hideDye = create(id: "minecraft.hide.dye") + public static let hideDyedColor = create(id: "minecraft.hide.dyedColor") + public static let hideEnchantable = create(id: "minecraft.hide.enchantable") + public static let hideEnchantmentGlintOverride = create(id: "minecraft.hide.enchantmentGlintOverride") + public static let hideEnchantments = create(id: "minecraft.hide.enchantments") + public static let hideEnchants = create(id: "minecraft.hide.enchants") + public static let hideEntityData = create(id: "minecraft.hide.entityData") + public static let hideEquippable = create(id: "minecraft.hide.equippable") + public static let hideFireworkExplosion = create(id: "minecraft.hide.fireworkExplosion") + public static let hideFireworks = create(id: "minecraft.hide.fireworks") + public static let hideFood = create(id: "minecraft.hide.food") + public static let hideFoxVariant = create(id: "minecraft.hide.foxVariant") + public static let hideFrogVariant = create(id: "minecraft.hide.frogVariant") + public static let hideGlider = create(id: "minecraft.hide.glider") + public static let hideHorseVariant = create(id: "minecraft.hide.horseVariant") + public static let hideInstrument = create(id: "minecraft.hide.instrument") + public static let hideIntangibleProjectile = create(id: "minecraft.hide.intangibleProjectile") + public static let hideItemModel = create(id: "minecraft.hide.itemModel") + public static let hideItemName = create(id: "minecraft.hide.itemName") + public static let hideJukeboxPlayable = create(id: "minecraft.hide.jukeboxPlayable") + public static let hideLlamaVariant = create(id: "minecraft.hide.llamaVariant") + public static let hideLock = create(id: "minecraft.hide.lock") + public static let hideLodestoneTracker = create(id: "minecraft.hide.lodestoneTracker") + public static let hideLore = create(id: "minecraft.hide.lore") + public static let hideMapColor = create(id: "minecraft.hide.map.color") + public static let hideMapDecorations = create(id: "minecraft.hide.map.decorations") + public static let hideMapId = create(id: "minecraft.hide.map.id") + public static let hideMapPostProcessing = create(id: "minecraft.hide.map.postProcessing") + public static let hideMaxDamage = create(id: "minecraft.hide.maxDamage") + public static let hideMaxStackSize = create(id: "minecraft.hide.maxStackSize") + public static let hideMooshroomVariant = create(id: "minecraft.hide.mooshroomVariant") + public static let hideNoteBlockSound = create(id: "minecraft.hide.noteBlockSound") + public static let hideOminousBottleAmplifier = create(id: "minecraft.hide.ominousBottleAmplifier") + public static let hidePaintingVariant = create(id: "minecraft.hide.paintingVariant") + public static let hideParrotVariant = create(id: "minecraft.hide.parrotVariant") + public static let hidePigVariant = create(id: "minecraft.hide.pigVariant") + public static let hidePlacedOn = create(id: "minecraft.hide.placedOn") + public static let hidePotDecorations = create(id: "minecraft.hide.potDecorations") + public static let hidePotionContents = create(id: "minecraft.hide.potionContents") + public static let hidePotionDurationScale = create(id: "minecraft.hide.potionDurationScale") + public static let hideProfile = create(id: "minecraft.hide.profile") + public static let hideProvidesBannerPatterns = create(id: "minecraft.hide.providesBannerPatterns") + public static let hideProvidesTrimMaterial = create(id: "minecraft.hide.providesTrimMaterial") + public static let hideRabbitVariant = create(id: "minecraft.hide.rabbitVariant") + public static let hideRarity = create(id: "minecraft.hide.rarity") + public static let hideRecipes = create(id: "minecraft.hide.recipes") + public static let hideRepairCost = create(id: "minecraft.hide.repairCost") + public static let hideRepairable = create(id: "minecraft.hide.repairable") + public static let hideSalmonSize = create(id: "minecraft.hide.salmonSize") + public static let hideSheepColor = create(id: "minecraft.hide.sheepColor") + public static let hideShulkerColor = create(id: "minecraft.hide.shulkerColor") + public static let hideStoredEnchantments = create(id: "minecraft.hide.storedEnchantments") + public static let hideSuspiciousStewEffects = create(id: "minecraft.hide.suspiciousStewEffects") + public static let hideTool = create(id: "minecraft.hide.tool") + public static let hideTooltipDisplay = create(id: "minecraft.hide.tooltipDisplay") + public static let hideTooltipStyle = create(id: "minecraft.hide.tooltipStyle") + public static let hideTrim = create(id: "minecraft.hide.trim") + public static let hideTropicalFishBaseColor = create(id: "minecraft.hide.tropicalFish.baseColor") + public static let hideTropicalFishPattern = create(id: "minecraft.hide.tropicalFish.pattern") + public static let hideTropicalFishPatternColor = create(id: "minecraft.hide.tropicalFish.patternColor") + public static let hideUnbreakable = create(id: "minecraft.hide.unbreakable") + public static let hideUseCooldown = create(id: "minecraft.hide.useCooldown") + public static let hideUseRemainder = create(id: "minecraft.hide.useRemainder") + public static let hideVillagerVariant = create(id: "minecraft.hide.villagerVariant") + public static let hideWeapon = create(id: "minecraft.hide.weapon") + public static let hideWolfCollar = create(id: "minecraft.hide.wolf.collar") + public static let hideWolfSoundVariant = create(id: "minecraft.hide.wolf.soundVariant") + public static let hideWolfVariant = create(id: "minecraft.hide.wolf.variant") + public static let hideWritableBookContent = create(id: "minecraft.hide.writableBookContent") + public static let hideWrittenBookContent = create(id: "minecraft.hide.writtenBookContent") +} \ No newline at end of file diff --git a/Sources/API/inventory/ItemFlag.swift b/Sources/API/inventory/ItemFlag.swift new file mode 100644 index 00000000..eccdd081 --- /dev/null +++ b/Sources/API/inventory/ItemFlag.swift @@ -0,0 +1,16 @@ + +/// Can hide some attributes from item stacks. +public struct ItemFlag: Hashable, Sendable { + public let id:String +} + +// MARK: Create +extension ItemFlag { + public static func create( + id: String + ) -> Self { + Self( + id: id + ) + } +} \ No newline at end of file diff --git a/Sources/API/inventory/ItemRarity+Defaults.swift b/Sources/API/inventory/ItemRarity+Defaults.swift new file mode 100644 index 00000000..a3506c13 --- /dev/null +++ b/Sources/API/inventory/ItemRarity+Defaults.swift @@ -0,0 +1,14 @@ + +extension ItemRarity { + /// White item name. + public static let common = create("minecraft.common") + + /// Light purple item name. + public static let epic = create("minecraft.epic") + + /// Aqua item name. + public static let rare = create("minecraft.rare") + + /// Yellow item name. + public static let uncommon = create("minecraft.uncommon") +} \ No newline at end of file diff --git a/Sources/API/inventory/ItemRarity.swift b/Sources/API/inventory/ItemRarity.swift new file mode 100644 index 00000000..cab59f5e --- /dev/null +++ b/Sources/API/inventory/ItemRarity.swift @@ -0,0 +1,15 @@ + +public struct ItemRarity: Sendable { + public let id:String +} + +// MARK: Create +extension ItemRarity { + public static func create( + _ id: String + ) -> Self { + Self( + id: id + ) + } +} \ No newline at end of file diff --git a/Sources/API/inventory/ItemStack.swift b/Sources/API/inventory/ItemStack.swift index 9b67f7ba..12496a5f 100644 --- a/Sources/API/inventory/ItemStack.swift +++ b/Sources/API/inventory/ItemStack.swift @@ -9,6 +9,9 @@ public struct ItemStack: Sendable { /// The `Material` of this item. public var material:Material + + /// The item's current meta. + public var meta:ItemMeta? } // MARK: Enchantments diff --git a/Sources/API/inventory/meta/ItemMeta.swift b/Sources/API/inventory/meta/ItemMeta.swift new file mode 100644 index 00000000..077f9f01 --- /dev/null +++ b/Sources/API/inventory/meta/ItemMeta.swift @@ -0,0 +1,52 @@ + +public struct ItemMeta: Sendable { + + /// The item's name. + /// Item name differs from display name in that it cannot be edited by an anvil, is not styled with italics, and does not show labels. + public var itemName:String? + + /// The item's display name. + public var displayName:String? + + /// The item's lore. + public var lore:[String] + + /// Sound to play when the item is broken. + public var breakSound:Sound? + + // Type of damage this item will deliver. + public let damageType:DamageType? + + /// The item's rarity. + public let rarity:ItemRarity? + + /// The item's current item flags. + public var itemFlags:Set +} + +// MARK: Booleans +extension ItemMeta { + public var hasDamageType: Bool { + damageType != nil + } + + public var hasDisplayName: Bool { + displayName != nil + } + + public var hasLore: Bool { + !lore.isEmpty + } + + public var hasRarity: Bool { + rarity != nil + } +} + +// MARK: Item Flags +extension ItemMeta { + /// - Returns: If the flag is present on this item. + public func hasItemFlag(_ flag: ItemFlag) -> Bool { + itemFlags.contains(flag) + } +} \ No newline at end of file diff --git a/Sources/API/Material+Defaults.swift b/Sources/API/material/Material+Defaults.swift similarity index 100% rename from Sources/API/Material+Defaults.swift rename to Sources/API/material/Material+Defaults.swift diff --git a/Sources/API/Material.swift b/Sources/API/material/Material.swift similarity index 100% rename from Sources/API/Material.swift rename to Sources/API/material/Material.swift diff --git a/Sources/API/sound/Sound+Block.swift b/Sources/API/sound/Sound+Block.swift new file mode 100644 index 00000000..6d6e9f13 --- /dev/null +++ b/Sources/API/sound/Sound+Block.swift @@ -0,0 +1,266 @@ + +// MARK: Amethyst +extension Sound { + public static let blockAmethystBlockBreak = create("minecraft.block.amethyst.block.break") + public static let blockAmethystBlockChime = create("minecraft.block.amethyst.block.chime") + public static let blockAmethystBlockFall = create("minecraft.block.amethyst.block.fall") + public static let blockAmethystBlockHit = create("minecraft.block.amethyst.block.hit") + public static let blockAmethystBlockPlace = create("minecraft.block.amethyst.block.place") + public static let blockAmethystBlockResonate = create("minecraft.block.amethyst.block.resonate") + public static let blockAmethystBlockStep = create("minecraft.block.amethyst.block.step") + public static let blockAmethystClusterBreak = create("minecraft.block.amethyst.cluster.break") + public static let blockAmethystClusterFall = create("minecraft.block.amethyst.cluster.fall") + public static let blockAmethystClusterHit = create("minecraft.block.amethyst.cluster.hit") + public static let blockAmethystClusterPlace = create("minecraft.block.amethyst.cluster.place") + public static let blockAmethystClusterStep = create("minecraft.block.amethyst.cluster.step") +} + +// TODO: finish + +// MARK: Ancient debris + +// MARK: Anvil + +// MARK: Azalea + +// MARK: Bamboo + +// MARK: Barrel + +// MARK: Basalt + +// MARK: Beacon + +// MARK: Beehive + +// MARK: Bell + +// MARK: Big dripleaf + +// MARK: Blast furnace + +// MARK: Bone + +// MARK: Brewing stand + +// MARK: Bubble + +// MARK: Cactus + +// MARK: Cake + +// MARK: Calcite + +// MARK: Campfire + +// MARK: Candle + +// MARK: Cave + +// MARK: Chain + +// MARK: Cherry + +// MARK: Chest + +// MARK: Chiseled + +// MARK: Chorus + +// MARK: Cobweb + +// MARK: Composter + +// MARK: Conduit + +// MARK: Copper + +// MARK: Coral + +// MARK: Crafter + +// MARK: Creaking + +// MARK: Crop + +// MARK: Deadbush + +// MARK: Decorated + +// MARK: Deepslate + +// MARK: Dispenser + +// MARK: Dried + +// MARK: Dripstone + +// MARK: Dry + +// MARK: Enchantment table + +// MARK: End + +// MARK: Ender + +// MARK: Eyeblossom + +// MARK: Fence + +// MARK: Fire + +// MARK: Flowering + +// MARK: Frog + +// MARK: Fungus + +// MARK: Furnace + +// MARK: Gilded + +// MARK: Grass + +// MARK: Gravel + +// MARK: Grindstone + +// MARK: Growing + +// MARK: Hanging + +// MARK: Heavy + +// MARK: Honey + +// MARK: Iron + +// MARK: Ladder + +// MARK: Lantern + +// MARK: Large + +// MARK: Lava + +// MARK: Leaf + +// MARK: Lever + +// MARK: Lily pad + +// MARK: Lodestone + +// MARK: Mangrove + +// MARK: Medium + +// MARK: Metal + +// MARK: Moss + +// MARK: Mud + +// MARK: Muddy + +// MARK: Nether + +// MARK: Netherite + +// MARK: Netherrack + +// MARK: Note + +// MARK: Nylium + +// MARK: Packed + +// MARK: Pale + +// MARK: Pink + +// MARK: Piston + +// MARK: Pointed + +// MARK: Polished + +// MARK: Portal + +// MARK: Powder snow + +// MARK: Pumpkin + +// MARK: Redstone + +// MARK: Resin + +// MARK: Respawn + +// MARK: Rooted + +// MARK: Roots + +// MARK: Sand + +// MARK: Scaffolding + +// MARK: Sculk + +// MARK: Shelf + +// MARK: Shroomlight + +// MARK: Shulker + +// MARK: Sign + +// MARK: Slime + +// MARK: Small dripleaf + +// MARK: Smithing table + +// MARK: Smoker + +// MARK: Sniffer + +// MARK: Snow + +// MARK: Soul + +// MARK: Spawner + +// MARK: Sponge + +// MARK: Spore + +// MARK: Stem + +// MARK: Stone + +// MARK: Suspicious + +// MARK: Sweet berry bush + +// MARK: Trial + +// MARK: Tripwire + +// MARK: Tuff + +// MARK: Vault + +// MARK: Vine + +// MARK: Wart + +// MARK: Weeping + +// MARK: Wet + +// MARK: Wood + +// MARK: Wooden + +// MARK: Wool \ No newline at end of file diff --git a/Sources/API/sound/Sound+Defaults.swift b/Sources/API/sound/Sound+Defaults.swift new file mode 100644 index 00000000..6c0d7f33 --- /dev/null +++ b/Sources/API/sound/Sound+Defaults.swift @@ -0,0 +1,52 @@ + +// MARK: Ambient +extension Sound { + public static let ambientBasaltDeltasAdditions = create("minecraft.ambient.basaltDeltas.additions") + public static let ambientBasaltDeltasLoop = create("minecraft.ambient.basaltDeltas.loop") + public static let ambientBasaltDeltasMood = create("minecraft.ambient.basaltDeltas.mood") + public static let ambientCave = create("minecraft.ambient.cave") + public static let ambientCrimsonForestAdditions = create("minecraft.ambient.crimsonForest.additions") + public static let ambientCrimsonForestLoop = create("minecraft.ambient.crimsonForest.loop") + public static let ambientCrimsonForestMood = create("minecraft.ambient.crimsonForest.mood") + public static let ambientNetherWastesAdditions = create("minecraft.ambient.netherWastes.additions") + public static let ambientNetherWastesLoop = create("minecraft.ambient.netherWastes.loop") + public static let ambientNetherWastesMood = create("minecraft.ambient.netherWastes.mood") + public static let ambientSoulSandValleyAdditions = create("minecraft.ambient.soulSandValley.additions") + public static let ambientSoulSandValleyLoop = create("minecraft.ambient.soulSandValley.loop") + public static let ambientSoulSandValleyMood = create("minecraft.ambient.soulSandValley.mood") + public static let ambientUnderwaterEnter = create("minecraft.ambient.underwater.enter") + public static let ambientUnderwaterExit = create("minecraft.ambient.underwater.exit") + public static let ambientUnderwaterLoop = create("minecraft.ambient.underwater.loop") + public static let ambientUnderwaterLoopAdditions = create("minecraft.ambient.underwater.loop.additions") + public static let ambientUnderwaterLoopAdditionsRare = create("minecraft.ambient.underwater.loop.additions.rare") + public static let ambientUnderwaterLoopAdditionsUltraRare = create("minecraft.ambient.underwater.loop.additions.ultraRare") + public static let ambientWarpedForestAdditions = create("minecraft.ambient.warpedForest.additions") + public static let ambientWarpedForestLoop = create("minecraft.ambient.warpedForest.loop") + public static let ambientWarpedForestMood = create("minecraft.ambient.warpedForest.mood") +} + +// MARK: Particle +extension Sound { + public static let particleSoulEscape = create("minecraft.particle.soulEscape") +} + +// MARK: UI +extension Sound { + public static let uiButtonClick = create("minecraft.ui.button.click") + public static let uiCartographyTableTakeResult = create("minecraft.ui.cartographyTable.takeResult") + public static let uiHUDBubblePop = create("minecraft.ui.hud.bubblePop") + public static let uiLoomSelectPattern = create("minecraft.ui.loom.selectPattern") + public static let uiLoomTakeResult = create("minecraft.ui.loom.takeResult") + public static let uiStonecutterSelectRecipe = create("minecraft.ui.stonecutter.selectRecipe") + public static let uiStonecutterTakeResult = create("minecraft.ui.stonecutter.takeResult") + public static let uiToastChallengeComplete = create("minecraft.ui.toast.challengeComplete") + public static let uiToastIn = create("minecraft.ui.toast.in") + public static let uiToastOut = create("minecraft.ui.toast.out") +} + +// MARK: Weather +extension Sound { + public static let weatherEndFlash = create("minecraft.weather.end.flash") + public static let weatherRain = create("minecraft.weather.rain") + public static let weatherRainAbove = create("minecraft.weather.above") +} \ No newline at end of file diff --git a/Sources/API/sound/Sound.swift b/Sources/API/sound/Sound.swift new file mode 100644 index 00000000..1ae02054 --- /dev/null +++ b/Sources/API/sound/Sound.swift @@ -0,0 +1,21 @@ + +public struct Sound: Sendable { + public let id:String + + public init( + id: String + ) { + self.id = id + } +} + +// MARK: Create +extension Sound { + public static func create( + _ id: String + ) -> Self { + Self( + id: id + ) + } +} \ No newline at end of file From 6546c1734d87ded856858a2164bf9e5cb61f2633 Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sat, 27 Dec 2025 16:34:28 -0600 Subject: [PATCH 05/11] added two ban structs to the API module --- Sources/API/ban/BanEntry.swift | 23 +++++++++++++++++++++++ Sources/API/ban/IpBanList.swift | 19 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 Sources/API/ban/BanEntry.swift create mode 100644 Sources/API/ban/IpBanList.swift diff --git a/Sources/API/ban/BanEntry.swift b/Sources/API/ban/BanEntry.swift new file mode 100644 index 00000000..ad3e7dd6 --- /dev/null +++ b/Sources/API/ban/BanEntry.swift @@ -0,0 +1,23 @@ + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +public struct BanEntry: Hashable, Sendable { + /// Creation date of the ban. + public var created:Date + + /// Expiration date of the ban. + public var expiration:Date? + + /// Target data of the ban. + public let target:T + + /// The reason for the ban. + public var reason:String? + + /// The source of ban such as a player, console, plugin, etc. + public var source:String? +} \ No newline at end of file diff --git a/Sources/API/ban/IpBanList.swift b/Sources/API/ban/IpBanList.swift new file mode 100644 index 00000000..68bf354d --- /dev/null +++ b/Sources/API/ban/IpBanList.swift @@ -0,0 +1,19 @@ + +/// List of banned IP addresses. +public struct IpBanList: Sendable { + public typealias Entry = BanEntry + + public var entries:Set +} + +extension IpBanList { + /// - Returns: Whether the specified IP is currently banned. + public func isBanned(_ ip: Entry) -> Bool { + entries.contains(ip) + } + + /// Removes the specified IP from the ban list. + public mutating func pardon(_ ip: Entry) { + entries.remove(ip) + } +} \ No newline at end of file From cde444d893ebbf35ef59f09a35cf7c8c34bc7400 Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sat, 27 Dec 2025 16:36:18 -0600 Subject: [PATCH 06/11] move default enchantments to its own file --- .../enchantment/Enchantment+Defaults.swift | 131 ++++++++++++++++++ Sources/API/enchantment/Enchantment.swift | 131 +----------------- 2 files changed, 132 insertions(+), 130 deletions(-) create mode 100644 Sources/API/enchantment/Enchantment+Defaults.swift diff --git a/Sources/API/enchantment/Enchantment+Defaults.swift b/Sources/API/enchantment/Enchantment+Defaults.swift new file mode 100644 index 00000000..ce547eee --- /dev/null +++ b/Sources/API/enchantment/Enchantment+Defaults.swift @@ -0,0 +1,131 @@ + +extension Enchantment { + /// Increases the speed an `Entity` mines underwater. + public static let aquaAffinity = create("minecraft.aquaAffinity", maxLevel: 1) + + /// Increases damage against arthropod entities. + public static let baneOfArthropods = create("minecraft.baneOfArthropods", maxLevel: 5) + + /// Item cannot be removed. + public static let bindingCurse = create("minecraft.bindingCurse", maxLevel: 1) + + /// Provides protection against explosive damage. + public static let blastProtection = create("minecraft.blastProtection", maxLevel: 4) + + /// Reduces armor effectiveness against maces. + public static let breach = create("minecraft.breach", maxLevel: 4) + + /// Strikes lightning when a mob is hit with a trident if conditions are stormy. + public static let channeling = create("minecraft.channeling", maxLevel: 1) + + /// Increases fall damage of maces. + public static let density = create("minecraft.density", maxLevel: 5) + + /// Increases walking speed while in water. + public static let depthStrider = create("minecraft.depthStrider", maxLevel: 3) + + /// Reduces the duration of destroying of blocks. + public static let efficiency = create("minecraft.efficiency", maxLevel: 5) + + /// Provides protection against fall damage. + public static let featherFalling = create("minecraft.featherFalling", maxLevel: 4) + + /// Chance to set the victim on fire when hit. + public static let fireAspect = create("minecraft.fireAspect", maxLevel: 2) + + /// Provides protection against fire damage. + public static let fireProtection = create("minecraft.fireProtection", maxLevel: 4) + + /// Sets the victim on fire when hit by an arrow shot from a bow. + public static let flame = create("minecraft.flame", maxLevel: 1) + + /// Chance of gaining extra loot when destroying blocks. + public static let fortune = create("minecraft.fortune", maxLevel: 3) + + /// Freezes still water adjacent to ice the `Entity` is walking on. + public static let frostWalker = create("minecraft.frostWalker", maxLevel: 2) + + /// Deals more damage to mobs that live in the ocean. + public static let impaling = create("minecraft.impaling", maxLevel: 5) + + /// Provides infinite arrows when shooting a bow. + public static let infinity = create("minecraft.infinity", maxLevel: 1) + + /// Damage to others will knock them back when hit. + public static let knockback = create("minecraft.knockback", maxLevel: 2) + + /// Chance of gaining extra loot when killing monsters. + public static let looting = create("minecraft.looting", maxLevel: 3) + + /// Causes a thrown trident to return to the thrower. + public static let loyalty = create("minecraft.loyalty", maxLevel: 3) + + /// Decreases chance of catching worthless junk. + public static let luckOfTheSea = create("minecraft.luckOfTheSea", maxLevel: 3) + + /// Lunges further forward when attacking. + public static let lunge = create("minecraft.lunge", maxLevel: 3) + + /// Increases rate of fish biting your hook. + public static let lure = create("minecraft.lure", maxLevel: 3) + + /// Repairs an item's durability when obtaining experience orbs. + public static let mending = create("minecraft.mending", maxLevel: 1) + + /// Shoot multiple arrows from crossbows. + public static let multishot = create("minecraft.multishot", maxLevel: 3) + + /// Crossbow projectiles pierce entities. + public static let piercing = create("minecraft.piercing", maxLevel: 5) + + /// Provides extra damage when shooting arrows from bows. + public static let power = create("minecraft.power", maxLevel: 5) + + /// Provides protection against projectile damage. + public static let projectileProtection = create("minecraft.projectileProtection", maxLevel: 4) + + /// Provides protection against environmental damage. + public static let protection = create("minecraft.protection", maxLevel: 4) + + /// Knockback the victim when hit by an arrow from a bow. + public static let punch = create("minecraft.punch", maxLevel: 2) + + /// Charges crossbows quicker. + public static let quickCharge = create("minecraft.quickCharge", maxLevel: 3) + + /// Decreases the rate of air loss when underwater. + public static let respiration = create("minecraft.respiration", maxLevel: 3) + + /// When raining, launches the player in the direction their trident is thrown. + public static let riptide = create("minecraft.riptide", maxLevel: 3) + + /// Increases damage against all targets. + public static let sharpness = create("minecraft.sharpness", maxLevel: 5) + + /// Allows blocks to drop themselves instead of fragments. + public static let silkTouch = create("minecraft.silkTouch", maxLevel: 1) + + /// increases damage against undead targets. + public static let smite = create("minecraft.smite", maxLevel: 5) + + /// Walk quicker on soul blocks. + public static let soulSpeed = create("minecraft.soulSpeed", maxLevel: 3) + + /// Increases damage against targets when using a sweep attack. + public static let sweepingEdge = create("minecraft.sweepingEdge", maxLevel: 3) + + /// Walk quicker while sneaking. + public static let swiftSneak = create("minecraft.swiftSneak", maxLevel: 3) + + /// Damages the attacker. + public static let thorns = create("minecraft.thorns", maxLevel: 4) + + /// Decreases the chance a tool loses durability. + public static let unbreaking = create("minecraft.unbreaking", maxLevel: 3) + + /// Item disappears instead of dropping. + public static let vanishingCurse = create("minecraft.vanishingCurse", maxLevel: 1) + + /// Emits wind burst upon hitting enemy. + public static let windBurst = create("minecraft.windBurst", maxLevel: 3) +} \ No newline at end of file diff --git a/Sources/API/enchantment/Enchantment.swift b/Sources/API/enchantment/Enchantment.swift index f4fd7fd7..34fdd689 100644 --- a/Sources/API/enchantment/Enchantment.swift +++ b/Sources/API/enchantment/Enchantment.swift @@ -22,7 +22,7 @@ extension Enchantment: Hashable { } } -// MARK: Defaults +// MARK: Create extension Enchantment { public static func create( _ id: String, @@ -34,133 +34,4 @@ extension Enchantment { maxLevel: maxLevel ) } - - /// Increases the speed an `Entity` mines underwater. - public static let aquaAffinity = create("minecraft.aquaAffinity", maxLevel: 1) - - /// Increases damage against arthropod entities. - public static let baneOfArthropods = create("minecraft.baneOfArthropods", maxLevel: 5) - - /// Item cannot be removed. - public static let bindingCurse = create("minecraft.bindingCurse", maxLevel: 1) - - /// Provides protection against explosive damage. - public static let blastProtection = create("minecraft.blastProtection", maxLevel: 4) - - /// Reduces armor effectiveness against maces. - public static let breach = create("minecraft.breach", maxLevel: 4) - - /// Strikes lightning when a mob is hit with a trident if conditions are stormy. - public static let channeling = create("minecraft.channeling", maxLevel: 1) - - /// Increases fall damage of maces. - public static let density = create("minecraft.density", maxLevel: 5) - - /// Increases walking speed while in water. - public static let depthStrider = create("minecraft.depthStrider", maxLevel: 3) - - /// Reduces the duration of destroying of blocks. - public static let efficiency = create("minecraft.efficiency", maxLevel: 5) - - /// Provides protection against fall damage. - public static let featherFalling = create("minecraft.featherFalling", maxLevel: 4) - - /// Chance to set the victim on fire when hit. - public static let fireAspect = create("minecraft.fireAspect", maxLevel: 2) - - /// Provides protection against fire damage. - public static let fireProtection = create("minecraft.fireProtection", maxLevel: 4) - - /// Sets the victim on fire when hit by an arrow shot from a bow. - public static let flame = create("minecraft.flame", maxLevel: 1) - - /// Chance of gaining extra loot when destroying blocks. - public static let fortune = create("minecraft.fortune", maxLevel: 3) - - /// Freezes still water adjacent to ice the `Entity` is walking on. - public static let frostWalker = create("minecraft.frostWalker", maxLevel: 2) - - /// Deals more damage to mobs that live in the ocean. - public static let impaling = create("minecraft.impaling", maxLevel: 5) - - /// Provides infinite arrows when shooting a bow. - public static let infinity = create("minecraft.infinity", maxLevel: 1) - - /// Damage to others will knock them back when hit. - public static let knockback = create("minecraft.knockback", maxLevel: 2) - - /// Chance of gaining extra loot when killing monsters. - public static let looting = create("minecraft.looting", maxLevel: 3) - - /// Causes a thrown trident to return to the thrower. - public static let loyalty = create("minecraft.loyalty", maxLevel: 3) - - /// Decreases chance of catching worthless junk. - public static let luckOfTheSea = create("minecraft.luckOfTheSea", maxLevel: 3) - - /// Lunges further forward when attacking. - public static let lunge = create("minecraft.lunge", maxLevel: 3) - - /// Increases rate of fish biting your hook. - public static let lure = create("minecraft.lure", maxLevel: 3) - - /// Repairs an item's durability when obtaining experience orbs. - public static let mending = create("minecraft.mending", maxLevel: 1) - - /// Shoot multiple arrows from crossbows. - public static let multishot = create("minecraft.multishot", maxLevel: 3) - - /// Crossbow projectiles pierce entities. - public static let piercing = create("minecraft.piercing", maxLevel: 5) - - /// Provides extra damage when shooting arrows from bows. - public static let power = create("minecraft.power", maxLevel: 5) - - /// Provides protection against projectile damage. - public static let projectileProtection = create("minecraft.projectileProtection", maxLevel: 4) - - /// Provides protection against environmental damage. - public static let protection = create("minecraft.protection", maxLevel: 4) - - /// Knockback the victim when hit by an arrow from a bow. - public static let punch = create("minecraft.punch", maxLevel: 2) - - /// Charges crossbows quicker. - public static let quickCharge = create("minecraft.quickCharge", maxLevel: 3) - - /// Decreases the rate of air loss when underwater. - public static let respiration = create("minecraft.respiration", maxLevel: 3) - - /// When raining, launches the player in the direction their trident is thrown. - public static let riptide = create("minecraft.riptide", maxLevel: 3) - - /// Increases damage against all targets. - public static let sharpness = create("minecraft.sharpness", maxLevel: 5) - - /// Allows blocks to drop themselves instead of fragments. - public static let silkTouch = create("minecraft.silkTouch", maxLevel: 1) - - /// increases damage against undead targets. - public static let smite = create("minecraft.smite", maxLevel: 5) - - /// Walk quicker on soul blocks. - public static let soulSpeed = create("minecraft.soulSpeed", maxLevel: 3) - - /// Increases damage against targets when using a sweep attack. - public static let sweepingEdge = create("minecraft.sweepingEdge", maxLevel: 3) - - /// Walk quicker while sneaking. - public static let swiftSneak = create("minecraft.swiftSneak", maxLevel: 3) - - /// Damages the attacker. - public static let thorns = create("minecraft.thorns", maxLevel: 4) - - /// Decreases the chance a tool loses durability. - public static let unbreaking = create("minecraft.unbreaking", maxLevel: 3) - - /// Item disappears instead of dropping. - public static let vanishingCurse = create("minecraft.vanishingCurse", maxLevel: 1) - - /// Emits wind burst upon hitting enemy. - public static let windBurst = create("minecraft.windBurst", maxLevel: 3) } \ No newline at end of file From 40c6118a045a6b8cca2b427e6abdf0ae7dafc488 Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sat, 27 Dec 2025 16:39:55 -0600 Subject: [PATCH 07/11] add `EnchantmentOffer` --- Sources/API/enchantment/EnchantmentOffer.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Sources/API/enchantment/EnchantmentOffer.swift diff --git a/Sources/API/enchantment/EnchantmentOffer.swift b/Sources/API/enchantment/EnchantmentOffer.swift new file mode 100644 index 00000000..88937538 --- /dev/null +++ b/Sources/API/enchantment/EnchantmentOffer.swift @@ -0,0 +1,12 @@ + +/// An offer from the enchantment table. +public struct EnchantmentOffer: Sendable { + /// Cost of the offer which is displayed as a number on the right hand side of the enchantment. + public var cost:Int + + /// Type of enchantment for this offer. + public var enchantment:Enchantment + + /// Level of the offered enchantment for this offer. + public var enchantmentLevel:Int +} \ No newline at end of file From 46a9bed87f3eeaf748a8f3d01972c7374767766c Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sat, 27 Dec 2025 16:49:09 -0600 Subject: [PATCH 08/11] add two structs relating to scoreboards --- Sources/API/scoreboard/DisplaySlot.swift | 23 +++++++++++++++++++++++ Sources/API/scoreboard/RenderType.swift | 9 +++++++++ 2 files changed, 32 insertions(+) create mode 100644 Sources/API/scoreboard/DisplaySlot.swift create mode 100644 Sources/API/scoreboard/RenderType.swift diff --git a/Sources/API/scoreboard/DisplaySlot.swift b/Sources/API/scoreboard/DisplaySlot.swift new file mode 100644 index 00000000..28f4021c --- /dev/null +++ b/Sources/API/scoreboard/DisplaySlot.swift @@ -0,0 +1,23 @@ + +/// Locations for displaying objectives to the player. +public enum DisplaySlot: String, CaseIterable, Sendable { + case belowName + case playerList + case sidebar + case sidebarAqua + case sidebarBlack + case sidebarBlue + case sidebarDarkAqua + case sidebarDarkBlue + case sidebarDarkGray + case sidebarDarkGreen + case sidebarDarkPurple + case sidebarDarkRed + case sidebarGold + case sidebarGray + case sidebarGreen + case sidebarLightPurple + case sidebarRed + case sidebarWhite + case sidebarYellow +} \ No newline at end of file diff --git a/Sources/API/scoreboard/RenderType.swift b/Sources/API/scoreboard/RenderType.swift new file mode 100644 index 00000000..8ca333c5 --- /dev/null +++ b/Sources/API/scoreboard/RenderType.swift @@ -0,0 +1,9 @@ + +/// Controls the way an `Objective` is rendered client side. +public enum RenderType: String, Sendable { + /// Display number of hearts corresponding to value. + case hearts + + /// Display integer value. + case integer +} \ No newline at end of file From ed029774c9b83576092666b39ca3e7492ec2f078 Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sat, 27 Dec 2025 17:09:43 -0600 Subject: [PATCH 09/11] added 3 more structs to the API module --- Sources/API/Difficulty.swift | 15 +++++++++++++++ Sources/API/Location.swift | 33 +++++++++++++++++++++++++++++++++ Sources/API/World.swift | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 Sources/API/Difficulty.swift create mode 100644 Sources/API/Location.swift create mode 100644 Sources/API/World.swift diff --git a/Sources/API/Difficulty.swift b/Sources/API/Difficulty.swift new file mode 100644 index 00000000..509f3e8d --- /dev/null +++ b/Sources/API/Difficulty.swift @@ -0,0 +1,15 @@ + +/// Various difficulty levels. +public enum Difficulty: Sendable { + /// Hostile mobs spawn, enemies deal less damage than `normal`, the hunger bar does deplete and starving deals up to 5 hearts of damage. + case easy + + /// Hostile mobs spawn, enemies deal greater damage than `normal`, the hunger bar does deplete and starving can kill players. + case hard + + /// Hostile mobs spawn, enemies deal normal amounts of damage, the hunger bar does deplete and starving deals up to 9.5 hearts of damage. + case normal + + /// Players regain health over time, hostile mobs don't spawn, the hunger bar does not deplete. + case peaceful +} \ No newline at end of file diff --git a/Sources/API/Location.swift b/Sources/API/Location.swift new file mode 100644 index 00000000..72f75974 --- /dev/null +++ b/Sources/API/Location.swift @@ -0,0 +1,33 @@ + +/// A 3-dimensional position in a world. +public struct Location: Sendable { + /// The 'x' coordinate of this location. + public var x:Float + + /// The 'y' coordinate of this location. + public var y:Float + + /// The 'z' coordinate of this location. + public var z:Float + + public var yaw:Float + public var pitch:Float +} + +// MARK: Whole coordinates +extension Location { + /// Floored 'x' coordinate of this location. + public var blockX: Int { + Int(x) + } + + /// Floored 'y' coordinate of this location. + public var blockY: Int { + Int(y) + } + + /// Floored 'z' coordinate of this location. + public var blockZ: Int { + Int(z) + } +} \ No newline at end of file diff --git a/Sources/API/World.swift b/Sources/API/World.swift new file mode 100644 index 00000000..f50a2b2b --- /dev/null +++ b/Sources/API/World.swift @@ -0,0 +1,33 @@ + +public struct World: Sendable { + + /// The spawn location for this world. + public var spawnLocation:Location + + /// Releative in-game time of this world. + public var time:Int + + /// View distance used for this world. + public var viewDistance:Int + + public var difficulty:Difficulty + + var flags:Flags.RawValue +} + +// MARK: Flags +extension World { + enum Flags: UInt16 { + case animalsCanSpawn = 1 + case monstersCanSpawn = 2 + case pvpIsAllowed = 4 + case hasCeiling = 8 + case hasSkylight = 16 + case autoSaves = 32 + case bedWorks = 64 + case hardcore = 128 + case natural = 256 + case piglinSafe = 512 + case respawnAnchorWorks = 1024 + } +} \ No newline at end of file From 247d28087e8b5ca1c823ed6327ac1c12696443d7 Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sun, 28 Dec 2025 05:09:54 -0600 Subject: [PATCH 10/11] add `EnchantmentTarget` --- .../API/enchantment/EnchantmentTarget.swift | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Sources/API/enchantment/EnchantmentTarget.swift diff --git a/Sources/API/enchantment/EnchantmentTarget.swift b/Sources/API/enchantment/EnchantmentTarget.swift new file mode 100644 index 00000000..32ee8479 --- /dev/null +++ b/Sources/API/enchantment/EnchantmentTarget.swift @@ -0,0 +1,60 @@ + +/// Applicable targets for an `Enchantment`. +public enum EnchantmentTarget: String, CaseIterable, Sendable { + /// Allows the enchantment to be applied to armor. + case armor + + /// Allows the enchantment to be applied to the feet slot. + case armorFeet + + /// Allows the enchantment to be applied to the head slot. + case armorHead + + /// Allows the enchantment to be applied to the leg slot. + case armorLegs + + /// Allows the enchantment to be applied to the torso slot. + case armorTorso + + /// Allows the enchantment to be applied to bows. + case bow + + /// Allows the enchantment to be applied to items with durability. + case breakable + + /// Allows the enchantment to be applied to crossbows. + case crossbow + + /// Allows the enchantment to be applied to fishing rods. + case fishingRod + + /// Allows the enchantment to be applied to tools (axes, pickaxes, shovels, etc). + case tool + + /// Allows the enchantment to be applied to tridents. + case trident + + /// Allows the enchantment to be applied to vanishing items. + case vanishable + + /// Allows the enchantment to be applied to weapons (swords). + case weapon + + /// Allows the enchantment to be applied to wearable items. + case wearable +} + +// MARK: Includes +extension EnchantmentTarget { + /// Whether this target is applicable to the specified item. + public func includes(_ itemstack: ItemStack) -> Bool { + // TODO: fix + return false + } + + /// Whether this target is applicable to the specified material. + public func includes(_ material: Material) -> Bool { + // TODO: fix + return false + } +} \ No newline at end of file From 0d6d63b0e9bbdd6f64ef61b000708991e3e56e48 Mon Sep 17 00:00:00 2001 From: RandomHashTags Date: Sun, 28 Dec 2025 08:22:35 -0600 Subject: [PATCH 11/11] added more API stuff --- Sources/API/block/BlockFace.swift | 60 ++++++ Sources/API/damage/DamageSource.swift | 42 ++++ Sources/API/entity/Allay.swift | 85 ++++++++ Sources/API/entity/Damageable.swift | 28 +++ Sources/API/entity/Entity.swift | 188 ++++++++++++++++++ Sources/API/entity/LivingEntity.swift | 145 ++++++++++++++ Sources/API/entity/Pose.swift | 22 ++ Sources/API/entity/SpawnCategory.swift | 26 +++ .../potion/PotionEffectType+Defaults.swift | 119 +++++++++++ Sources/API/potion/PotionEffectType.swift | 21 ++ 10 files changed, 736 insertions(+) create mode 100644 Sources/API/block/BlockFace.swift create mode 100644 Sources/API/damage/DamageSource.swift create mode 100644 Sources/API/entity/Allay.swift create mode 100644 Sources/API/entity/Damageable.swift create mode 100644 Sources/API/entity/Entity.swift create mode 100644 Sources/API/entity/LivingEntity.swift create mode 100644 Sources/API/entity/Pose.swift create mode 100644 Sources/API/entity/SpawnCategory.swift create mode 100644 Sources/API/potion/PotionEffectType+Defaults.swift create mode 100644 Sources/API/potion/PotionEffectType.swift diff --git a/Sources/API/block/BlockFace.swift b/Sources/API/block/BlockFace.swift new file mode 100644 index 00000000..802b0766 --- /dev/null +++ b/Sources/API/block/BlockFace.swift @@ -0,0 +1,60 @@ + +/// Face of a block. +public enum BlockFace: String, CaseIterable, Sendable { + case down + case east + case eastNorthEast + case eastSouthEast + case north + case northEast + case northNorthEast + case northNorthWest + case northWest + case `self` + case south + case southEast + case southSouthEast + case southSouthWest + case southWest + case up + case west + case westNorthWest + case westSouthWest +} + +extension BlockFace { + /// If this face is aligned with one of the unit axes in 3D Catesian space (north, east, south, west, up, down) + public var isCartesian: Bool { + switch self { + case .north, .east, .south, .west, .up, .down: + true + default: + false + } + } + + /// Opposite face of the current face. + public var oppositeFace: Self { + switch self { + case .down: .up + case .east: .west + case .eastNorthEast: .westSouthWest + case .eastSouthEast: .westNorthWest + case .north: .south + case .northEast: .southWest + case .northNorthEast: .southSouthWest + case .northNorthWest: .southSouthEast + case .northWest: .southEast + case .self: .self + case .south: .north + case .southEast: .northWest + case .southSouthEast: .northNorthWest + case .southSouthWest: .northNorthEast + case .southWest: .northEast + case .up: .down + case .west: .east + case .westNorthWest: .eastSouthEast + case .westSouthWest: .eastNorthEast + } + } +} \ No newline at end of file diff --git a/Sources/API/damage/DamageSource.swift b/Sources/API/damage/DamageSource.swift new file mode 100644 index 00000000..f76d401c --- /dev/null +++ b/Sources/API/damage/DamageSource.swift @@ -0,0 +1,42 @@ + +/// A source of damage. +public struct DamageSource: Sendable { + + /// Location where the damage originates. + public let damageLocation:Location? + + /// Amount of hunger exhaustion caused by this damage. + public let foodExhaustion:Float + + var flags:Flags.RawValue +} + +// MARK: Flags +extension DamageSource { + enum Flags: UInt8, Sendable { + case indirect = 1 + case scalesWithDifficulty = 2 + } + + private func isFlag(_ flag: Flags) -> Bool { + flags & flag.rawValue > 0 + } + + /// If this source of damage is indirect. + public var isIndirect: Bool { + isFlag(.indirect) + } + + /// If this source of damage scales with difficulty. + public var scalesWithDifficulty: Bool { + isFlag(.scalesWithDifficulty) + } +} + +// MARK: Source location +extension DamageSource { + /// Location where the damage originates, taking into account the causing entity. + public var sourceLocation: Location? { + damageLocation // TODO: fix + } +} \ No newline at end of file diff --git a/Sources/API/entity/Allay.swift b/Sources/API/entity/Allay.swift new file mode 100644 index 00000000..eb26de43 --- /dev/null +++ b/Sources/API/entity/Allay.swift @@ -0,0 +1,85 @@ + +/// An Allay entity. +public struct Allay: Sendable { + + /// Allay's underlying living entity storage. + public var livingEntity:LivingEntity + + /// Cooldown, measured in ticks, for duplicating the allay. + public private(set) var duplicationCooldown:UInt + + /// Location of the jukebox the allay is currently dancing to. + public private(set) var jukebox:Location? + + /// Bit-packed boolean values. + var flags:Flags.RawValue +} + +// MARK: Flags +extension Allay { + enum Flags: UInt8, Sendable { + case canDuplicate = 1 + case dancing = 2 + } + + private func isFlag(_ flag: Flags) -> Bool { + flags & flag.rawValue > 0 + } + + private mutating func setFlag(_ flag: Flags, value: Bool) { + if value { + flags |= flag.rawValue + } else { + flags &= ~flag.rawValue + } + } + + /// If the allay can duplicate. + public var canDuplicate: Bool { + isFlag(.canDuplicate) + } + + /// If the allay is currently dancing. + public var isDancing: Bool { + isFlag(.dancing) + } +} + +// MARK: Cooldown +extension Allay { + /// Reset the cooldown for duplication. + public mutating func resetDuplicationCooldown() { + duplicationCooldown = 0 + } +} + +// MARK: Dancing +extension Allay { + /// Causes the allay to start dancing with the provided jukebox location. + public mutating func startDancing(at location: Location) { + setFlag(.dancing, value: true) + jukebox = location + } + + /// Makes the allay stop dancing. + public mutating func stopDancing() { + setFlag(.dancing, value: false) + jukebox = nil + } +} + +// MARK: Duplication +extension Allay { + /// Duplicate the allay without dance or requiring an item. + public func duplicate() -> Self { + let dupe = Self( + livingEntity: livingEntity, + duplicationCooldown: duplicationCooldown, + jukebox: jukebox, + flags: flags + ) + // TODO: spawn in world + // TODO: update duplication cooldown + return dupe + } +} \ No newline at end of file diff --git a/Sources/API/entity/Damageable.swift b/Sources/API/entity/Damageable.swift new file mode 100644 index 00000000..6d5ac231 --- /dev/null +++ b/Sources/API/entity/Damageable.swift @@ -0,0 +1,28 @@ + +/// Entity that has health and can take damage. +public struct Damageable: Sendable { + /// Damageable's underlying entity storage. + public var entity:Entity + + /// Current health for this damageable. + public var health:Double { + didSet { + health = max(0, oldValue) + } + } + public var absorptionAmount:Double +} + +// MARK: Damage +extension Damageable { + /// Deals the specified amount of damage to this damageable. + /// + /// - Parameters: + /// - amount: Amount of damage to deal + public mutating func damage(amount: Double) { + health -= amount + if health > 0 { + health = 0 + } + } +} \ No newline at end of file diff --git a/Sources/API/entity/Entity.swift b/Sources/API/entity/Entity.swift new file mode 100644 index 00000000..79da509f --- /dev/null +++ b/Sources/API/entity/Entity.swift @@ -0,0 +1,188 @@ + +#if canImport(FoundationEssentials) +import FoundationEssentials +#elseif canImport(Foundation) +import Foundation +#endif + +/// A base entity in the world. +public struct Entity: Sendable { + /// Persistent unique id for the entity. + public let uniqueId:UUID + + /// Unique id for the entity. + public let entityId:UInt64 + + /// Distance the entity has fallen. + public var fallDistance:Float + + /// Entity's current fire ticks (remaining ticks the entity stays on fire). + public var fireTicks:Int + + /// Entity's current freeze ticks (amount of ticks the entity has been freezing). + public var freezeTicks:Int + + /// Entity's current location. + public private(set) var location:Location + + /// Entity's maximum fire ticks. + public var maxFireTicks:Int + + /// Entity's maximum freeze ticks. + public var maxFreezeTicks:Int + + /// Entity's current pose. + public private(set) var pose:Pose + + /// Entity's spawn category. + public let spawnCategory:SpawnCategory + + + // MARK: Dimensions + + /// Entity's current height. + public private(set) var height:Double + + /// Entity's current width. + public private(set) var width:Double + + + // MARK: Sounds + + /// The sound this entity makes while swimming. + /// For most entities this is `minecraft.entity.generic.splash`. + public let soundSwim:Sound + + /// The sound this entity makes when splashing in water. + /// For most entities this is `minecraft.entity.generic.splash`. + public let soundSwimSplash:Sound + + /// The sound the entity makes when splashing in water at high speeds. + /// For most entities this is `minecraft.entity.generic.splash`. + public let soundSwimHighSpeedSplash:Sound + + + // MARK: Other + + /// List of passengers of this vehicle. + public var passengers:[Entity] + + var flags:Flags.RawValue +} + +// MARK: Flags +extension Entity { + enum Flags: UInt16, Sendable { + case gravity = 1 + case customNameVisible = 2 + case dead = 4 + case glowing = 8 + case invulnerable = 16 + case inWater = 32 + case onGround = 64 + case persistent = 128 + case silent = 256 + case visibleByDefault = 512 + } + + private func isFlag(_ flag: Flags) -> Bool { + flags & flag.rawValue > 0 + } + private mutating func setFlag(_ flag: Flags, value: Bool) { + if value { + flags |= flag.rawValue + } else { + flags &= ~flag.rawValue + } + } + + /// If gravity applies to this entity. + public var hasGravity: Bool { + isFlag(.gravity) + } + + /// If the entity's custom name is displayed client side. + public var isCustomNameVisible: Bool { + isFlag(.customNameVisible) + } + + /// If the entity has been marked for removal. + public var isDead: Bool { + isFlag(.dead) + } + + /// If the entity is glowing. + public var isGlowing: Bool { + isFlag(.glowing) + } + + /// If the entity is invulnerable. + public var isInvulnerable: Bool { + isFlag(.invulnerable) + } + + /// If the entity is in water. + public var isInWater: Bool { + isFlag(.inWater) + } + + /// If the entity is supported by a block. + public var isOnGround: Bool { + isFlag(.onGround) + } + + /// If the entity gets persisted. + public var isPersistent: Bool { + isFlag(.persistent) + } + + /// If the entity is silent. + public var isSilent: Bool { + isFlag(.silent) + } + + /// If the entity is visible by default. + public var isVisibleByDefault: Bool { + isFlag(.visibleByDefault) + } +} + +// MARK: Booleans +extension Entity { + /// If the entity doesn't have any passengers. + public var isEmpty: Bool { + passengers.isEmpty + } + + /// If the entity is fully frozen (`freezeTicks` is greater than `maxFreezeTicks`). + public var isFrozen: Bool { + freezeTicks > maxFreezeTicks + } + + /// If the entity is alive, in a world and was not despawned. + public var isValid: Bool { + !isFlag(.dead) // TODO: finish + } +} + +// MARK: Remove +extension Entity { + /// Marks the entity for removal. + public mutating func remove() { + setFlag(.dead, value: true) + } +} + +// MARK: Teleport +extension Entity { + /// Teleports the entity to the target entity. + /// + /// - Note: If the entity is riding a vehicle, it will be dismounted prior to teleportation. + /// + /// - Returns: If the teleport was successful. + public mutating func teleport(to entity: Entity) -> Bool { + // TODO: finish + location = entity.location + return true + } +} \ No newline at end of file diff --git a/Sources/API/entity/LivingEntity.swift b/Sources/API/entity/LivingEntity.swift new file mode 100644 index 00000000..97aa8734 --- /dev/null +++ b/Sources/API/entity/LivingEntity.swift @@ -0,0 +1,145 @@ + +/// A living entity such as an animal, monster or player. +public struct LivingEntity: Sendable { + + /// The living entity's underlying damageable storage. + public var damageable:Damageable + + /// Maximum number of ticks the entity has of air. + public var maximumAir:Int + + /// Maximum number of ticks the entity becomes immune to damage after receiving damage. + public var maximumNoDamageTicks:Int + + /// Number of ticks the entity has performed no action. + public var noActionTicks:Int + + /// Remaining number of ticks the entity is immune from damage. + public var noDamageTicks:Int + + /// Remaining number of ticks the entity has of air. + public var remainingAir:Int + + // MARK: Sounds + /// Sound the entity will make on death. + public let soundDeath:Sound? + + /// Sound the entity will make when falling from a large height. + public let soundFallDamageBig:Sound + + /// Sound the entity will make when falling from a small height. + public let soundFallDamageSmall:Sound + + /// Sound the entity will make when damaged. + public let soundHurt:Sound? + + // MARK: Other + /// Bit-packed boolean values. + var flags:Flags.RawValue +} + +// MARK: Flags +extension LivingEntity { + enum Flags: UInt16, Sendable { + case ai = 1 + case climbing = 2 + case collidable = 4 + case gliding = 8 + case invisible = 16 + case riptiding = 32 + case sleeping = 64 + case swimming = 128 + case pickupItems = 256 + } + + private func isFlag(_ flag: Flags) -> Bool { + flags & flag.rawValue > 0 + } + private mutating func setFlag(_ flag: Flags, value: Bool) { + if value { + flags |= flag.rawValue + } else { + flags &= ~flag.rawValue + } + } + + /// If the entity has AI. + public var hasAI: Bool { + get { + isFlag(.ai) + } + set { + setFlag(.ai, value: newValue) + } + } + + /// If the entity is currently climbing. + public var isClimbing: Bool { + isFlag(.climbing) + } + + /// If the entity is currently subject to collisions with other entities. + public var isCollidable: Bool { + get { + isFlag(.collidable) + } + set { + setFlag(.collidable, value: newValue) + } + } + + /// If the entity is currently gliding (such as using an Elytra). + public var isGliding: Bool { + get { + isFlag(.gliding) + } + set { + setFlag(.gliding, value: newValue) + } + } + + /// If the entity is currently invisible. + public var isInvisible: Bool { + get { + isFlag(.invisible) + } + set { + setFlag(.invisible, value: newValue) + } + } + + /// If the entity is currently riptiding. + public var isRiptiding: Bool { + get { + isFlag(.riptiding) + } + set { + setFlag(.riptiding, value: newValue) + } + } + + /// If the entity is currently sleeping/slumbering. + public var isSleeping: Bool { + isFlag(.sleeping) + } + + /// If the entity is currentky swimming. + public var isSwimming: Bool { + get { + isFlag(.swimming) + } + set { + setFlag(.swimming, value: newValue) + } + } + + /// If the entity can currently pick up items. + public var canPickupItems: Bool { + get { + isFlag(.pickupItems) + } + set { + setFlag(.pickupItems, value: newValue) + } + } +} \ No newline at end of file diff --git a/Sources/API/entity/Pose.swift b/Sources/API/entity/Pose.swift new file mode 100644 index 00000000..e9eb7fe6 --- /dev/null +++ b/Sources/API/entity/Pose.swift @@ -0,0 +1,22 @@ + +/// An entity's body pose. +public enum Pose: String, Sendable { + case croaking + case digging + case dying + case emerging + case gliding + case inhaling + case longJumping + case roaring + case shooting + case sitting + case sleeping + case sliding + case sneaking + case sniffing + case spinAttack + case standing + case swimming + case usingTongue +} \ No newline at end of file diff --git a/Sources/API/entity/SpawnCategory.swift b/Sources/API/entity/SpawnCategory.swift new file mode 100644 index 00000000..c2f5d3ac --- /dev/null +++ b/Sources/API/entity/SpawnCategory.swift @@ -0,0 +1,26 @@ + +public enum SpawnCategory: String, CaseIterable, Sendable { + /// - Example: Bat + case ambient + + /// - Example: Strider, Cow, Turtle + case animal + + /// All Axolotls are represented by this category. + case axolotl + + /// - Example: Player, Armor Stand, Boat + case misc + + /// - Example: Witch, Zombie, Creeper + case monster + + /// - Example: Cod, Pufferfish, Tropical Fish, Salmon + case waterAmbient + + /// - Example: Squid or Dolphin + case waterAnimal + + /// - Example: Glow Squid + case waterUndergroundCreature +} \ No newline at end of file diff --git a/Sources/API/potion/PotionEffectType+Defaults.swift b/Sources/API/potion/PotionEffectType+Defaults.swift new file mode 100644 index 00000000..390b2003 --- /dev/null +++ b/Sources/API/potion/PotionEffectType+Defaults.swift @@ -0,0 +1,119 @@ + +extension PotionEffectType { + /// Increases the maximum health of an entity with health that cannot be regenerated but is refilled every 30 seconds. + public static let absorption = create("minecraft.absorption") + + /// Triggers an ominous event when the player enters a village or trial chamber. + public static let badOmen = create("minecraft.badOmen") + + /// Blinds an entity. + public static let blindness = create("minecraft.blindness") + + /// Allows breathing underwater. + public static let breathOfTheNautilus = create("minecraft.breathOfTheNautilus") + + /// Effects granted by a nearby conduit. + public static let conduitPower = create("minecraft.conduitPower") + + /// Causes the player's vision to dim occasionally. + public static let darkness = create("minecraft.darkness") + + /// Increases underwater movement speed. + public static let dolphinsGrace = create("minecraft.dolphinsGrace") + + /// Become immune to fire damage. + public static let fireResistance = create("minecraft.fireResistance") + + /// Outlines the entity so that it can be seen from afar. + public static let glowing = create("minecraft.glowing") + + /// Increases block breaking speed. + public static let haste = create("minecraft.haste") + + /// Increases the maximum health of an entity. + public static let healthBoost = create("minecraft.healthBoost") + + /// Reduces the cost of villager trades. + public static let heroOfTheVillage = create("minecraft.heroOfTheVillage") + + /// Increases hunger, reducing food faster. + public static let hunger = create("minecraft.hunger") + + /// Chance of spawning silverfish when hurt. + public static let infested = create("minecraft.infested") + + /// Hurts an entity. + public static let instantDamage = create("minecraft.instantDamage", isInstant: true) + + /// Heals an entity. + public static let instantHealth = create("minecraft.instantHealth", isInstant: true) + + /// Grants invisibility. + public static let invisibility = create("minecraft.invisibility") + + /// Increases jump height. + public static let jumpBoost = create("minecraft.jumpBoost") + + /// Causes the entity to float into the air. + public static let levitation = create("minecraft.levitation") + + /// Increases luck. + public static let luck = create("minecraft.luck") + + /// Decreases block breaking speed. + public static let miningFatigue = create("minecraft.miningFatigue") + + /// Warps vision on the client. + public static let nausea = create("minecraft.nausea") + + /// Allows an entity to see in the dark. + public static let nightVision = create("minecraft.nightVision") + + /// Causes slimes to spawn upon death. + public static let oozing = create("minecraft.oozing") + + /// Deals damage to an entity over time. + public static let poison = create("minecraft.poison") + + /// Triggers a raid when a plaer enters a village. + public static let raidOmen = create("minecraft.raidOmen") + + /// Regenerates health over time. + public static let regeneration = create("minecraft.regeneration") + + /// Decreases damage received. + public static let resistance = create("minecraft.resistance") + + /// Increases the food level of an entity over time. + public static let saturation = create("minecraft.saturation") + + /// Slows entity fall rate. + public static let slowFalling = create("minecraft.slowFalling") + + /// Decreases movement speed. + public static let slowness = create("minecraft.slowness") + + /// Increases damage dealt. + public static let strength = create("minecraft.strength") + + /// causes trial spawners to become ominous. + public static let trialOmen = create("minecraft.trailOmen") + + /// Decreases luck. + public static let unluck = create("minecraft.unluck") + + /// Allows breathing underwater. + public static let waterBreathing = create("minecraft.waterBreathing") + + /// Decreases damage dealt. + public static let weakness = create("minecraft.weakness") + + /// Creates cobwebs upon death. + public static let weaving = create("minecraft.weaving") + + /// Emits a wind burst upon death. + public static let windCharged = create("minecraft.windCharged") + + /// Deals damage to over time and gives the health to the shooter. + public static let wither = create("minecraft.wither") +} \ No newline at end of file diff --git a/Sources/API/potion/PotionEffectType.swift b/Sources/API/potion/PotionEffectType.swift new file mode 100644 index 00000000..f007fd8f --- /dev/null +++ b/Sources/API/potion/PotionEffectType.swift @@ -0,0 +1,21 @@ + +/// A type of potion and its effect on an entity. +public struct PotionEffectType: Sendable { + public let id:String + + /// If the effect of this type happens once, immediately. + public let isInstant:Bool +} + +// MARK: Create +extension PotionEffectType { + public static func create( + _ id: String, + isInstant: Bool = false + ) -> Self { + Self( + id: id, + isInstant: isInstant + ) + } +} \ No newline at end of file