This commit is contained in:
BuildTools 2024-02-05 04:30:26 +05:00
commit 1d508bb581
5 changed files with 375 additions and 0 deletions

View File

@ -0,0 +1,83 @@
package su.nightexpress.excellentenchants.api.enchantment;
import org.bukkit.Keyed;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.api.config.JYML;
import su.nightexpress.excellentenchants.enchantment.type.ObtainType;
import su.nightexpress.excellentenchants.tier.Tier;
import java.util.List;
import java.util.Set;
public interface IEnchantment extends Keyed {
boolean isAvailableToUse(@NotNull LivingEntity entity);
@NotNull JYML getConfig();
@NotNull String getId();
@NotNull String getDisplayName();
@NotNull String getNameFormatted(int level);
@NotNull String getNameFormatted(int level, int charges);
@NotNull List<String> getDescription();
@NotNull List<String> getDescription(int level);
@NotNull Set<String> getConflicts();
@NotNull Tier getTier();
int getMaxLevel();
int getStartLevel();
int getLevelByEnchantCost(int expLevel);
double getObtainChance(@NotNull ObtainType obtainType);
int getObtainLevelMin(@NotNull ObtainType obtainType);
int getObtainLevelMax(@NotNull ObtainType obtainType);
int generateLevel(@NotNull ObtainType obtainType);
int getAnvilMergeCost(int level);
boolean conflictsWith(@NotNull Enchantment enchantment);
boolean canEnchantItem(@Nullable ItemStack item);
boolean isCursed();
boolean isTreasure();
boolean isChargesEnabled();
int getChargesMax(int level);
int getChargesConsumeAmount(int level);
int getChargesRechargeAmount(int level);
@NotNull ItemStack getChargesFuel();
boolean isChargesFuel(@NotNull ItemStack item);
int getCharges(@NotNull ItemStack item);
boolean isFullOfCharges(@NotNull ItemStack item);
boolean isOutOfCharges(@NotNull ItemStack item);
void consumeCharges(@NotNull ItemStack item, int level);
void consumeChargesNoUpdate(@NotNull ItemStack item, int level);
}

View File

@ -0,0 +1,59 @@
package su.nightexpress.excellentenchants.enchantment.type;
import org.bukkit.Material;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.utils.ItemUtil;
import su.nightexpress.excellentenchants.config.Config;
public enum FitItemType {
HELMET, CHESTPLATE, LEGGINGS, BOOTS, ELYTRA,
WEAPON, TOOL, ARMOR, UNIVERSAL,
SWORD, TRIDENT, AXE, BOW, CROSSBOW,
HOE, PICKAXE, SHOVEL, FISHING_ROD;
@Nullable
public static FitItemType getByEnchantmentTarget(@NotNull EnchantmentTarget target) {
return switch (target) {
case ARMOR -> ARMOR;
case ARMOR_FEET -> BOOTS;
case ARMOR_LEGS -> LEGGINGS;
case ARMOR_TORSO -> CHESTPLATE;
case ARMOR_HEAD -> HELMET;
case WEAPON -> WEAPON;
case TOOL -> TOOL;
case BOW -> BOW;
case FISHING_ROD -> FISHING_ROD;
case TRIDENT -> TRIDENT;
case CROSSBOW -> CROSSBOW;
case BREAKABLE, WEARABLE -> UNIVERSAL;
default -> null;
};
}
public boolean isIncluded(@NotNull ItemStack item) {
return switch (this) {
case UNIVERSAL -> ARMOR.isIncluded(item) || WEAPON.isIncluded(item) || TOOL.isIncluded(item) || BOW.isIncluded(item) || FISHING_ROD.isIncluded(item) || ELYTRA.isIncluded(item);
case HELMET -> ItemUtil.isHelmet(item);
case CHESTPLATE -> ItemUtil.isChestplate(item) || (Config.ENCHANTMENTS_ITEM_CHESTPLATE_ENCHANTS_TO_ELYTRA.get() && ELYTRA.isIncluded(item));
case LEGGINGS -> ItemUtil.isLeggings(item);
case BOOTS -> ItemUtil.isBoots(item);
case ELYTRA -> item.getType() == Material.ELYTRA;
case WEAPON -> SWORD.isIncluded(item) || ItemUtil.isTrident(item);
case TOOL -> ItemUtil.isTool(item);
case ARMOR -> ItemUtil.isArmor(item);
case SWORD -> ItemUtil.isSword(item) || (Config.ENCHANTMENTS_ITEM_SWORD_ENCHANTS_TO_AXES.get() && AXE.isIncluded(item));
case TRIDENT -> ItemUtil.isTrident(item);
case AXE -> ItemUtil.isAxe(item);
case BOW -> item.getType() == Material.BOW || (Config.ENCHANTMENTS_ITEM_BOW_ENCHANTS_TO_CROSSBOW.get() && CROSSBOW.isIncluded(item));
case CROSSBOW -> item.getType() == Material.CROSSBOW;
case HOE -> ItemUtil.isHoe(item);
case PICKAXE -> ItemUtil.isPickaxe(item);
case SHOVEL -> ItemUtil.isShovel(item);
case FISHING_ROD -> item.getType() == Material.FISHING_ROD;
};
}
}

