diff --git a/bedwars-api/pom.xml b/bedwars-api/pom.xml index cc2a286ee..733d6f250 100644 --- a/bedwars-api/pom.xml +++ b/bedwars-api/pom.xml @@ -5,7 +5,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT 4.0.0 bedwars-api diff --git a/bedwars-plugin/pom.xml b/bedwars-plugin/pom.xml index 3005f0e1f..a108a7702 100644 --- a/bedwars-plugin/pom.xml +++ b/bedwars-plugin/pom.xml @@ -5,7 +5,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT 4.0.0 bedwars-plugin @@ -187,6 +187,11 @@ versionsupport_v1_20_R1 ${project.version} + + com.andrei1058.bedwars + versionsupport_v1_20_R2 + ${project.version} + com.andrei1058.bedwars versionsupport-common diff --git a/pom.xml b/pom.xml index 7e211c240..904ebdc36 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.andrei1058.bedwars BedWars1058 pom - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT UTF-8 @@ -112,6 +112,7 @@ versionsupport_v1_19_R2 versionsupport_v1_19_R3 versionsupport_v1_20_R1 + versionsupport_v1_20_R2 diff --git a/resetadapter_aswm/pom.xml b/resetadapter_aswm/pom.xml index cf32cec88..6725d96a6 100644 --- a/resetadapter_aswm/pom.xml +++ b/resetadapter_aswm/pom.xml @@ -7,7 +7,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT resetadapter-aswm diff --git a/resetadapter_slime/pom.xml b/resetadapter_slime/pom.xml index 8beccd4e4..f551ca914 100644 --- a/resetadapter_slime/pom.xml +++ b/resetadapter_slime/pom.xml @@ -7,7 +7,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT resetadapter-slime diff --git a/resetadapter_slimepaper/pom.xml b/resetadapter_slimepaper/pom.xml index d35e03e56..5a7422179 100644 --- a/resetadapter_slimepaper/pom.xml +++ b/resetadapter_slimepaper/pom.xml @@ -7,7 +7,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT resetadapter-slimepaper diff --git a/versionsupport_1_12_R1/pom.xml b/versionsupport_1_12_R1/pom.xml index 97da5e59a..d0bf8ca1f 100644 --- a/versionsupport_1_12_R1/pom.xml +++ b/versionsupport_1_12_R1/pom.xml @@ -10,7 +10,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT diff --git a/versionsupport_1_8_R3/pom.xml b/versionsupport_1_8_R3/pom.xml index baeeef32a..d2800299b 100644 --- a/versionsupport_1_8_R3/pom.xml +++ b/versionsupport_1_8_R3/pom.xml @@ -7,7 +7,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT versionsupport_1_8_R3 diff --git a/versionsupport_common/pom.xml b/versionsupport_common/pom.xml index 4064fb83d..a5b5a4003 100644 --- a/versionsupport_common/pom.xml +++ b/versionsupport_common/pom.xml @@ -5,7 +5,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT 4.0.0 diff --git a/versionsupport_v1_16_R3/pom.xml b/versionsupport_v1_16_R3/pom.xml index d17b5c5eb..9e1d04258 100644 --- a/versionsupport_v1_16_R3/pom.xml +++ b/versionsupport_v1_16_R3/pom.xml @@ -5,7 +5,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT 4.0.0 diff --git a/versionsupport_v1_17_R1/pom.xml b/versionsupport_v1_17_R1/pom.xml index 3faace93f..7ca5af14c 100644 --- a/versionsupport_v1_17_R1/pom.xml +++ b/versionsupport_v1_17_R1/pom.xml @@ -5,7 +5,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT 4.0.0 diff --git a/versionsupport_v1_18_R2/pom.xml b/versionsupport_v1_18_R2/pom.xml index 338ccb682..def00468f 100644 --- a/versionsupport_v1_18_R2/pom.xml +++ b/versionsupport_v1_18_R2/pom.xml @@ -5,7 +5,7 @@ BedWars1058 com.andrei1058.bedwars - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT 4.0.0 diff --git a/versionsupport_v1_19_R2/pom.xml b/versionsupport_v1_19_R2/pom.xml index aedb55828..354b6ea9d 100644 --- a/versionsupport_v1_19_R2/pom.xml +++ b/versionsupport_v1_19_R2/pom.xml @@ -6,7 +6,7 @@ com.andrei1058.bedwars BedWars1058 - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT versionsupport_v1_19_R2 diff --git a/versionsupport_v1_19_R3/pom.xml b/versionsupport_v1_19_R3/pom.xml index b2de132f7..f0bcac348 100644 --- a/versionsupport_v1_19_R3/pom.xml +++ b/versionsupport_v1_19_R3/pom.xml @@ -6,7 +6,7 @@ com.andrei1058.bedwars BedWars1058 - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT versionsupport_v1_19_R3 diff --git a/versionsupport_v1_20_R1/pom.xml b/versionsupport_v1_20_R1/pom.xml index 2948b3d10..fd7042cd4 100644 --- a/versionsupport_v1_20_R1/pom.xml +++ b/versionsupport_v1_20_R1/pom.xml @@ -6,7 +6,7 @@ com.andrei1058.bedwars BedWars1058 - 23.10-SNAPSHOT + 23.10.1-SNAPSHOT versionsupport_v1_20_R1 diff --git a/versionsupport_v1_20_R2/pom.xml b/versionsupport_v1_20_R2/pom.xml new file mode 100644 index 000000000..881cb95ad --- /dev/null +++ b/versionsupport_v1_20_R2/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + + com.andrei1058.bedwars + BedWars1058 + 23.10.1-SNAPSHOT + + + versionsupport_v1_20_R2 + + + 1.19 + 1.19 + UTF-8 + + + + + com.andrei1058.bedwars + bedwars-api + ${project.version} + jar + provided + + + com.andrei1058.bedwars + versionsupport-common + ${project.version} + jar + provided + + + org.spigotmc + spigot + 1.20.2-R0.1-SNAPSHOT + jar + provided + + + + + + + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 19 + 19 + + + + + + \ No newline at end of file diff --git a/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableAttributes.java b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableAttributes.java new file mode 100644 index 000000000..2ca63287f --- /dev/null +++ b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableAttributes.java @@ -0,0 +1,5 @@ +package com.andrei1058.bedwars.support.version.v1_20_R2.despawnable; + +public record DespawnableAttributes(DespawnableType type, double speed, double health, double damage, int despawnSeconds) { + +} diff --git a/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableFactory.java b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableFactory.java new file mode 100644 index 000000000..34124d3f4 --- /dev/null +++ b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableFactory.java @@ -0,0 +1,27 @@ +package com.andrei1058.bedwars.support.version.v1_20_R2.despawnable; + +import com.andrei1058.bedwars.api.arena.team.ITeam; +import com.andrei1058.bedwars.api.server.VersionSupport; +import org.bukkit.Location; +import org.bukkit.entity.LivingEntity; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class DespawnableFactory { + + private final VersionSupport versionSupport; + private final List> providers = new ArrayList<>(); + + public DespawnableFactory(VersionSupport versionSupport) { + this.versionSupport = versionSupport; + providers.add(new TeamIronGolem()); + providers.add(new TeamSilverfish()); + } + + public LivingEntity spawn(@NotNull DespawnableAttributes attr, @NotNull Location location, @NotNull ITeam team){ + return providers.stream().filter(provider -> provider.getType() == attr.type()) + .findFirst().orElseThrow().spawn(attr, location,team, versionSupport); + } +} diff --git a/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableProvider.java b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableProvider.java new file mode 100644 index 000000000..a8dffa4a4 --- /dev/null +++ b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableProvider.java @@ -0,0 +1,71 @@ +package com.andrei1058.bedwars.support.version.v1_20_R2.despawnable; + +import com.andrei1058.bedwars.api.arena.team.ITeam; +import com.andrei1058.bedwars.api.server.VersionSupport; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityCreature; +import net.minecraft.world.entity.EntityInsentient; +import net.minecraft.world.entity.EntityLiving; +import net.minecraft.world.entity.ai.attributes.GenericAttributes; +import net.minecraft.world.entity.ai.goal.PathfinderGoal; +import net.minecraft.world.entity.ai.goal.PathfinderGoalSelector; +import net.minecraft.world.entity.ai.goal.target.PathfinderGoalNearestAttackableTarget; +import net.minecraft.world.entity.player.EntityHuman; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public abstract class DespawnableProvider { + + abstract DespawnableType getType(); + + abstract String getDisplayName(DespawnableAttributes attr, ITeam team); + + abstract T spawn(@NotNull DespawnableAttributes attr, @NotNull Location location, @NotNull ITeam team, VersionSupport api); + + protected boolean notSameTeam(@NotNull Entity entity, ITeam team, @NotNull VersionSupport api) { + var despawnable = api.getDespawnablesList().getOrDefault(entity.getBukkitEntity().getUniqueId(), null); + return null == despawnable || despawnable.getTeam() != team; + } + + protected PathfinderGoalSelector getTargetSelector(@NotNull EntityCreature entityLiving) { + return entityLiving.bP; + } + + protected PathfinderGoalSelector getGoalSelector(@NotNull EntityCreature entityLiving) { + return entityLiving.bO; + } + + protected void clearSelectors(@NotNull EntityCreature entityLiving) { + entityLiving.bO.b().clear(); + entityLiving.bP.b().clear(); + } + + protected PathfinderGoal getTargetGoal(EntityInsentient entity, ITeam team, VersionSupport api) { + return new PathfinderGoalNearestAttackableTarget<>(entity, EntityLiving.class, 20, true, false, + entityLiving -> { + if (entityLiving instanceof EntityHuman) { + return !((EntityHuman) entityLiving).getBukkitEntity().isDead() && + !team.wasMember(((EntityHuman) entityLiving).getBukkitEntity().getUniqueId()) && + !team.getArena().isReSpawning(((EntityHuman) entityLiving).getBukkitEntity().getUniqueId()) + && !team.getArena().isSpectator(((EntityHuman) entityLiving).getBukkitEntity().getUniqueId()); + } + return notSameTeam(entityLiving, team, api); + }); + } + + protected void applyDefaultSettings(org.bukkit.entity.@NotNull LivingEntity bukkitEntity, DespawnableAttributes attr, + ITeam team) { + bukkitEntity.setRemoveWhenFarAway(false); + bukkitEntity.setPersistent(true); + bukkitEntity.setCustomNameVisible(true); + bukkitEntity.setCustomName(getDisplayName(attr, team)); + + var entity = ((EntityInsentient)((CraftEntity)bukkitEntity).getHandle()); + Objects.requireNonNull(entity.a(GenericAttributes.a)).a(attr.health()); + Objects.requireNonNull(entity.a(GenericAttributes.d)).a(attr.speed()); + Objects.requireNonNull(entity.a(GenericAttributes.f)).a(attr.damage()); + } +} diff --git a/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableType.java b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableType.java new file mode 100644 index 000000000..fe6f773df --- /dev/null +++ b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/DespawnableType.java @@ -0,0 +1,6 @@ +package com.andrei1058.bedwars.support.version.v1_20_R2.despawnable; + +public enum DespawnableType { + IRON_GOLEM, + SILVERFISH +} diff --git a/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/TeamIronGolem.java b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/TeamIronGolem.java new file mode 100644 index 000000000..f4e732d67 --- /dev/null +++ b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/TeamIronGolem.java @@ -0,0 +1,58 @@ +package com.andrei1058.bedwars.support.version.v1_20_R2.despawnable; + +import com.andrei1058.bedwars.api.arena.team.ITeam; +import com.andrei1058.bedwars.api.language.Language; +import com.andrei1058.bedwars.api.language.Messages; +import com.andrei1058.bedwars.api.server.VersionSupport; +import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; +import net.minecraft.world.entity.ai.goal.PathfinderGoalMeleeAttack; +import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomLookaround; +import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomStroll; +import net.minecraft.world.entity.ai.goal.target.PathfinderGoalHurtByTarget; +import net.minecraft.world.entity.animal.EntityIronGolem; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.IronGolem; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class TeamIronGolem extends DespawnableProvider { + + @Override + public DespawnableType getType() { + return DespawnableType.IRON_GOLEM; + } + + @Override + String getDisplayName(@NotNull DespawnableAttributes attr, @NotNull ITeam team) { + Language lang = Language.getDefaultLanguage(); + return lang.m(Messages.SHOP_UTILITY_NPC_IRON_GOLEM_NAME).replace("{despawn}", String.valueOf(attr.despawnSeconds()) + .replace("{health}", StringUtils.repeat(lang.m(Messages.FORMATTING_DESPAWNABLE_UTILITY_NPC_HEALTH) + " ", 10)) + .replace("{TeamColor}", team.getColor().chat().toString()) + ); + } + + public @NotNull IronGolem spawn(@NotNull DespawnableAttributes attr, @NotNull Location location, @NotNull ITeam team, VersionSupport api) { + + var bukkitEntity = (IronGolem) Objects.requireNonNull(location.getWorld()).spawnEntity(location, EntityType.IRON_GOLEM); + applyDefaultSettings(bukkitEntity, attr, team); + + var entity = (EntityIronGolem) ((CraftEntity) bukkitEntity).getHandle(); + + clearSelectors(entity); + var goalSelector = getGoalSelector(entity); + var targetSelector = getTargetSelector(entity); + + goalSelector.a(1, new PathfinderGoalFloat(entity)); + goalSelector.a(2, new PathfinderGoalMeleeAttack(entity, 1.5D, false)); + goalSelector.a(3, new PathfinderGoalRandomStroll(entity, 1D)); + goalSelector.a(4, new PathfinderGoalRandomLookaround(entity)); + targetSelector.a(1, new PathfinderGoalHurtByTarget(entity)); + targetSelector.a(2, getTargetGoal(entity, team, api)); + + return bukkitEntity; + } +} diff --git a/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/TeamSilverfish.java b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/TeamSilverfish.java new file mode 100644 index 000000000..45477e35b --- /dev/null +++ b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/despawnable/TeamSilverfish.java @@ -0,0 +1,56 @@ +package com.andrei1058.bedwars.support.version.v1_20_R2.despawnable; + +import com.andrei1058.bedwars.api.arena.team.ITeam; +import com.andrei1058.bedwars.api.language.Language; +import com.andrei1058.bedwars.api.language.Messages; +import com.andrei1058.bedwars.api.server.VersionSupport; +import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; +import net.minecraft.world.entity.ai.goal.PathfinderGoalMeleeAttack; +import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomLookaround; +import net.minecraft.world.entity.ai.goal.PathfinderGoalRandomStroll; +import net.minecraft.world.entity.ai.goal.target.PathfinderGoalHurtByTarget; +import net.minecraft.world.entity.monster.EntitySilverfish; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Silverfish; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class TeamSilverfish extends DespawnableProvider { + @Override + public DespawnableType getType() { + return DespawnableType.SILVERFISH; + } + + @Override + String getDisplayName(@NotNull DespawnableAttributes attr, @NotNull ITeam team) { + Language lang = Language.getDefaultLanguage(); + return lang.m(Messages.SHOP_UTILITY_NPC_SILVERFISH_NAME).replace("{despawn}", String.valueOf(attr.despawnSeconds()) + .replace("{health}", StringUtils.repeat(lang.m(Messages.FORMATTING_DESPAWNABLE_UTILITY_NPC_HEALTH) + " ", 10)) + .replace("{TeamColor}", team.getColor().chat().toString()) + ); + } + + @Override + public Silverfish spawn(@NotNull DespawnableAttributes attr, @NotNull Location location, @NotNull ITeam team, VersionSupport api) { + var bukkitEntity = (Silverfish) Objects.requireNonNull(location.getWorld()).spawnEntity(location, EntityType.SILVERFISH); + applyDefaultSettings(bukkitEntity, attr, team); + + var entity = (EntitySilverfish) ((CraftEntity) bukkitEntity).getHandle(); + clearSelectors(entity); + + var goalSelector = getGoalSelector(entity); + var targetSelector = getTargetSelector(entity); + goalSelector.a(1, new PathfinderGoalFloat(entity)); + goalSelector.a(2, new PathfinderGoalMeleeAttack(entity, 1.9D, false)); + goalSelector.a(3, new PathfinderGoalRandomStroll(entity, 2D)); + goalSelector.a(4, new PathfinderGoalRandomLookaround(entity)); + targetSelector.a(1, new PathfinderGoalHurtByTarget(entity)); + targetSelector.a(2, getTargetGoal(entity, team, api)); + + return bukkitEntity; + } +} diff --git a/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/v1_20_R2.java b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/v1_20_R2.java new file mode 100644 index 000000000..31ce34f5f --- /dev/null +++ b/versionsupport_v1_20_R2/src/main/java/com/andrei1058/bedwars/support/version/v1_20_R2/v1_20_R2.java @@ -0,0 +1,836 @@ +package com.andrei1058.bedwars.support.version.v1_20_R2; + +import com.andrei1058.bedwars.api.arena.IArena; +import com.andrei1058.bedwars.api.arena.shop.ShopHolo; +import com.andrei1058.bedwars.api.arena.team.ITeam; +import com.andrei1058.bedwars.api.arena.team.TeamColor; +import com.andrei1058.bedwars.api.entity.Despawnable; +import com.andrei1058.bedwars.api.events.player.PlayerKillEvent; +import com.andrei1058.bedwars.api.language.Language; +import com.andrei1058.bedwars.api.language.Messages; +import com.andrei1058.bedwars.api.server.VersionSupport; +import com.andrei1058.bedwars.support.version.common.VersionCommon; +import com.andrei1058.bedwars.support.version.v1_20_R2.despawnable.DespawnableAttributes; +import com.andrei1058.bedwars.support.version.v1_20_R2.despawnable.DespawnableFactory; +import com.andrei1058.bedwars.support.version.v1_20_R2.despawnable.DespawnableType; +import com.mojang.datafixers.util.Pair; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import net.minecraft.core.particles.ParticleParamRedstone; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.*; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.EntityPlayer; +import net.minecraft.server.network.PlayerConnection; +import net.minecraft.world.entity.EntityLiving; +import net.minecraft.world.entity.EnumItemSlot; +import net.minecraft.world.entity.item.EntityTNTPrimed; +import net.minecraft.world.entity.projectile.EntityFireball; +import net.minecraft.world.entity.projectile.IProjectile; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.*; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockBase; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.data.type.Bed; +import org.bukkit.block.data.type.Ladder; +import org.bukkit.block.data.type.WallSign; +import org.bukkit.command.Command; +import org.bukkit.craftbukkit.v1_20_R2.CraftServer; +import org.bukkit.craftbukkit.v1_20_R2.entity.*; +import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; +import org.bukkit.entity.*; +import org.bukkit.event.inventory.InventoryEvent; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.plugin.Plugin; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; + +import java.lang.reflect.Field; +import java.util.*; +import java.util.logging.Level; + +@SuppressWarnings("unused") +public class v1_20_R2 extends VersionSupport { + + private final DespawnableFactory despawnableFactory; + + public v1_20_R2(Plugin plugin, String name) { + super(plugin, name); + loadDefaultEffects(); + this.despawnableFactory = new DespawnableFactory(this); + } + + @Override + public void registerVersionListeners() { + new VersionCommon(this); + } + + @Override + public void registerCommand(String name, Command cmd) { + ((CraftServer) getPlugin().getServer()).getCommandMap().register(name, cmd); + } + + @Override + public String getTag(org.bukkit.inventory.ItemStack itemStack, String key) { + var tag = getTag(itemStack); + return tag == null ? null : tag.e(key) ? tag.l(key) : null; + } + + @Override + public void sendTitle(@NotNull Player p, String title, String subtitle, int fadeIn, int stay, int fadeOut) { + p.sendTitle(title == null ? " " : title, subtitle == null ? " " : subtitle, fadeIn, stay, fadeOut); + } + + public void spawnSilverfish(Location loc, ITeam bedWarsTeam, double speed, double health, int despawn, double damage) { + var attr = new DespawnableAttributes(DespawnableType.SILVERFISH, speed, health, damage, despawn); + var entity = despawnableFactory.spawn(attr, loc, bedWarsTeam); + + new Despawnable( + entity, + bedWarsTeam, despawn, + Messages.SHOP_UTILITY_NPC_SILVERFISH_NAME, + PlayerKillEvent.PlayerKillCause.SILVERFISH_FINAL_KILL, + PlayerKillEvent.PlayerKillCause.SILVERFISH + ); + } + + @Override + public void spawnIronGolem(Location loc, ITeam bedWarsTeam, double speed, double health, int despawn) { + var attr = new DespawnableAttributes(DespawnableType.IRON_GOLEM, speed, health, 4, despawn); + var entity = despawnableFactory.spawn(attr, loc, bedWarsTeam); + new Despawnable( + entity, + bedWarsTeam, despawn, + Messages.SHOP_UTILITY_NPC_IRON_GOLEM_NAME, + PlayerKillEvent.PlayerKillCause.IRON_GOLEM_FINAL_KILL, + PlayerKillEvent.PlayerKillCause.IRON_GOLEM + ); + } + + @Override + public void playAction(@NotNull Player p, String text) { + p.spigot().sendMessage( + ChatMessageType.ACTION_BAR, + new TextComponent(ChatColor.translateAlternateColorCodes('&', text) + ) + ); + } + + @Override + public boolean isBukkitCommandRegistered(String name) { + return ((CraftServer) getPlugin().getServer()).getCommandMap().getCommand(name) != null; + } + + @Override + public org.bukkit.inventory.ItemStack getItemInHand(@NotNull Player p) { + return p.getInventory().getItemInMainHand(); + } + + @Override + public void hideEntity(@NotNull Entity e, Player p) { + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(e.getEntityId()); + this.sendPacket(p, packet); + } + + @Override + public void minusAmount(Player p, org.bukkit.inventory.@NotNull ItemStack i, int amount) { + if (i.getAmount() - amount <= 0) { + if (p.getInventory().getItemInOffHand().equals(i)) { + p.getInventory().setItemInOffHand(null); + } else { + p.getInventory().removeItem(i); + } + return; + } + i.setAmount(i.getAmount() - amount); + + // todo this is marked as unstable on 1.20 for some reason + p.updateInventory(); + } + + @Override + public void setSource(TNTPrimed tnt, Player owner) { + EntityLiving nmsEntityLiving = (((CraftLivingEntity) owner).getHandle()); + EntityTNTPrimed nmsTNT = (((CraftTNTPrimed) tnt).getHandle()); + try { + Field sourceField = EntityTNTPrimed.class.getDeclaredField("d"); + sourceField.setAccessible(true); + sourceField.set(nmsTNT, nmsEntityLiving); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Override + public boolean isArmor(org.bukkit.inventory.ItemStack itemStack) { + var i = getItem(itemStack); + if (null == i) return false; + return i instanceof ItemArmor || i instanceof ItemElytra; + + } + + @Override + public boolean isTool(org.bukkit.inventory.ItemStack itemStack) { + var i = getItem(itemStack); + if (null == i) return false; + return i instanceof ItemTool; + } + + @Override + public boolean isSword(org.bukkit.inventory.ItemStack itemStack) { + var i = getItem(itemStack); + if (null == i) return false; + return i instanceof ItemSword; + } + + @Override + public boolean isAxe(org.bukkit.inventory.ItemStack itemStack) { + var i = getItem(itemStack); + if (null == i) return false; + return i instanceof ItemAxe; + } + + @Override + public boolean isBow(org.bukkit.inventory.ItemStack itemStack) { + var i = getItem(itemStack); + if (null == i) return false; + return i instanceof ItemBow; + } + + @Override + public boolean isProjectile(org.bukkit.inventory.ItemStack itemStack) { + var entity = getEntity(itemStack); + if (null == entity) return false; + return entity instanceof IProjectile; + } + + @Override + public boolean isInvisibilityPotion(org.bukkit.inventory.@NotNull ItemStack itemStack) { + if (!itemStack.getType().equals(org.bukkit.Material.POTION)) return false; + + org.bukkit.inventory.meta.PotionMeta pm = (org.bukkit.inventory.meta.PotionMeta) itemStack.getItemMeta(); + + return pm != null && pm.hasCustomEffects() && pm.hasCustomEffect(org.bukkit.potion.PotionEffectType.INVISIBILITY); + } + + @Override + public void registerEntities() { + } + + @Override + public void spawnShop(@NotNull Location loc, String name1, List players, IArena arena) { + Location l = loc.clone(); + + if (l.getWorld() == null) return; + Villager vlg = (Villager) l.getWorld().spawnEntity(loc, EntityType.VILLAGER); + vlg.setAI(false); + vlg.setRemoveWhenFarAway(false); + vlg.setCollidable(false); + vlg.setInvulnerable(true); + vlg.setSilent(true); + + for (Player p : players) { + String[] name = Language.getMsg(p, name1).split(","); + if (name.length == 1) { + ArmorStand a = createArmorStand(name[0], l.clone().add(0, 1.85, 0)); + new ShopHolo(Language.getPlayerLanguage(p).getIso(), a, null, l, arena); + } else { + ArmorStand a = createArmorStand(name[0], l.clone().add(0, 2.1, 0)); + ArmorStand b = createArmorStand(name[1], l.clone().add(0, 1.85, 0)); + new ShopHolo(Language.getPlayerLanguage(p).getIso(), a, b, l, arena); + } + } + for (ShopHolo sh : ShopHolo.getShopHolo()) { + if (sh.getA() == arena) { + sh.update(); + } + } + } + + @Override + public double getDamage(org.bukkit.inventory.ItemStack i) { + var tag = getTag(i); + if (null == tag) { + throw new RuntimeException("Provided item has no Tag"); + } + return tag.k("generic.attackDamage"); + } + + private static ArmorStand createArmorStand(String name, Location loc) { + if (loc == null) return null; + if (loc.getWorld() == null) return null; + ArmorStand a = loc.getWorld().spawn(loc, ArmorStand.class); + a.setGravity(false); + a.setVisible(false); + a.setCustomNameVisible(true); + a.setCustomName(name); + return a; + } + + @Override + public void voidKill(Player p) { + EntityPlayer player = getPlayer(p); + player.a(player.dM().m(), 1000); + } + + @Override + public void hideArmor(@NotNull Player victim, Player receiver) { + List> items = new ArrayList<>(); + items.add(new Pair<>(EnumItemSlot.f, new ItemStack(Item.b(0)))); + items.add(new Pair<>(EnumItemSlot.e, new ItemStack(Item.b(0)))); + items.add(new Pair<>(EnumItemSlot.d, new ItemStack(Item.b(0)))); + items.add(new Pair<>(EnumItemSlot.c, new ItemStack(Item.b(0)))); + PacketPlayOutEntityEquipment packet1 = new PacketPlayOutEntityEquipment(victim.getEntityId(), items); + sendPacket(receiver, packet1); + } + + @Override + public void showArmor(@NotNull Player victim, Player receiver) { + List> items = new ArrayList<>(); + items.add(new Pair<>(EnumItemSlot.f, CraftItemStack.asNMSCopy(victim.getInventory().getHelmet()))); + items.add(new Pair<>(EnumItemSlot.e, CraftItemStack.asNMSCopy(victim.getInventory().getChestplate()))); + items.add(new Pair<>(EnumItemSlot.d, CraftItemStack.asNMSCopy(victim.getInventory().getLeggings()))); + items.add(new Pair<>(EnumItemSlot.c, CraftItemStack.asNMSCopy(victim.getInventory().getBoots()))); + PacketPlayOutEntityEquipment packet1 = new PacketPlayOutEntityEquipment(victim.getEntityId(), items); + sendPacket(receiver, packet1); + } + + @Override + public void spawnDragon(Location l, ITeam bwt) { + if (l == null || l.getWorld() == null) { + getPlugin().getLogger().log(Level.WARNING, "Could not spawn Dragon. Location is null"); + return; + } + EnderDragon ed = (EnderDragon) l.getWorld().spawnEntity(l, EntityType.ENDER_DRAGON); + ed.setPhase(EnderDragon.Phase.CIRCLING); + } + + @Override + public void colorBed(ITeam bwt) { + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + BlockState bed = bwt.getBed().clone().add(x, 0, z).getBlock().getState(); + if (bed instanceof Bed) { + bed.setType(bwt.getColor().bedMaterial()); + bed.update(); + } + } + } + } + + @Override + public void registerTntWhitelist(float endStoneBlast, float glassBlast) { + try { + // blast resistance + Field field = BlockBase.class.getDeclaredField("aF"); + field.setAccessible(true); + // end stone + field.set(Blocks.fz, endStoneBlast); + // obsidian +// field.set(Blocks.co, glassBlast); + // standard glass + field.set(Blocks.aQ, glassBlast); + + var coloredGlass = new net.minecraft.world.level.block.Block[]{ + Blocks.ej, Blocks.ek, Blocks.el, Blocks.em, + Blocks.en, Blocks.eo, Blocks.ep, Blocks.eq, + Blocks.er, Blocks.es, Blocks.et, Blocks.eu, + Blocks.ev, Blocks.ew, Blocks.ex, Blocks.ey, + + // tinted glass + Blocks.qB, + }; + + Arrays.stream(coloredGlass).forEach( + glass -> { + try { + field.set(glass, glassBlast); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + ); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + @Override + public void setBlockTeamColor(@NotNull Block block, TeamColor teamColor) { + if (block.getType().toString().contains("STAINED_GLASS") || block.getType().toString().equals("GLASS")) { + block.setType(teamColor.glassMaterial()); + } else if (block.getType().toString().contains("_TERRACOTTA")) { + block.setType(teamColor.glazedTerracottaMaterial()); + } else if (block.getType().toString().contains("_WOOL")) { + block.setType(teamColor.woolMaterial()); + } + } + + @Override + public void setCollide(@NotNull Player p, IArena a, boolean value) { + p.setCollidable(value); + if (a == null) return; + a.updateSpectatorCollideRule(p, value); + } + + @Override + public org.bukkit.inventory.ItemStack addCustomData(org.bukkit.inventory.ItemStack i, String data) { + var tag = getCreateTag(i); + tag.a(VersionSupport.PLUGIN_TAG_GENERIC_KEY, data); + return applyTag(i, tag); + } + + @Override + public org.bukkit.inventory.ItemStack setTag(org.bukkit.inventory.ItemStack itemStack, String key, String value) { + var tag = getCreateTag(itemStack); + tag.a(key, value); + return applyTag(itemStack, tag); + } + + @Override + public boolean isCustomBedWarsItem(org.bukkit.inventory.ItemStack i) { + return getCreateTag(i).e(VersionSupport.PLUGIN_TAG_GENERIC_KEY); + } + + @Override + public String getCustomData(org.bukkit.inventory.ItemStack i) { + return getCreateTag(i).l(VersionSupport.PLUGIN_TAG_GENERIC_KEY); + } + + @Override + public org.bukkit.inventory.ItemStack colourItem(org.bukkit.inventory.ItemStack itemStack, ITeam bedWarsTeam) { + if (itemStack == null) return null; + String type = itemStack.getType().toString(); + if (isBed(itemStack.getType())) { + return new org.bukkit.inventory.ItemStack(bedWarsTeam.getColor().bedMaterial(), itemStack.getAmount()); + } else if (type.contains("_STAINED_GLASS_PANE")) { + return new org.bukkit.inventory.ItemStack(bedWarsTeam.getColor().glassPaneMaterial(), itemStack.getAmount()); + } else if (type.contains("STAINED_GLASS") || type.equals("GLASS")) { + return new org.bukkit.inventory.ItemStack(bedWarsTeam.getColor().glassMaterial(), itemStack.getAmount()); + } else if (type.contains("_TERRACOTTA")) { + return new org.bukkit.inventory.ItemStack(bedWarsTeam.getColor().glazedTerracottaMaterial(), itemStack.getAmount()); + } else if (type.contains("_WOOL")) { + return new org.bukkit.inventory.ItemStack(bedWarsTeam.getColor().woolMaterial(), itemStack.getAmount()); + } + return itemStack; + } + + @Override + public org.bukkit.inventory.ItemStack createItemStack(String material, int amount, short data) { + org.bukkit.inventory.ItemStack i; + try { + i = new org.bukkit.inventory.ItemStack(org.bukkit.Material.valueOf(material), amount); + } catch (Exception ex) { + getPlugin().getLogger().log(Level.WARNING, material + " is not a valid " + getName() + " material!"); + i = new org.bukkit.inventory.ItemStack(org.bukkit.Material.BEDROCK); + } + return i; + } + + @Override + public org.bukkit.Material materialFireball() { + return org.bukkit.Material.FIRE_CHARGE; + } + + @Override + public org.bukkit.Material materialPlayerHead() { + return org.bukkit.Material.PLAYER_HEAD; + } + + @Override + public org.bukkit.Material materialSnowball() { + return org.bukkit.Material.SNOWBALL; + } + + @Override + public org.bukkit.Material materialGoldenHelmet() { + return org.bukkit.Material.GOLDEN_HELMET; + } + + @Override + public org.bukkit.Material materialGoldenChestPlate() { + return org.bukkit.Material.GOLDEN_CHESTPLATE; + } + + @Override + public org.bukkit.Material materialGoldenLeggings() { + return org.bukkit.Material.GOLDEN_LEGGINGS; + } + + @Override + public org.bukkit.Material materialNetheriteHelmet() { + return Material.NETHERITE_HELMET; + } + + @Override + public org.bukkit.Material materialNetheriteChestPlate() { + return Material.NETHERITE_CHESTPLATE; + } + + @Override + public org.bukkit.Material materialNetheriteLeggings() { + return Material.NETHERITE_LEGGINGS; + } + + @Override + public org.bukkit.Material materialElytra() { + return Material.ELYTRA; + } + + @Override + public org.bukkit.Material materialCake() { + return org.bukkit.Material.CAKE; + } + + @Override + public org.bukkit.Material materialCraftingTable() { + return org.bukkit.Material.CRAFTING_TABLE; + } + + @Override + public org.bukkit.Material materialEnchantingTable() { + return org.bukkit.Material.ENCHANTING_TABLE; + } + + @Override + public org.bukkit.Material woolMaterial() { + return org.bukkit.Material.WHITE_WOOL; + } + + @Override + public String getShopUpgradeIdentifier(org.bukkit.inventory.ItemStack itemStack) { + var tag = getCreateTag(itemStack); + return tag.e(VersionSupport.PLUGIN_TAG_TIER_KEY) ? tag.l(VersionSupport.PLUGIN_TAG_TIER_KEY) : "null"; + } + + @Override + public org.bukkit.inventory.ItemStack setShopUpgradeIdentifier(org.bukkit.inventory.ItemStack itemStack, String identifier) { + var tag = getCreateTag(itemStack); + tag.a(VersionSupport.PLUGIN_TAG_TIER_KEY, identifier); + return applyTag(itemStack, tag); + } + + @Override + public org.bukkit.inventory.ItemStack getPlayerHead(Player player, org.bukkit.inventory.ItemStack copyTagFrom) { + org.bukkit.inventory.ItemStack head = new org.bukkit.inventory.ItemStack(materialPlayerHead()); + + if (copyTagFrom != null) { + var tag = getTag(copyTagFrom); + head = applyTag(head, tag); + } + + var meta = head.getItemMeta(); + if (meta instanceof SkullMeta) { + ((SkullMeta) meta).setOwnerProfile(player.getPlayerProfile()); + } + head.setItemMeta(meta); + return head; + } + + @Override + public void sendPlayerSpawnPackets(Player respawned, IArena arena) { + if (respawned == null) return; + if (arena == null) return; + if (!arena.isPlayer(respawned)) return; + + // if method was used when the player was still in re-spawning screen + if (arena.getRespawnSessions().containsKey(respawned)) return; + + EntityPlayer entityPlayer = getPlayer(respawned); + PacketPlayOutSpawnEntity show = new PacketPlayOutSpawnEntity(entityPlayer); + PacketPlayOutEntityVelocity playerVelocity = new PacketPlayOutEntityVelocity(entityPlayer); + // we send head rotation packet because sometimes on respawn others see him with bad rotation + PacketPlayOutEntityHeadRotation head = new PacketPlayOutEntityHeadRotation(entityPlayer, getCompressedAngle(entityPlayer.getBukkitYaw())); + + // retrieve current armor and in-hand items + // we send a packet later for timing issues where other players do not see them + List> list = getPlayerEquipment(entityPlayer); + + + for (Player p : arena.getPlayers()) { + if (p == null) continue; + if (p.equals(respawned)) continue; + // if p is in re-spawning screen continue + if (arena.getRespawnSessions().containsKey(p)) continue; + + EntityPlayer boundTo = getPlayer(p); + if (p.getWorld().equals(respawned.getWorld())) { + if (respawned.getLocation().distance(p.getLocation()) <= arena.getRenderDistance()) { + + // send respawned player to regular players + this.sendPackets( + p, show, head, playerVelocity, + new PacketPlayOutEntityEquipment(respawned.getEntityId(), list) + ); + + // send nearby players to respawned player + // if the player has invisibility hide armor + if (p.hasPotionEffect(PotionEffectType.INVISIBILITY)) { + hideArmor(p, respawned); + } else { + + PacketPlayOutSpawnEntity show2 = new PacketPlayOutSpawnEntity(boundTo); + PacketPlayOutEntityVelocity playerVelocity2 = new PacketPlayOutEntityVelocity(boundTo); + PacketPlayOutEntityHeadRotation head2 = new PacketPlayOutEntityHeadRotation(boundTo, getCompressedAngle(boundTo.getBukkitYaw())); + this.sendPackets(respawned, show2, playerVelocity2, head2); + + showArmor(p, respawned); + } + } + } + } + + for (Player spectator : arena.getSpectators()) { + if (spectator == null) continue; + if (spectator.equals(respawned)) continue; + EntityPlayer boundTo = ((CraftPlayer) spectator).getHandle(); + respawned.hidePlayer(getPlugin(), spectator); + if (spectator.getWorld().equals(respawned.getWorld())) { + if (respawned.getLocation().distance(spectator.getLocation()) <= arena.getRenderDistance()) { + + // send respawned player to spectator + this.sendPackets( + spectator, show, playerVelocity, + new PacketPlayOutEntityEquipment(respawned.getEntityId(), list), + new PacketPlayOutEntityHeadRotation(entityPlayer, getCompressedAngle(entityPlayer.getBukkitYaw())) + ); + } + } + } + } + + @Override + public String getInventoryName(@NotNull InventoryEvent e) { + return e.getView().getTitle(); + } + + @Override + public void setUnbreakable(@NotNull ItemMeta itemMeta) { + itemMeta.setUnbreakable(true); + } + + @Override + public String getMainLevel() { + //noinspection deprecation + return ((DedicatedServer) MinecraftServer.getServer()).a().m; + } + + @Override + public int getVersion() { + return 9; + } + + @Override + public void setJoinSignBackground(@NotNull BlockState b, org.bukkit.Material material) { + if (b.getBlockData() instanceof WallSign) { + b.getBlock().getRelative(((WallSign) b.getBlockData()).getFacing().getOppositeFace()).setType(material); + } + } + + @Override + public void spigotShowPlayer(Player victim, @NotNull Player receiver) { + receiver.showPlayer(getPlugin(), victim); + } + + @Override + public void spigotHidePlayer(Player victim, @NotNull Player receiver) { + receiver.hidePlayer(getPlugin(), victim); + } + + @Override + public Fireball setFireballDirection(Fireball fireball, @NotNull Vector vector) { + EntityFireball fb = ((CraftFireball) fireball).getHandle(); + fb.b = vector.getX() * 0.1D; + fb.c = vector.getY() * 0.1D; + fb.d = vector.getZ() * 0.1D; + return (Fireball) fb.getBukkitEntity(); + } + + @Override + public void playRedStoneDot(@NotNull Player player) { + Color color = Color.RED; + PacketPlayOutWorldParticles particlePacket = new PacketPlayOutWorldParticles( + new ParticleParamRedstone( + new Vector3f((float) color.getRed(), + (float) color.getGreen(), + (float) color.getBlue()), (float) 1 + ), + true, + player.getLocation().getX(), + player.getLocation().getY() + 2.6, + player.getLocation().getZ(), + 0, 0, 0, 0, 0 + ); + for (Player inWorld : player.getWorld().getPlayers()) { + if (inWorld.equals(player)) continue; + this.sendPacket(inWorld, particlePacket); + } + } + + @Override + public void clearArrowsFromPlayerBody(Player player) { + // minecraft clears them on death on newer version + } + + /** + * Gets the NMS Item from ItemStack + */ + private @Nullable Item getItem(org.bukkit.inventory.ItemStack itemStack) { + var i = CraftItemStack.asNMSCopy(itemStack); + if (null == i) { + return null; + } + return i.d(); + } + + /** + * Gets the NMS Entity from ItemStack + */ + private @Nullable net.minecraft.world.entity.Entity getEntity(org.bukkit.inventory.ItemStack itemStack) { + var i = CraftItemStack.asNMSCopy(itemStack); + if (null == i) { + return null; + } + return i.H(); + } + + private @Nullable NBTTagCompound getTag(@NotNull org.bukkit.inventory.ItemStack itemStack) { + var i = CraftItemStack.asNMSCopy(itemStack); + if (null == i) { + return null; + } + return i.v(); + } + + private @Nullable NBTTagCompound getTag(@NotNull ItemStack itemStack) { + return itemStack.v(); + } + + private @NotNull NBTTagCompound initializeTag(org.bukkit.inventory.ItemStack itemStack) { + var i = CraftItemStack.asNMSCopy(itemStack); + if (null == i) { + throw new RuntimeException("Cannot convert given item to a NMS item"); + } + return initializeTag(i); + } + + private @NotNull NBTTagCompound initializeTag(ItemStack itemStack) { + + var tag = getTag(itemStack); + if (null != tag) { + throw new RuntimeException("Provided item already has a Tag"); + } + tag = new NBTTagCompound(); + itemStack.c(tag); + + return tag; + } + + public NBTTagCompound getCreateTag(ItemStack itemStack) { + var tag = getTag(itemStack); + return null == tag ? initializeTag(itemStack) : tag; + } + + public NBTTagCompound getCreateTag(org.bukkit.inventory.ItemStack itemStack) { + var i = CraftItemStack.asNMSCopy(itemStack); + if (null == i) { + throw new RuntimeException("Cannot convert given item to a NMS item"); + } + return getCreateTag(i); + } + + public org.bukkit.inventory.ItemStack applyTag(org.bukkit.inventory.ItemStack itemStack, NBTTagCompound tag) { + return CraftItemStack.asBukkitCopy(applyTag(getNmsItemCopy(itemStack), tag)); + } + + public ItemStack applyTag(@NotNull ItemStack itemStack, NBTTagCompound tag) { + itemStack.c(tag); + return itemStack; + } + + public ItemStack getNmsItemCopy(org.bukkit.inventory.ItemStack itemStack) { + ItemStack i = CraftItemStack.asNMSCopy(itemStack); + if (null == i) { + throw new RuntimeException("Cannot convert given item to a NMS item"); + } + return i; + } + + public EntityPlayer getPlayer(Player player) { + return ((CraftPlayer) player).getHandle(); + } + + public List> getPlayerEquipment(@NotNull Player player) { + return getPlayerEquipment(getPlayer(player)); + } + + public List> getPlayerEquipment(@NotNull EntityPlayer entityPlayer) { + List> list = new ArrayList<>(); + list.add(new Pair<>(EnumItemSlot.a, entityPlayer.c(EnumItemSlot.a))); + list.add(new Pair<>(EnumItemSlot.b, entityPlayer.c(EnumItemSlot.b))); + list.add(new Pair<>(EnumItemSlot.f, entityPlayer.c(EnumItemSlot.f))); + list.add(new Pair<>(EnumItemSlot.e, entityPlayer.c(EnumItemSlot.e))); + list.add(new Pair<>(EnumItemSlot.d, entityPlayer.c(EnumItemSlot.d))); + list.add(new Pair<>(EnumItemSlot.c, entityPlayer.c(EnumItemSlot.c))); + + return list; + } + + @Override + public void placeTowerBlocks(@NotNull Block b, @NotNull IArena a, @NotNull TeamColor color, int x, int y, int z) { + b.getRelative(x, y, z).setType(color.woolMaterial()); + a.addPlacedBlock(b.getRelative(x, y, z)); + } + + @Override + public void placeLadder(@NotNull Block b, int x, int y, int z, @NotNull IArena a, int ladderData) { + Block block = b.getRelative(x, y, z); //ladder block + block.setType(Material.LADDER); + Ladder ladder = (Ladder) block.getBlockData(); + a.addPlacedBlock(block); + switch (ladderData) { + case 2 -> { + ladder.setFacing(BlockFace.NORTH); + block.setBlockData(ladder); + } + case 3 -> { + ladder.setFacing(BlockFace.SOUTH); + block.setBlockData(ladder); + } + case 4 -> { + ladder.setFacing(BlockFace.WEST); + block.setBlockData(ladder); + } + case 5 -> { + ladder.setFacing(BlockFace.EAST); + block.setBlockData(ladder); + } + } + } + + @Override + public void playVillagerEffect(@NotNull Player player, Location location) { + player.spawnParticle(Particle.VILLAGER_HAPPY, location, 1); + } + + private void sendPacket(Player player, Packet packet) { + ((CraftPlayer) player).getHandle().c.a(packet); + } + + private void sendPackets(Player player, Packet @NotNull ... packets) { + PlayerConnection connection = ((CraftPlayer) player).getHandle().c; + for (Packet p : packets) { + connection.a(p); + } + } +} \ No newline at end of file