Mirror von
https://github.com/PaperMC/Paper.git
synchronisiert 2024-12-16 03:20:07 +01:00
03a4e7ac75
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: 37262de8 PR-812: Add Registry#match(String) d6b40162 SPIGOT-4569: Add more BlockData API f9691891 PR-809: Throw a more clear error for BlockIterators with zero direction, add Vector#isZero() 91e79e19 PR-804: Added methods to get translation keys for materials, itemstacks and more 426b00d3 PR-795: Add new BiomeParameterPoint passed to BiomeProvider#getBiome 0e91ea52 SPIGOT-7224: Add events for brewing stands and campfires starting their actions CraftBukkit Changes: a50301aa5 Fix issues with fluid tag conversion and fluid #isTagged 6aeb5e4c3 SPIGOT-4569: Implement more BlockData API 7dbf862c2 PR-1131: Added methods to get translation keys for materials, itemstacks and more 7167588b1 PR-1117: Add new BiomeParameterPoint passed to BiomeProvider#getBiome 7c44152eb SPIGOT-7224: Add events for brewing stands and campfires starting their actions
386 Zeilen
18 KiB
Diff
386 Zeilen
18 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
|
Date: Tue, 22 Jun 2021 23:41:11 -0400
|
|
Subject: [PATCH] More Projectile API
|
|
|
|
== AT ==
|
|
public net.minecraft.world.entity.projectile.FishingHook timeUntilLured
|
|
public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaX
|
|
public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaY
|
|
public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaZ
|
|
public net.minecraft.world.entity.projectile.ShulkerBullet currentMoveDirection
|
|
public net.minecraft.world.entity.projectile.ShulkerBullet flightSteps
|
|
public net.minecraft.world.entity.projectile.AbstractArrow soundEvent
|
|
public net.minecraft.world.entity.projectile.ThrownTrident dealtDamage
|
|
public net.minecraft.world.entity.projectile.Projectile hasBeenShot
|
|
public net.minecraft.world.entity.projectile.Projectile leftOwner
|
|
public net.minecraft.world.entity.projectile.Projectile preOnHit(Lnet/minecraft/world/phys/HitResult;)V
|
|
public net.minecraft.world.entity.projectile.Projectile canHitEntity(Lnet/minecraft/world/entity/Entity;)Z
|
|
|
|
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
|
index 740ff3fed9c8d637527fda8544eba2b9d7d7280a..1f1519c1b33d16eba59546c86f20a099486441d7 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
|
|
@@ -100,6 +100,11 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
|
|
@Override
|
|
protected void onHit(HitResult hitResult) {
|
|
super.onHit(hitResult);
|
|
+ // Paper start - More projectile API
|
|
+ this.splash(hitResult);
|
|
+ }
|
|
+ public void splash(@org.jetbrains.annotations.Nullable HitResult hitResult) {
|
|
+ // Paper end - More projectile API
|
|
if (!this.level.isClientSide) {
|
|
ItemStack itemstack = this.getItem();
|
|
Potion potionregistry = PotionUtils.getPotion(itemstack);
|
|
@@ -113,7 +118,7 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
|
|
if (this.isLingering()) {
|
|
showParticles = this.makeAreaOfEffectCloud(itemstack, potionregistry); // Paper
|
|
} else {
|
|
- showParticles = this.applySplash(list, hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null); // Paper
|
|
+ showParticles = this.applySplash(list, hitResult != null && hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null); // Paper - nullable hitResult
|
|
}
|
|
}
|
|
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
|
|
index 40e5b19bc8fa3de3b3d54da0762aee5bd7bb8d7b..1c8d63e462f3ed3d5286659ae0d1ec04d8b55177 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
|
|
@@ -21,5 +21,46 @@ public abstract class AbstractProjectile extends CraftEntity implements Projecti
|
|
public void setBounce(boolean doesBounce) {
|
|
this.doesBounce = doesBounce;
|
|
}
|
|
+ // Paper start
|
|
+ @Override
|
|
+ public boolean hasLeftShooter() {
|
|
+ return this.getHandle().leftOwner;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setHasLeftShooter(boolean leftShooter) {
|
|
+ this.getHandle().leftOwner = leftShooter;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean hasBeenShot() {
|
|
+ return this.getHandle().hasBeenShot;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setHasBeenShot(boolean beenShot) {
|
|
+ this.getHandle().hasBeenShot = beenShot;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public boolean canHitEntity(org.bukkit.entity.Entity entity) {
|
|
+ return this.getHandle().canHitEntity(((CraftEntity) entity).getHandle());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void hitEntity(org.bukkit.entity.Entity entity) {
|
|
+ this.getHandle().preOnHit(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle()));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void hitEntity(org.bukkit.entity.Entity entity, org.bukkit.util.Vector vector) {
|
|
+ this.getHandle().preOnHit(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle(), new net.minecraft.world.phys.Vec3(vector.getX(), vector.getY(), vector.getZ())));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.world.entity.projectile.Projectile getHandle() {
|
|
+ return (net.minecraft.world.entity.projectile.Projectile) entity;
|
|
+ }
|
|
+ // Paper end
|
|
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
|
|
index 15abd085eeb0a31a925c1a8d6de903c9d4625a29..40ae8e43f40f9bf457d2917ac4f131b21e4f8dd2 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java
|
|
@@ -108,6 +108,27 @@ public class CraftArrow extends AbstractProjectile implements AbstractArrow {
|
|
return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getPickupItem());
|
|
}
|
|
|
|
+ @Override
|
|
+ public void setLifetimeTicks(int ticks) {
|
|
+ this.getHandle().life = ticks;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getLifetimeTicks() {
|
|
+ return this.getHandle().life;
|
|
+ }
|
|
+
|
|
+ @org.jetbrains.annotations.NotNull
|
|
+ @Override
|
|
+ public org.bukkit.Sound getHitSound() {
|
|
+ return org.bukkit.craftbukkit.CraftSound.getBukkit(this.getHandle().soundEvent);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setHitSound(@org.jetbrains.annotations.NotNull org.bukkit.Sound sound) {
|
|
+ this.getHandle().setSoundEvent(org.bukkit.craftbukkit.CraftSound.getSoundEffect(sound));
|
|
+ }
|
|
+
|
|
@Override
|
|
public void setNoPhysics(boolean noPhysics) {
|
|
this.getHandle().setNoPhysics(noPhysics);
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
|
index c242f654c88ca1773429348939d3bb2ffae3768c..d1c7ab67cba881d96b7a5e9220130d86d0514304 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
|
|
@@ -16,24 +16,26 @@ import org.bukkit.inventory.meta.FireworkMeta;
|
|
public class CraftFirework extends CraftProjectile implements Firework {
|
|
|
|
private final Random random = new Random();
|
|
- private final CraftItemStack item;
|
|
+ //private CraftItemStack item; // Paper - Remove usage, not accurate representation of current item.
|
|
|
|
public CraftFirework(CraftServer server, FireworkRocketEntity entity) {
|
|
super(server, entity);
|
|
|
|
- ItemStack item = this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM);
|
|
-
|
|
- if (item.isEmpty()) {
|
|
- item = new ItemStack(Items.FIREWORK_ROCKET);
|
|
- this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
|
|
- }
|
|
-
|
|
- this.item = CraftItemStack.asCraftMirror(item);
|
|
-
|
|
- // Ensure the item is a firework...
|
|
- if (this.item.getType() != Material.FIREWORK_ROCKET) {
|
|
- this.item.setType(Material.FIREWORK_ROCKET);
|
|
- }
|
|
+// Paper Start - Expose firework item directly
|
|
+// ItemStack item = this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM);
|
|
+//
|
|
+// if (item.isEmpty()) {
|
|
+// item = new ItemStack(Items.FIREWORK_ROCKET);
|
|
+// this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
|
|
+// }
|
|
+//
|
|
+// this.item = CraftItemStack.asCraftMirror(item);
|
|
+//
|
|
+// // Ensure the item is a firework...
|
|
+// if (this.item.getType() != Material.FIREWORK_ROCKET) {
|
|
+// this.item.setType(Material.FIREWORK_ROCKET);
|
|
+// }
|
|
+ // Paper End - Expose firework item directly
|
|
}
|
|
|
|
@Override
|
|
@@ -53,12 +55,12 @@ public class CraftFirework extends CraftProjectile implements Firework {
|
|
|
|
@Override
|
|
public FireworkMeta getFireworkMeta() {
|
|
- return (FireworkMeta) this.item.getItemMeta();
|
|
+ return (FireworkMeta) CraftItemStack.getItemMeta(this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM), Material.FIREWORK_ROCKET); // Paper - Expose firework item directly
|
|
}
|
|
|
|
@Override
|
|
public void setFireworkMeta(FireworkMeta meta) {
|
|
- this.item.setItemMeta(meta);
|
|
+ applyFireworkEffect(meta); // Paper - Expose firework item directly
|
|
|
|
// Copied from EntityFireworks constructor, update firework lifetime/power
|
|
this.getHandle().lifetime = 10 * (1 + meta.getPower()) + this.random.nextInt(6) + this.random.nextInt(7);
|
|
@@ -142,4 +144,46 @@ public class CraftFirework extends CraftProjectile implements Firework {
|
|
return getHandle().spawningEntity;
|
|
}
|
|
// Paper end
|
|
+ // Paper start - Expose firework item directly + manually setting flight
|
|
+ @Override
|
|
+ public org.bukkit.inventory.ItemStack getItem() {
|
|
+ return CraftItemStack.asBukkitCopy(this.getHandle().getItem());
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setItem(org.bukkit.inventory.ItemStack itemStack) {
|
|
+ FireworkMeta meta = getFireworkMeta();
|
|
+ ItemStack nmsItem = itemStack == null ? ItemStack.EMPTY : CraftItemStack.asNMSCopy(itemStack);
|
|
+ this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, nmsItem);
|
|
+
|
|
+ applyFireworkEffect(meta);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getTicksFlown() {
|
|
+ return this.getHandle().life;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setTicksFlown(int ticks) {
|
|
+ this.getHandle().life = ticks;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getTicksToDetonate() {
|
|
+ return this.getHandle().lifetime;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setTicksToDetonate(int ticks) {
|
|
+ this.getHandle().lifetime = ticks;
|
|
+ }
|
|
+
|
|
+ void applyFireworkEffect(FireworkMeta meta) {
|
|
+ ItemStack item = this.getHandle().getItem();
|
|
+ CraftItemStack.applyMetaToItem(item, meta);
|
|
+
|
|
+ this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM, item);
|
|
+ }
|
|
+ // Paper end - Expose firework item directly + manually setting flight
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
|
|
index 6bfa984781a483d048ef4318761203c701d8a632..5e0c2c5094e1578162d1a50d50701fbd25e6d961 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
|
|
@@ -119,4 +119,15 @@ public class CraftFishHook extends CraftProjectile implements FishHook {
|
|
public HookState getState() {
|
|
return HookState.values()[this.getHandle().currentState.ordinal()];
|
|
}
|
|
+ // Paper start - More FishHook API
|
|
+ @Override
|
|
+ public int getWaitTime() {
|
|
+ return this.getHandle().timeUntilLured;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setWaitTime(int ticks) {
|
|
+ this.getHandle().timeUntilLured = ticks;
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java
|
|
index 20b54f8896be1f8744a29e1d0205e58d27049f1f..ca8a9b2773d70a8800b2179b164ce33d7e2bdc5e 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java
|
|
@@ -40,6 +40,40 @@ public class CraftShulkerBullet extends AbstractProjectile implements ShulkerBul
|
|
this.getHandle().setTarget(target == null ? null : ((CraftEntity) target).getHandle());
|
|
}
|
|
|
|
+ @Override
|
|
+ public org.bukkit.util.Vector getTargetDelta() {
|
|
+ net.minecraft.world.entity.projectile.ShulkerBullet bullet = this.getHandle();
|
|
+ return new org.bukkit.util.Vector(bullet.targetDeltaX, bullet.targetDeltaY, bullet.targetDeltaZ);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setTargetDelta(org.bukkit.util.Vector vector) {
|
|
+ net.minecraft.world.entity.projectile.ShulkerBullet bullet = this.getHandle();
|
|
+ bullet.targetDeltaX = vector.getX();
|
|
+ bullet.targetDeltaY = vector.getY();
|
|
+ bullet.targetDeltaZ = vector.getZ();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public org.bukkit.block.BlockFace getCurrentMovementDirection() {
|
|
+ return org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(this.getHandle().currentMoveDirection);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setCurrentMovementDirection(org.bukkit.block.BlockFace movementDirection) {
|
|
+ this.getHandle().currentMoveDirection = org.bukkit.craftbukkit.block.CraftBlock.blockFaceToNotch(movementDirection);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getFlightSteps() {
|
|
+ return this.getHandle().flightSteps;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setFlightSteps(int steps) {
|
|
+ this.getHandle().flightSteps = steps;
|
|
+ }
|
|
+
|
|
@Override
|
|
public String toString() {
|
|
return "CraftShulkerBullet";
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
|
|
index 0db8aa840ea026d48215ac5dc80ffde5f12725b1..397e0df15a0e64e5bc522f62f3b327a5039ec4c8 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java
|
|
@@ -39,11 +39,31 @@ public class CraftThrownPotion extends CraftThrowableProjectile implements Throw
|
|
Validate.notNull(item, "ItemStack cannot be null.");
|
|
|
|
// The ItemStack must be a potion.
|
|
- Validate.isTrue(item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION, "ItemStack must be a lingering or splash potion. This item stack was " + item.getType() + ".");
|
|
+ //Validate.isTrue(item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION, "ItemStack must be a lingering or splash potion. This item stack was " + item.getType() + "."); // Paper - Projectile API
|
|
+ org.bukkit.inventory.meta.PotionMeta meta = (item.getType() == Material.LINGERING_POTION || item.getType() == Material.SPLASH_POTION) ? null : this.getPotionMeta(); // Paper - Projectile API
|
|
|
|
this.getHandle().setItem(CraftItemStack.asNMSCopy(item));
|
|
+ if (meta != null) this.setPotionMeta(meta); // Paper - Projectile API
|
|
}
|
|
|
|
+ // Paper start - Projectile API
|
|
+ @Override
|
|
+ public org.bukkit.inventory.meta.PotionMeta getPotionMeta() {
|
|
+ return (org.bukkit.inventory.meta.PotionMeta) CraftItemStack.getItemMeta(this.getHandle().getItemRaw(), Material.SPLASH_POTION);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setPotionMeta(org.bukkit.inventory.meta.PotionMeta meta) {
|
|
+ net.minecraft.world.item.ItemStack item = this.getHandle().getItem();
|
|
+ CraftItemStack.applyMetaToItem(item, meta);
|
|
+ this.getHandle().setItem(item); // Reset item
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void splash() {
|
|
+ this.getHandle().splash(null);
|
|
+ }
|
|
+ // Paper end
|
|
@Override
|
|
public net.minecraft.world.entity.projectile.ThrownPotion getHandle() {
|
|
return (net.minecraft.world.entity.projectile.ThrownPotion) entity;
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java
|
|
index 832981b07ef5c633ef00a382f56798ee87eec0df..faf071201b7c1414225a33fe9641eac9477d53c7 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java
|
|
@@ -59,5 +59,15 @@ public class CraftTrident extends CraftArrow implements Trident {
|
|
com.google.common.base.Preconditions.checkArgument(loyaltyLevel >= 0 && loyaltyLevel <= 127, "The loyalty level has to be between 0 and 127");
|
|
this.getHandle().setLoyalty((byte) loyaltyLevel);
|
|
}
|
|
+
|
|
+ @Override
|
|
+ public boolean hasDealtDamage() {
|
|
+ return this.getHandle().dealtDamage;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void setHasDealtDamage(boolean hasDealtDamage) {
|
|
+ this.getHandle().dealtDamage = hasDealtDamage;
|
|
+ }
|
|
// Paper end
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
|
index f3fcaf02a7718e20c1779934687a718e28a1d55a..3e5abea2f814a0a364cf87ff4ce1b1718ba2ddac 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
|
|
@@ -278,12 +278,20 @@ public final class CraftItemStack extends ItemStack {
|
|
public ItemMeta getItemMeta() {
|
|
return CraftItemStack.getItemMeta(this.handle);
|
|
}
|
|
+ // Paper start
|
|
+ public static void applyMetaToItem(net.minecraft.world.item.ItemStack itemStack, ItemMeta meta) {
|
|
+ ((org.bukkit.craftbukkit.inventory.CraftMetaItem) meta).applyToItem(itemStack.getOrCreateTag());
|
|
+ }
|
|
|
|
public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item) {
|
|
+ return getItemMeta(item, CraftItemStack.getType(item));
|
|
+ }
|
|
+ public static ItemMeta getItemMeta(net.minecraft.world.item.ItemStack item, Material material) {
|
|
+ // Paper end
|
|
if (!CraftItemStack.hasItemMeta(item)) {
|
|
- return CraftItemFactory.instance().getItemMeta(CraftItemStack.getType(item));
|
|
+ return CraftItemFactory.instance().getItemMeta(material); // Paper
|
|
}
|
|
- switch (CraftItemStack.getType(item)) {
|
|
+ switch (material) { // Paper
|
|
case WRITTEN_BOOK:
|
|
return new CraftMetaBookSigned(item.getTag());
|
|
case WRITABLE_BOOK:
|