View File

@ -0,0 +1,23 @@
package su.nightexpress.excellentenchants.enchantment.type;
import org.jetbrains.annotations.NotNull;
public enum ObtainType {
ENCHANTING("Enchanting_Table"),
VILLAGER("Villagers"),
LOOT_GENERATION("Loot_Generation"),
FISHING("Fishing"),
MOB_SPAWNING("Mob_Spawning");
private final String pathName;
ObtainType(@NotNull String pathName) {
this.pathName = pathName;
}
@NotNull
public String getPathName() {
return pathName;
}
}

View File

@ -0,0 +1,94 @@
package su.nightexpress.excellentenchants.enchantment.util;
import org.jetbrains.annotations.NotNull;
public class Evaluator {
public static double evaluate(@NotNull final String str) {
return new Object() {
int pos = -1, ch;
void nextChar() {
ch = (++pos < str.length()) ? str.charAt(pos) : -1;
}
boolean eat(int charToEat) {
while (ch == ' ') nextChar();
if (ch == charToEat) {
nextChar();
return true;
}
return false;
}
double parse() {
nextChar();
double x = parseExpression();
if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
return x;
}
// Grammar:
// expression = term | expression `+` term | expression `-` term
// term = factor | term `*` factor | term `/` factor
// factor = `+` factor | `-` factor | `(` expression `)` | number
// | functionName `(` expression `)` | functionName factor
// | factor `^` factor
double parseExpression() {
double x = parseTerm();
for (;;) {
if (eat('+')) x += parseTerm(); // addition
else if (eat('-')) x -= parseTerm(); // subtraction
else return x;
}
}
double parseTerm() {
double x = parseFactor();
for (;;) {
if (eat('*')) x *= parseFactor(); // multiplication
else if (eat('/')) x /= parseFactor(); // division
else return x;
}
}
double parseFactor() {
if (eat('+')) return +parseFactor(); // unary plus
if (eat('-')) return -parseFactor(); // unary minus
double x;
int startPos = this.pos;
if (eat('(')) { // parentheses
x = parseExpression();
if (!eat(')')) throw new RuntimeException("Missing ')'");
} else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
x = Double.parseDouble(str.substring(startPos, this.pos));
} else if (ch >= 'a' && ch <= 'z') { // functions
while (ch >= 'a' && ch <= 'z') nextChar();
String func = str.substring(startPos, this.pos);
if (eat('(')) {
x = parseExpression();
if (!eat(')')) throw new RuntimeException("Missing ')' after argument to " + func);
} else {
x = parseFactor();
}
x = switch (func) {
case "sqrt" -> Math.sqrt(x);
case "sin" -> Math.sin(Math.toRadians(x));
case "cos" -> Math.cos(Math.toRadians(x));
case "tan" -> Math.tan(Math.toRadians(x));
default -> throw new RuntimeException("Unknown function: " + func);
};
} else {
throw new RuntimeException("Unexpected: " + (char)ch);
}
if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation
return x;
}
}.parse();
}
}

View File

