/*
* This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT).
*
* Copyright (c) JCThePants (www.jcwhatever.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.jcwhatever.nucleus.internal.managed.nms;
import com.jcwhatever.nucleus.utils.PreCon;
import com.jcwhatever.nucleus.utils.nms.INmsPotionHandler;
import com.jcwhatever.nucleus.utils.potions.PotionUtils;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import org.bukkit.potion.PotionType;
import javax.annotation.Nullable;
/**
* Minecraft Potions handler.
*/
class NmsPotionHandler implements INmsPotionHandler {
// Potion strings found in net.minecraft.server.PotionBrewer
private static final String SUGAR = "-0+1-2-3&4-4+13";
private static final String MAGMA_CREAM = "+0+1-2-3&4-4+13";
private static final String SPECKLED_MELON = "+0-1+2-3&4-4+13";
private static final String SPIDER_EYE = "-0-1+2-3&4-4+13";
private static final String FERMENTED_SPIDER_EYE = "-0+3-4+13";
private static final String BLAZE_POWDER = "+0-1-2+3&4-4+13";
private static final String GOLDEN_CARROT = "-0+1+2-3+13&4-4";
private static final String PUFFER_FISH = "+0-1+2+3+13&4-4";
private static final String RABBIT_FOOT = "+0+1-2+3&4-4+13";
private static final String YELLOW_DUST = "+5-6-7";
private static final String REDSTONE = "-5+6-7";
private static final String SULPHUR = "+14&13-13";
@Override
public boolean isAvailable() {
return true;
}
@Override
public int getPotionId(PotionType type, int level, boolean isSplash, boolean isExtended) {
PreCon.notNull(type);
if (type == PotionType.WATER)
return 0;
int id = type.getDamageValue();
if (level > 1) {
id |= 32;
}
if (isExtended) {
id |= 64;
}
id |= isSplash ? 16384 : 8192;
return id;
}
@Override
public ItemStack getPotionStack(PotionType type, int level, boolean isSplash, boolean isExtended) {
PreCon.notNull(type);
int id = getPotionId(type, level, isSplash, isExtended);
ItemStack itemStack = new ItemStack(Material.POTION);
itemStack.setDurability((short)id);
return itemStack;
}
@Nullable
@Override
public ItemStack getPotionStack(int potionId) {
PotionType type = PotionType.getByDamageValue(potionId & 15);
if (type == null)
return null;
int level = (potionId & 32) == 32 ? 2 : 1;
boolean isSplash = (potionId & 16384) == 16384;
boolean isExtended = (potionId & 64) == 64;
return getPotionStack(type, level, isSplash, isExtended);
}
@Override
public int getPotionIdFromRecipe(ItemStack ingredient, ItemStack bottle) {
PreCon.notNull(ingredient);
PreCon.notNull(bottle);
if (!PotionUtils.isPotionIngredient(ingredient))
return -1;
if (bottle.getType() != Material.POTION)
return -1;
String potionString = getPotionString(ingredient.getData());
if (potionString == null) {
if (bottle.getDurability() != 0)
return -1;
if (ingredient.getType() == Material.NETHER_STALK)
return 16;
if (ingredient.getType() == Material.GLOWSTONE_DUST)
return 32;
if (ingredient.getType() == Material.REDSTONE)
return 64;
return -1;
}
int bottleData = bottle.getDurability();
int potionId = getPotionData(bottleData, potionString);
if ((potionId & 32) == 0) {
// see if a level one potion is valid, if not, make this a level 2 potion
if (!PotionUtils.isValidPotionId(potionId)) {
potionId |= 32;
}
}
return potionId;
}
@Override
public boolean isSplash(int potionId) {
return (potionId & 16384) == 16384;
}
@Override
public int getLevel(int potionId) {
return (potionId & 32) == 32 ? 2 : 1;
}
@Override
public boolean isExtendedDuration(int potionId) {
return (potionId & 64) == 64;
}
private static String getPotionString(MaterialData data) {
switch (data.getItemType()) {
case SUGAR:
return SUGAR;
case MAGMA_CREAM:
return MAGMA_CREAM;
case SPECKLED_MELON:
return SPECKLED_MELON;
case SPIDER_EYE:
return SPIDER_EYE;
case FERMENTED_SPIDER_EYE:
return FERMENTED_SPIDER_EYE;
case BLAZE_POWDER:
return BLAZE_POWDER;
case GOLDEN_CARROT:
return GOLDEN_CARROT;
case RAW_FISH:
if (data.getData() == 3)
return PUFFER_FISH;
return null;
case RABBIT_FOOT:
return RABBIT_FOOT;
case GLOWSTONE_DUST:
return YELLOW_DUST;
case REDSTONE:
return REDSTONE;
case SULPHUR:
return SULPHUR;
default:
return null;
}
}
// method from net.minecraft.server.PotionBrewer
private static int getPotionData(int data, String potionString) {
boolean flag = false;
boolean flag1 = false;
boolean flag2 = false;
boolean flag3 = false;
int k = 0;
for (int i = 0; i < potionString.length(); i++) {
char ch = potionString.charAt(i);
if (ch >= 48 && ch <= 57) { // 0-9
k *= 10;
k += ch - 48;
flag = true;
} else if (ch == 33) { // !
if (flag) {
data = getPotionData(data, k, flag2, flag1, flag3);
flag3 = false;
flag1 = false;
flag2 = false;
flag = false;
k = 0;
}
flag1 = true;
} else if (ch == 45) { // -
if (flag) {
data = getPotionData(data, k, flag2, flag1, flag3);
flag3 = false;
flag1 = false;
flag2 = false;
flag = false;
k = 0;
}
flag2 = true;
} else if (ch == 43) { // +
if (flag) {
data = getPotionData(data, k, flag2, flag1, flag3);
flag3 = false;
flag1 = false;
flag2 = false;
flag = false;
k = 0;
}
} else if (ch == 38) { // &
if (flag) {
data = getPotionData(data, k, flag2, flag1, flag3);
flag3 = false;
flag1 = false;
flag2 = false;
flag = false;
k = 0;
}
flag3 = true;
}
}
if (flag) {
data = getPotionData(data, k, flag2, flag1, flag3);
}
return data & 32767;
}
// method from net.minecraft.server.PotionBrewer
private static int getPotionData(int i, int j, boolean flag, boolean flag1, boolean flag2) {
if (flag2) {
if (!getPotionData(i, j)) {
return 0;
}
} else if (flag) {
i &= ~(1 << j);
} else if (flag1) {
if ((i & 1 << j) == 0) {
i |= 1 << j;
} else {
i &= ~(1 << j);
}
} else {
i |= 1 << j;
}
return i;
}
// method from net.minecraft.server.PotionBrewer
private static boolean getPotionData(int i, int j) {
return (i & 1 << j) != 0;
}
}