@ -0,0 +1,116 @@
package su.nightexpress.excellentenchants.nms;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.game.ClientboundAnimatePacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.projectile.FishingHook;
import net.minecraft.world.item.SpawnEggItem;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlock;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftFishHook;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory;
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack;
import org.bukkit.entity.FishHook;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
public class V1_20_R2 implements EnchantNMS {
@Override
public void sendAttackPacket(@NotNull Player player, int id) {
CraftPlayer craftPlayer = (CraftPlayer) player;
ServerPlayer entity = craftPlayer.getHandle();
ClientboundAnimatePacket packet = new ClientboundAnimatePacket(entity, id);
craftPlayer.getHandle().connection.send(packet);
}
@Override
public void retrieveHook(@NotNull FishHook hook, @NotNull ItemStack item) {
CraftFishHook craftFishHook = (CraftFishHook) hook;
FishingHook handle = craftFishHook.getHandle();
handle.retrieve(CraftItemStack.asNMSCopy(item));
}
@Override
@Nullable
public ItemStack getSpawnEgg(@NotNull LivingEntity entity) {
CraftLivingEntity craftLivingEntity = (CraftLivingEntity) entity;
net.minecraft.world.entity.LivingEntity livingEntity = craftLivingEntity.getHandle();
SpawnEggItem eggItem = SpawnEggItem.byId(livingEntity.getType());
if (eggItem == null) return null;
return CraftItemStack.asBukkitCopy(eggItem.getDefaultInstance());
}
@Override
@NotNull
public Set<Block> handleFlameWalker(@NotNull LivingEntity bukkitEntity, @NotNull Location location, int level) {
Entity entity = ((CraftLivingEntity) bukkitEntity).getHandle();
BlockPos pos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
ServerLevel world = ((CraftWorld) bukkitEntity.getWorld()).getHandle();
int radius = Math.min(16, 2 + level);
BlockState bStone = Blocks.MAGMA_BLOCK.defaultBlockState();
BlockPos.MutableBlockPos posAbove = new BlockPos.MutableBlockPos();
Set<Block> blocks = new HashSet<>();
for (BlockPos posNear : BlockPos.betweenClosed(pos.offset(-radius, -1, -radius), pos.offset(radius, -1, radius))) {
if (!posNear.closerThan(entity.blockPosition(), radius)) continue;
posAbove.set(posNear.getX(), posNear.getY() + 1, posNear.getZ());
BlockState bLavaAbove = world.getBlockState(posAbove);
BlockState bLava = world.getBlockState(posNear);
if (!bLavaAbove.isAir()) continue;
if (!bLava.getBlock().equals(Blocks.LAVA)) continue;
if (bLava.getValue(LiquidBlock.LEVEL) != 0) continue;
if (!bStone.canSurvive(world, posNear)) continue;
if (!world.isUnobstructed(bStone, posNear, CollisionContext.empty())) continue;
if (!CraftEventFactory.handleBlockFormEvent(world, posNear, bStone, entity)) continue;
//world.scheduleTick(posNear, Blocks.STONE, Rnd.get(60, 120));
Location bukkitLoc = new Location(world.getWorld(), posNear.getX(), posNear.getY(), posNear.getZ());
blocks.add(bukkitLoc.getBlock());
}
return blocks;
}
@NotNull
public Item popResource(@NotNull Block block, @NotNull ItemStack item) {
Level world = ((CraftWorld)block.getWorld()).getHandle();
BlockPos pos = ((CraftBlock)block).getPosition();
net.minecraft.world.item.ItemStack itemstack = CraftItemStack.asNMSCopy(item);
float yMod = EntityType.ITEM.getHeight() / 2.0F;
double x = (pos.getX() + 0.5F) + Mth.nextDouble(world.random, -0.25D, 0.25D);
double y = (pos.getY() + 0.5F) + Mth.nextDouble(world.random, -0.25D, 0.25D) - yMod;
double z = (pos.getZ() + 0.5F) + Mth.nextDouble(world.random, -0.25D, 0.25D);
ItemEntity itemEntity = new ItemEntity(world, x, y, z, itemstack);
itemEntity.setDefaultPickUpDelay();
return (Item) itemEntity.getBukkitEntity();
}
}