mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2026-08-21 10:25:13 -06:00
Merge branch 2009scape:master into master
This commit is contained in:
commit
86c8216ffa
83 changed files with 1643 additions and 4159 deletions
|
|
@ -20859,8 +20859,10 @@
|
|||
{
|
||||
"ge_buy_limit": "200",
|
||||
"grand_exchange_price": "177",
|
||||
"examine": "I need to add some meat too.",
|
||||
"durability": null,
|
||||
"name": "Incomplete stew",
|
||||
"tradeable": "true",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "1997"
|
||||
},
|
||||
|
|
@ -20876,8 +20878,10 @@
|
|||
{
|
||||
"ge_buy_limit": "200",
|
||||
"grand_exchange_price": "210",
|
||||
"examine": "I need to add some potato too.",
|
||||
"durability": null,
|
||||
"name": "Incomplete stew",
|
||||
"tradeable": "true",
|
||||
"archery_ticket_price": "0",
|
||||
"id": "1999"
|
||||
},
|
||||
|
|
@ -64514,7 +64518,7 @@
|
|||
},
|
||||
{
|
||||
"ge_buy_limit": "10000",
|
||||
"examine": "Raw sweetcorn.",
|
||||
"examine": "A bowl of cooked sweetcorn.",
|
||||
"grand_exchange_price": "110",
|
||||
"durability": null,
|
||||
"name": "Sweetcorn",
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ public enum Consumables {
|
|||
EGG_AND_TOMATO(new Food(new int[] {7064, 1923}, new HealingEffect(8))),
|
||||
SWEET_CORN(new Food(new int[] {5988}, new MultiEffect(new HealingEffect(1), new PercentageHealthEffect(10)))),
|
||||
SWEETCORN_BOWL(new Food(new int[] {7088, 1923}, new MultiEffect(new HealingEffect(1), new PercentageHealthEffect(10)))),
|
||||
CHOPPED_TUNA(new Food(new int[] {7086, 1923}, new HealingEffect(10))),
|
||||
CHOPPED_ONION(new Food(new int[] {1871, 1923}, new HealingEffect(1))),
|
||||
POTATO_WITH_BUTTER(new Food(new int[] {6703}, new HealingEffect(7))),
|
||||
CHILLI_POTATO(new Food(new int[] {7054}, new HealingEffect(14))),
|
||||
FRIED_ONIONS(new Food(new int[] {7084, 1923}, new HealingEffect(5))),
|
||||
|
|
|
|||
39
Server/src/main/content/global/skill/cooking/CakeListener.kt
Normal file
39
Server/src/main/content/global/skill/cooking/CakeListener.kt
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package content.global.skill.cooking
|
||||
|
||||
import core.api.*
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.skill.Skills
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class CakeListener : InteractionListener {
|
||||
private val cakeArr = intArrayOf(
|
||||
Items.EGG_1944,
|
||||
Items.BUCKET_OF_MILK_1927,
|
||||
Items.POT_OF_FLOUR_1933
|
||||
)
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, cakeArr, Items.CAKE_TIN_1887) { player, _, _ ->
|
||||
if (getDynLevel(player, Skills.COOKING) < 40) {
|
||||
sendMessage(player, "You need a Cooking level of at least 40 in order to do this.")
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
if(inInventory(player, Items.EGG_1944) && inInventory(player, Items.BUCKET_OF_MILK_1927) && inInventory(player, Items.POT_OF_FLOUR_1933) && inInventory(player, Items.CAKE_TIN_1887)) {
|
||||
if(removeItem(player, Items.EGG_1944) && removeItem(player, Items.BUCKET_OF_MILK_1927) && removeItem(player, Items.POT_OF_FLOUR_1933) && removeItem(player, Items.CAKE_TIN_1887)){
|
||||
addItem(player, Items.EMPTY_POT_1931)
|
||||
addItem(player, Items.UNCOOKED_CAKE_1889)
|
||||
addItem(player, Items.BUCKET_1925)
|
||||
sendMessage(player, "You mix the milk, flour and egg together to make a raw cake mix.")
|
||||
|
||||
}
|
||||
}
|
||||
else{
|
||||
// Not sure about the authentic message
|
||||
sendMessage(player, "You don't have enough ingredients to make that.")
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
package content.global.skill.cooking;
|
||||
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the plugin used to make a cake.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class CakeMakingPlugin extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Represents the bucket of milk item.
|
||||
*/
|
||||
private static final Item BUCKET_OF_MILK = new Item(1927);
|
||||
|
||||
/**
|
||||
* Represents the egg item.
|
||||
*/
|
||||
private static final Item EGG = new Item(1944);
|
||||
|
||||
/**
|
||||
* Represents the cake tin item.
|
||||
*/
|
||||
private static final Item CAKE_TIN = new Item(1887);
|
||||
|
||||
/**
|
||||
* Represents the pot of flour item.
|
||||
*/
|
||||
private static final Item POT_OF_FLOUR = new Item(1933);
|
||||
|
||||
/**
|
||||
* Represents the uncooked cake item.
|
||||
*/
|
||||
private static final Item UNCOOKED_CAKE = new Item(1889);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CakeMakingPlugin} {@code Object}.
|
||||
*/
|
||||
public CakeMakingPlugin() {
|
||||
super(1933);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
addHandler(1887, ITEM_TYPE, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
if (event.getUsedItem().getId() == 1887 && ((Item) event.getUsedWith()).getId() == 1933 || event.getUsedWith().getName().equalsIgnoreCase("cake tin") && ((Item) event.getUsedItem()).getName().equalsIgnoreCase("pot of flour")) {
|
||||
if (event.getPlayer().getInventory().contains(1933, 1) && event.getPlayer().getInventory().contains(1927, 1) && event.getPlayer().getInventory().contains(1944, 1)) {
|
||||
if (event.getPlayer().getInventory().remove(BUCKET_OF_MILK, EGG, CAKE_TIN, POT_OF_FLOUR)) {
|
||||
event.getPlayer().getInventory().add(UNCOOKED_CAKE);
|
||||
event.getPlayer().getPacketDispatch().sendMessage("You mix the milk, flour and egg together to make a raw cake mix.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package content.global.skill.cooking
|
||||
|
||||
import core.api.addItem
|
||||
import core.api.removeItem
|
||||
import core.api.sendMessage
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class CoconutListener : InteractionListener {
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, Items.COCONUT_5974, Items.HAMMER_2347) { player, used, _ ->
|
||||
if(removeItem(player, used.id)) {
|
||||
addItem(player, Items.COCONUT_5976)
|
||||
sendMessage(player, "You crush the coconut with a hammer.")
|
||||
return@onUseWith true
|
||||
}
|
||||
return@onUseWith false
|
||||
}
|
||||
onUseWith(IntType.ITEM, Items.COCONUT_5976, Items.VIAL_229) { player, used, with ->
|
||||
if(removeItem(player, used.id) && removeItem(player, with.id)) {
|
||||
addItem(player, Items.COCONUT_SHELL_5978)
|
||||
addItem(player, Items.COCONUT_MILK_5935)
|
||||
sendMessage(player, "You overturn the coconut into a vial.")
|
||||
return@onUseWith true
|
||||
}
|
||||
return@onUseWith false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
package content.global.skill.cooking;
|
||||
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the plugin used to make a coconut.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class CoconutMakePlugin extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Represents the items related to coconut making plugin.
|
||||
*/
|
||||
private static final Item[] ITEMS = new Item[] { new Item(5974, 1), new Item(5976, 1), new Item(229), new Item(5935, 1), new Item(5978) };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CoconutMakePlugin} {@code Object}.
|
||||
*/
|
||||
public CoconutMakePlugin() {
|
||||
super(5974, 5976);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
addHandler(2347, ITEM_TYPE, this);
|
||||
addHandler(229, ITEM_TYPE, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final Item usedWith = (Item) event.getUsedWith();
|
||||
if (usedWith.getId() == 5974 && event.getUsedItem().getId() == 2347 || usedWith.getId() == 2347 && event.getUsedItem().getId() == 5974) {
|
||||
player.getInventory().remove(ITEMS[0]);
|
||||
player.getInventory().add(ITEMS[1]);
|
||||
player.getPacketDispatch().sendMessage("You crush the coconut with a hammer.");
|
||||
}
|
||||
if (usedWith.getId() == 5976 && event.getUsedItem().getId() == 229 || usedWith.getId() == 229 && event.getUsedItem().getId() == 5976) {
|
||||
player.getInventory().remove(ITEMS[1]);
|
||||
player.getInventory().remove(ITEMS[2]);
|
||||
player.getInventory().add(ITEMS[3]);
|
||||
player.getInventory().add(ITEMS[4]);
|
||||
player.getPacketDispatch().sendMessage("You overturn the coconut into a vial.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
package content.global.skill.cooking;
|
||||
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.game.dialogue.SkillDialogueHandler.SkillDialogue;
|
||||
import core.game.dialogue.SkillDialogueHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a cooking recipe plugin. This is used to handle the multiple
|
||||
* recipes used in cooking these recipes can range from making a pizza or making
|
||||
* a pie.
|
||||
* @author 'Vexia
|
||||
* @version 1.9
|
||||
*/
|
||||
@Initializable
|
||||
public final class CookingRecipePlugin extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CookingRecipePlugin} {@code Object}.
|
||||
*/
|
||||
public CookingRecipePlugin() {
|
||||
super(getAllowedNodes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (Recipe recipe : Recipe.RECIPES) {
|
||||
for (Item ingredient : recipe.getIngredients()) {
|
||||
addHandler(ingredient.getId(), ITEM_TYPE, this);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
Recipe recipe = null;
|
||||
Item part = null;
|
||||
// TODO: Transitioning to a Listener would save an O(n) pass through the recipes list on every use-with
|
||||
recipeloop:
|
||||
for (Recipe temp : Recipe.RECIPES) {
|
||||
if (temp.isSingular()) {
|
||||
if (temp.getBase().getId() == event.getUsedItem().getId() || temp.getBase().getId() == event.getBaseItem().getId()) {
|
||||
for (Item ingredient : temp.getIngredients()) {
|
||||
if (ingredient.getId() == event.getBaseItem().getId() || ingredient.getId() == event.getUsedItem().getId()) {
|
||||
recipe = temp;
|
||||
break recipeloop;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int k = 0; k < temp.getParts().length; k++) {
|
||||
for (int i = 0; i < temp.getIngredients().length; i++) {
|
||||
Item tempPart = temp.getParts()[k];
|
||||
Item ingredient = temp.getIngredients()[i];
|
||||
if (tempPart.getId() == event.getUsedItem().getId() && ingredient.getId() == event.getBaseItem().getId() || tempPart.getId() == event.getBaseItem().getId() && ingredient.getId() == event.getUsedItem().getId()) {
|
||||
if (k == i) {// represents that this ingredient can
|
||||
// mix with the other.
|
||||
recipe = temp;
|
||||
part = tempPart;
|
||||
break recipeloop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (recipe != null) {
|
||||
final Player player = event.getPlayer();
|
||||
final Recipe recipe_ = recipe;
|
||||
final Item part_ = part;
|
||||
SkillDialogueHandler handler = new SkillDialogueHandler(player, SkillDialogue.ONE_OPTION, recipe.getProduct()) {
|
||||
@Override
|
||||
public void create(final int amount, int index) {
|
||||
player.getPulseManager().run(new Pulse(2) {
|
||||
int count = 0;
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
recipe_.mix(player, event);
|
||||
return ++count >= amount;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAll(int index) {
|
||||
return player.getInventory().getAmount(part_ != null ? part_ : recipe_.getBase());
|
||||
}
|
||||
};
|
||||
if (player.getInventory().getAmount(recipe.getBase()) == 1) {
|
||||
recipe_.mix(player, event);
|
||||
} else {
|
||||
handler.open();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to get the allowed nodes for this plugin.
|
||||
* @return the allowed nodes.
|
||||
*/
|
||||
private final static int[] getAllowedNodes() {
|
||||
List<Integer> bases = new ArrayList<>(10);
|
||||
for (Recipe recipe : Recipe.RECIPES) {
|
||||
for (Item base : recipe.getParts()) {
|
||||
if (bases.contains(base.getId())) {
|
||||
continue;
|
||||
}
|
||||
bases.add(base.getId());
|
||||
}
|
||||
if (bases.contains(recipe.getBase().getId())) {
|
||||
continue;
|
||||
}
|
||||
bases.add(recipe.getBase().getId());
|
||||
}
|
||||
int[] baseArray = new int[bases.size()];
|
||||
for (int i = 0; i < bases.size(); i++) {
|
||||
baseArray[i] = bases.get(i);
|
||||
}
|
||||
return baseArray;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
package content.global.skill.cooking;
|
||||
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the pie shell making plugin.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class PieShellPlugin extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Represents the pie sell item.
|
||||
*/
|
||||
private static final Item PIE_SHELL = new Item(2315, 1);
|
||||
|
||||
/**
|
||||
* Represents the pie dish item.
|
||||
*/
|
||||
private static final Item PIE_DISH = new Item(2313, 1);
|
||||
|
||||
/**
|
||||
* Represents the pastry dough item.
|
||||
*/
|
||||
private static final Item PASTRY_DOUGH = new Item(1953, 1);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PieMakingPlugin} {@code Object}.
|
||||
*/
|
||||
public PieShellPlugin() {
|
||||
super(1953);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
addHandler(2313, ITEM_TYPE, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
if (player.getInventory().remove(PASTRY_DOUGH, PIE_DISH)) {
|
||||
player.getInventory().add(PIE_SHELL);
|
||||
player.getPacketDispatch().sendMessage("You put the pastry dough into the pie dish to make a pie shell.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package content.global.skill.cooking
|
||||
|
||||
import core.api.*
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.skill.Skills
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class SkeweredFoodListener : InteractionListener {
|
||||
val skewerMap = hashMapOf(
|
||||
Items.RAW_CHOMPY_2876 to Items.SKEWERED_CHOMPY_7230,
|
||||
Items.RAW_RABBIT_3226 to Items.SKEWERED_RABBIT_7224,
|
||||
Items.RAW_BIRD_MEAT_9978 to Items.SKEWERED_BIRD_MEAT_9984,
|
||||
Items.RAW_BEAST_MEAT_9986 to Items.SKEWERED_BEAST_9992
|
||||
)
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, skewerMap.keys.toIntArray(), Items.IRON_SPIT_7225) { player, used, with ->
|
||||
val level = when (used.id) {
|
||||
Items.RAW_BIRD_MEAT_9978 -> 11
|
||||
Items.RAW_RABBIT_3226 -> 16
|
||||
Items.RAW_BEAST_MEAT_9986 -> 21
|
||||
Items.RAW_CHOMPY_2876 -> 30
|
||||
else -> 0
|
||||
}
|
||||
|
||||
if (getDynLevel(player, Skills.COOKING) < level) {
|
||||
sendMessage(player, "You need a Cooking level of at least $level in order to do this.")
|
||||
return@onUseWith true
|
||||
}
|
||||
if (removeItem(player, used.id) && removeItem(player, with.id)) {
|
||||
skewerMap[used.id]?.let { addItem(player, it) }
|
||||
return@onUseWith true
|
||||
}
|
||||
return@onUseWith false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
package content.global.skill.cooking;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import org.rs09.consts.Items;
|
||||
|
||||
/**
|
||||
* Represents the plugin used to make skwered items.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
@Initializable
|
||||
public class SkeweredFoodPlugin extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Represents the level required.
|
||||
*/
|
||||
private final int LEVEL = 20;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SkeweredFoodPlugin} {@code Object}.
|
||||
*/
|
||||
public SkeweredFoodPlugin() {
|
||||
super(7225);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (SkeweredSet set : SkeweredSet.values()) {
|
||||
addHandler(set.getRaw().getId(), ITEM_TYPE, this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
if (player.getSkills().getLevel(Skills.FIREMAKING) < LEVEL) {
|
||||
player.getPacketDispatch().sendMessage("You meed a Firemaking level of at least " + LEVEL + " in order to do this.");
|
||||
return true;
|
||||
}
|
||||
final SkeweredSet set = SkeweredSet.forItem(event.getBaseItem().getId() == 7225 ? event.getUsedItem() : event.getBaseItem());
|
||||
if (player.getInventory().remove(event.getBaseItem()) && player.getInventory().remove(event.getUsedItem())) {
|
||||
player.getInventory().add(set.getProduct());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a set of skwered items.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public enum SkeweredSet {
|
||||
CHOMPY(new Item(Items.RAW_CHOMPY_2876), new Item(Items.SKEWERED_CHOMPY_7230)),
|
||||
RABBIT(new Item(Items.RAW_RABBIT_3226), new Item(Items.SKEWERED_RABBIT_7224)),
|
||||
BIRD(new Item(Items.RAW_BIRD_MEAT_9978), new Item(Items.SKEWERED_BIRD_MEAT_9984)),
|
||||
BEAST(new Item(Items.RAW_BEAST_MEAT_9986), new Item(Items.SKEWERED_BEAST_9992));
|
||||
|
||||
/**
|
||||
* Represents the raw item.
|
||||
*/
|
||||
private final Item raw;
|
||||
|
||||
/**
|
||||
* Represents the product item.
|
||||
*/
|
||||
private final Item product;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SkeweredFoodPlugin} {@code Object}.
|
||||
* @param raw the raw item.
|
||||
* @param product the product.
|
||||
*/
|
||||
private SkeweredSet(Item raw, Item product) {
|
||||
this.raw = raw;
|
||||
this.product = product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw.
|
||||
* @return The raw.
|
||||
*/
|
||||
public Item getRaw() {
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the product.
|
||||
* @return The product.
|
||||
*/
|
||||
public Item getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skwered set.
|
||||
* @param item the item.
|
||||
* @return the set.
|
||||
*/
|
||||
public static SkeweredSet forItem(final Item item) {
|
||||
for (SkeweredSet set : values()) {
|
||||
if (set.getRaw().getId() == item.getId()) {
|
||||
return set;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package content.global.skill.cooking
|
||||
|
||||
import core.api.*
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class WatermelonSliceListener : InteractionListener {
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, Items.WATERMELON_5982, Items.KNIFE_946) { player, used, _ ->
|
||||
if(removeItem(player, used.asItem())) {
|
||||
addItemOrDrop(player, Items.WATERMELON_SLICE_5984, 3)
|
||||
sendMessage(player, "You slice the watermelon into three slices.")
|
||||
return@onUseWith true
|
||||
}
|
||||
return@onUseWith false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
package content.global.skill.cooking;
|
||||
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the plugin used to slice a watermelon.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class WatermelonSlicePlugin extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Represents the knife item.
|
||||
*/
|
||||
private static final Item KNIFE = new Item(946);
|
||||
|
||||
/**
|
||||
* Represents the watermelon item.
|
||||
*/
|
||||
private static final Item WATERMELON = new Item(5982);
|
||||
|
||||
/**
|
||||
* Represents the watermelon slice item.
|
||||
*/
|
||||
private static final Item WATERMELON_SLICE = new Item(5984);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code WatermelonSlicePlugin.java} {@code Object}.
|
||||
*/
|
||||
public WatermelonSlicePlugin() {
|
||||
super(KNIFE.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
addHandler(5982, ITEM_TYPE, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
if (event.getPlayer().getInventory().remove(WATERMELON)) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (!event.getPlayer().getInventory().add(WATERMELON_SLICE)) {
|
||||
GroundItemManager.create(WATERMELON_SLICE, event.getPlayer());
|
||||
}
|
||||
}
|
||||
event.getPlayer().getPacketDispatch().sendMessage("You slice the watermelon into three slices.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package content.global.skill.cooking
|
||||
|
||||
import content.global.skill.cooking.fermenting.WineFermentingPulse
|
||||
import core.api.addItem
|
||||
import core.api.getDynLevel
|
||||
import core.api.removeItem
|
||||
import core.api.sendMessage
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.world.GameWorld.Pulser
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class WineFermentListener : InteractionListener {
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, Items.GRAPES_1987, Items.JUG_OF_WATER_1937) { player, used, with ->
|
||||
if (getDynLevel(player, Skills.COOKING) < 35) {
|
||||
sendMessage(player, "You need a cooking level of 35 to do this.")
|
||||
return@onUseWith true
|
||||
}
|
||||
if (removeItem(player, used.id) && removeItem(player, with.id)) {
|
||||
addItem(player, Items.UNFERMENTED_WINE_1995)
|
||||
Pulser.submit(WineFermentingPulse(1, player))
|
||||
return@onUseWith true
|
||||
}
|
||||
return@onUseWith false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
package content.global.skill.cooking;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.cooking.fermenting.WineFermentingPulse;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.GameWorld;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the plugin used to ferment wine.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class WineFermentPlugin extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Represents the grapes item.
|
||||
*/
|
||||
private static final Item GRAPES = new Item(1987, 1);
|
||||
|
||||
/**
|
||||
* Represents the jug of water item.
|
||||
*/
|
||||
private static final Item JUG_OF_WATER = new Item(1937, 1);
|
||||
|
||||
/**
|
||||
* Represents the unfermented wine item.
|
||||
*/
|
||||
private static final Item UNFERMENTED_WINE = new Item(1995, 1);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code WineFermentPlugin} {@code Object}.
|
||||
*/
|
||||
public WineFermentPlugin() {
|
||||
super(1937);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
addHandler(1987, ITEM_TYPE, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < 35) {
|
||||
player.getPacketDispatch().sendMessage("You need a cooking level of 35 to do this.");
|
||||
return true;
|
||||
}
|
||||
if (player.getInventory().remove(GRAPES, JUG_OF_WATER)) {
|
||||
player.getInventory().add(UNFERMENTED_WINE);
|
||||
GameWorld.getPulser().submit(new WineFermentingPulse(1, player));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class ChocolateCakeListener : InteractionListener {
|
||||
|
||||
val chocolate = intArrayOf(Items.CHOCOLATE_BAR_1973, Items.CHOCOLATE_DUST_1975)
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, Items.CAKE_1891, *chocolate) { player, used, with ->
|
||||
val product = Items.CHOCOLATE_CAKE_1897
|
||||
val level = 50
|
||||
val experience = 30.0
|
||||
val message = ""
|
||||
val failMessage = "You need a Cooking level of $level in order to do that."
|
||||
|
||||
return@onUseWith standardMix(
|
||||
player,
|
||||
used.asItem(),
|
||||
with.asItem(),
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class CurryListener : InteractionListener {
|
||||
|
||||
val added = intArrayOf(Items.CURRY_LEAF_5970, Items.SPICE_2007)
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, Items.UNCOOKED_STEW_2001, *added) { player, used, with ->
|
||||
val product = Items.UNCOOKED_CURRY_2009
|
||||
val amountAdded = when (with.id) {
|
||||
Items.CURRY_LEAF_5970 -> 3
|
||||
Items.SPICE_2007 -> 1
|
||||
else -> 0
|
||||
}
|
||||
val level = 60
|
||||
val experience = 0.0
|
||||
val message = "You mix the spice with the stew."
|
||||
val failMessage = "You need a Cooking level of at least $level in order to do this."
|
||||
|
||||
return@onUseWith standardMix(
|
||||
player,
|
||||
used.asItem(),
|
||||
Item(with.id, amountAdded),
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.api.*
|
||||
import core.game.dialogue.SkillDialogueHandler
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import kotlin.math.min
|
||||
|
||||
fun standardMix(player: Player, used: Item, with: Item, product: Int, level: Int, experience: Double, message: String, failMessage: String): Boolean {
|
||||
// Avoids sending dialogue if not enough ingredients to create (relevant only for curry leaves)
|
||||
if (amountInInventory(player, used.id) < used.amount || amountInInventory(player, with.id) < with.amount) {
|
||||
// Not sure about the authentic message
|
||||
sendMessage(player, "You don't have enough ingredients to make that.")
|
||||
return true
|
||||
}
|
||||
|
||||
// Avoids sending dialogue if only one can be created
|
||||
if (amountInInventory(player, used.id) == used.amount || amountInInventory(player, with.id) == with.amount) {
|
||||
if (getDynLevel(player, Skills.COOKING) < level) {
|
||||
sendDialogue(player, failMessage)
|
||||
return true
|
||||
}
|
||||
|
||||
if (removeItem(player, used) && removeItem(player, with)) {
|
||||
sendMessage(player, message)
|
||||
rewardXP(player, Skills.COOKING, experience)
|
||||
addItem(player, product)
|
||||
containerIngredient(player, used.id)
|
||||
containerIngredient(player, with.id)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
mixHandler(
|
||||
player,
|
||||
used,
|
||||
with,
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
).open()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun mixHandler(player: Player, used: Item, with: Item, product: Int, level: Int, experience: Double, message: String, failMessage: String): SkillDialogueHandler {
|
||||
val handler: SkillDialogueHandler =
|
||||
object : SkillDialogueHandler(player, SkillDialogue.ONE_OPTION, product.asItem()) {
|
||||
override fun create(amount: Int, index: Int) {
|
||||
if (!playerMeetsInitialRequirements()) return
|
||||
MixScript(player, used, with, product, amount, level, experience, message, failMessage).invoke()
|
||||
}
|
||||
|
||||
private fun playerMeetsInitialRequirements(): Boolean {
|
||||
if (getDynLevel(player, Skills.COOKING) < level) {
|
||||
sendDialogue(player, failMessage)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getAll(index: Int): Int {
|
||||
return min(
|
||||
amountInInventory(player, used.id)/used.amount,
|
||||
amountInInventory(player, with.id)/with.amount
|
||||
)
|
||||
}
|
||||
}
|
||||
return handler
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.api.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class MixScript(
|
||||
private val player: Player,
|
||||
private val used: Item,
|
||||
private val with: Item,
|
||||
private val product: Int,
|
||||
private val sets: Int,
|
||||
private val level: Int,
|
||||
private val experience: Double,
|
||||
private val message: String,
|
||||
private val failMessage: String
|
||||
) {
|
||||
|
||||
private val delay = 2
|
||||
|
||||
fun invoke() {
|
||||
queueScript(player, delay) { stage -> Int
|
||||
if (getDynLevel(player, Skills.COOKING) < level) {
|
||||
sendDialogue(player, failMessage)
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
|
||||
if (inInventory(player, used.id, used.amount) && inInventory(player, with.id, with.amount)) {
|
||||
if(removeItem(player, used) && removeItem(player, with)) {
|
||||
sendMessage(player, message)
|
||||
rewardXP(player, Skills.COOKING, experience)
|
||||
addItem(player, product)
|
||||
containerIngredient(player, used.id)
|
||||
containerIngredient(player, with.id)
|
||||
}
|
||||
} else {
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
|
||||
if (stage >= sets - 1) {
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
|
||||
return@queueScript delayScript(player, delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun containerIngredient(player: Player, ingredient: Int): Boolean{
|
||||
return when (ingredient) {
|
||||
Items.BUCKET_OF_WATER_1929, Items.COMPOST_6032 -> addItem(player, Items.BUCKET_1925)
|
||||
Items.FRIED_MUSHROOMS_7082 -> addItem(player, Items.BOWL_1923)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
package content.global.skill.cooking.recipe;
|
||||
|
||||
import org.rs09.consts.Items;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* @author afaroutdude
|
||||
*/
|
||||
public class OomlieWrap extends Recipe {
|
||||
|
||||
private static final Item OOMLIE_WRAP = new Item(Items.WRAPPED_OOMLIE_2341);
|
||||
private static final Item RAW_OOMLIE = new Item(Items.RAW_OOMLIE_2337);
|
||||
private static final Item PALM_LEAF = new Item(Items.PALM_LEAF_2339);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < 50) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of 50 in order to do that.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return RAW_OOMLIE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return OOMLIE_WRAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { PALM_LEAF };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return "You wrap the raw oomlie in the palm leaf.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class OomlieWrapListener : InteractionListener {
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, Items.RAW_OOMLIE_2337, Items.PALM_LEAF_2339) { player, used, with ->
|
||||
val product = Items.WRAPPED_OOMLIE_2341
|
||||
val level = 50
|
||||
val experience = 0.0
|
||||
val message = "You wrap the raw oomlie in the palm leaf."
|
||||
val failMessage = "You need a Cooking level of at least $level in order to do that."
|
||||
|
||||
return@onUseWith standardMix(
|
||||
player,
|
||||
used.asItem(),
|
||||
with.asItem(),
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class PieListener : InteractionListener {
|
||||
|
||||
val base = PieProduct.values().map { it.base }.toIntArray()
|
||||
val added = PieProduct.values().map { it.added }.toIntArray()
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, base, *added) { player, used, with ->
|
||||
val pie = PieProduct.productMap[used.id] ?: return@onUseWith true
|
||||
|
||||
if (pie.added != with.id) {
|
||||
return@onUseWith false
|
||||
}
|
||||
|
||||
val product = pie.product
|
||||
val level = pie.minimumLevel
|
||||
val experience = 0.0
|
||||
val message = "You fill the pie with ${pie.ingredientMessage}."
|
||||
val failMessage = "You need a Cooking level of ${pie.minimumLevel} to make this."
|
||||
|
||||
return@onUseWith standardMix(
|
||||
player,
|
||||
used.asItem(),
|
||||
with.asItem(),
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
enum class PieProduct(
|
||||
val base: Int,
|
||||
val added: Int,
|
||||
val product: Int,
|
||||
val minimumLevel: Int,
|
||||
val ingredientMessage: String,
|
||||
) {
|
||||
REDBERRY_PIE(Items.REDBERRIES_1951, Items.PIE_SHELL_2315, Items.UNCOOKED_BERRY_PIE_2321, 10, "redberries"),
|
||||
MEAT_PIE(Items.COOKED_MEAT_2142, Items.PIE_SHELL_2315, Items.UNCOOKED_MEAT_PIE_2319, 20, "meat"),
|
||||
MUD_PIE_1(Items.COMPOST_6032, Items.PIE_SHELL_2315, Items.PART_MUD_PIE_7164, 29, "compost"),
|
||||
MUD_PIE_2(Items.PART_MUD_PIE_7164, Items.BUCKET_OF_WATER_1929, Items.PART_MUD_PIE_7166, 29, "water"),
|
||||
MUD_PIE_3(Items.PART_MUD_PIE_7166, Items.CLAY_434, Items.RAW_MUD_PIE_7168, 29, "clay"),
|
||||
APPLE_PIE(Items.COOKING_APPLE_1955, Items.PIE_SHELL_2315, Items.UNCOOKED_APPLE_PIE_2317, 30, "cooking apple"),
|
||||
GARDEN_PIE_1(Items.TOMATO_1982, Items.PIE_SHELL_2315, Items.PART_GARDEN_PIE_7172, 34, "tomato"),
|
||||
GARDEN_PIE_2(Items.PART_GARDEN_PIE_7172, Items.ONION_1957, Items.PART_GARDEN_PIE_7174, 34, "onion"),
|
||||
GARDEN_PIE_3(Items.PART_GARDEN_PIE_7174, Items.CABBAGE_1965, Items.RAW_GARDEN_PIE_7176, 34, "cabbage"),
|
||||
FISH_PIE_1(Items.TROUT_333, Items.PIE_SHELL_2315, Items.PART_FISH_PIE_7182, 47, "trout"),
|
||||
FISH_PIE_2(Items.PART_FISH_PIE_7182, Items.COD_339, Items.PART_FISH_PIE_7184, 47, "cod"),
|
||||
FISH_PIE_3(Items.PART_FISH_PIE_7184, Items.POTATO_1942, Items.RAW_FISH_PIE_7186, 47, "potato"),
|
||||
ADMIRAL_PIE_1(Items.SALMON_329, Items.PIE_SHELL_2315, Items.PART_ADMIRAL_PIE_7192, 70, "salmon"),
|
||||
ADMIRAL_PIE_2(Items.PART_ADMIRAL_PIE_7192, Items.TUNA_361, Items.PART_ADMIRAL_PIE_7194, 70, "tuna"),
|
||||
ADMIRAL_PIE_3(Items.PART_ADMIRAL_PIE_7194, Items.POTATO_1942, Items.RAW_ADMIRAL_PIE_7196, 70, "potato"),
|
||||
WILD_PIE_1(Items.RAW_BEAR_MEAT_2136, Items.PIE_SHELL_2315, Items.PART_WILD_PIE_7202, 85, "raw bear meat"),
|
||||
WILD_PIE_2(Items.PART_WILD_PIE_7202, Items.RAW_CHOMPY_2876, Items.PART_WILD_PIE_7204, 85, "raw chompy"),
|
||||
WILD_PIE_3(Items.PART_WILD_PIE_7204, Items.RAW_RABBIT_3226, Items.RAW_WILD_PIE_7206, 85, "raw rabbit"),
|
||||
SUMMER_PIE_1(Items.STRAWBERRY_5504, Items.PIE_SHELL_2315, Items.PART_SUMMER_PIE_7212, 95, "strawberry"),
|
||||
SUMMER_PIE_2(Items.PART_SUMMER_PIE_7212, Items.WATERMELON_5982, Items.PART_SUMMER_PIE_7214, 95, "watermelon"),
|
||||
SUMMER_PIE_3(Items.PART_SUMMER_PIE_7214, Items.COOKING_APPLE_1955, Items.RAW_SUMMER_PIE_7216, 95, "apple"),
|
||||
;
|
||||
|
||||
companion object {
|
||||
val productMap = HashMap<Int, PieProduct>()
|
||||
|
||||
init {
|
||||
for (pie in PieProduct.values()) {
|
||||
productMap[pie.base] = pie
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class PieShellListener : InteractionListener {
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, Items.PIE_DISH_2313, Items.PASTRY_DOUGH_1953) { player, used, with ->
|
||||
val product = Items.PIE_SHELL_2315
|
||||
val level = 1
|
||||
val experience = 0.0
|
||||
val message = "You put the pastry dough into the pie dish to make a pie shell."
|
||||
val failMessage = ""
|
||||
|
||||
return@onUseWith standardMix(
|
||||
player,
|
||||
used.asItem(),
|
||||
with.asItem(),
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class PizzaListener : InteractionListener {
|
||||
|
||||
val base = PizzaProduct.values().map { it.base }.toIntArray()
|
||||
val added = PizzaProduct.values().map { it.added }.toIntArray()
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, base, *added) { player, used, with ->
|
||||
val pizza = PizzaProduct.productMap[used.id] ?: return@onUseWith true
|
||||
|
||||
if (pizza.added != with.id) {
|
||||
return@onUseWith false
|
||||
}
|
||||
|
||||
val product = pizza.product
|
||||
val level = pizza.minimumLevel
|
||||
val experience = pizza.experience
|
||||
val message = "You add the ${pizza.message} to the pizza."
|
||||
val failMessage = "You need a Cooking level of at least ${pizza.minimumLevel} in order to do this."
|
||||
|
||||
return@onUseWith standardMix(
|
||||
player,
|
||||
used.asItem(),
|
||||
with.asItem(),
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
enum class PizzaProduct(
|
||||
val base: Int,
|
||||
val added: Int,
|
||||
val product: Int,
|
||||
val minimumLevel: Int,
|
||||
val experience: Double,
|
||||
val message: String,
|
||||
) {
|
||||
PIZZA_1(Items.TOMATO_1982, Items.PIZZA_BASE_2283, Items.INCOMPLETE_PIZZA_2285, 35, 0.0,"tomato"),
|
||||
PIZZA_2(Items.CHEESE_1985, Items.INCOMPLETE_PIZZA_2285, Items.UNCOOKED_PIZZA_2287, 35, 0.0, "cheese"),
|
||||
MEAT_PIZZA_1(Items.COOKED_MEAT_2142, Items.PLAIN_PIZZA_2289, Items.MEAT_PIZZA_2293, 45, 26.0, "meat"),
|
||||
MEAT_PIZZA_2(Items.COOKED_CHICKEN_2140, Items.PLAIN_PIZZA_2289, Items.MEAT_PIZZA_2293, 45, 26.0, "cooked chicken"),
|
||||
ANCHOVY_PIZZA(Items.ANCHOVIES_319, Items.PLAIN_PIZZA_2289, Items.ANCHOVY_PIZZA_2297, 55, 39.0, "anchovies"),
|
||||
PINEAPPLE_PIZZA_1(Items.PINEAPPLE_CHUNKS_2116, Items.PLAIN_PIZZA_2289, Items.PINEAPPLE_PIZZA_2301, 65, 52.0, "pineapple"),
|
||||
PINEAPPLE_PIZZA_2(Items.PINEAPPLE_RING_2118, Items.PLAIN_PIZZA_2289, Items.PINEAPPLE_PIZZA_2301, 65, 52.0, "pineapple"),
|
||||
;
|
||||
|
||||
companion object {
|
||||
val productMap = HashMap<Int, PizzaProduct>()
|
||||
|
||||
init {
|
||||
for (pizza in PizzaProduct.values()) {
|
||||
productMap[pizza.base] = pizza
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class PotatoListener : InteractionListener {
|
||||
|
||||
val added = PotatoProduct.values().map { it.added }.toIntArray()
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, Items.BAKED_POTATO_6701, Items.PAT_OF_BUTTER_6697) { player, used, with ->
|
||||
val product = Items.POTATO_WITH_BUTTER_6703
|
||||
val level = 39
|
||||
val experience = 40.5
|
||||
val message = "You add a pat of butter to the potato."
|
||||
val failMessage = "You need a Cooking level of at least $level in order to do this."
|
||||
|
||||
return@onUseWith standardMix(
|
||||
player,
|
||||
used.asItem(),
|
||||
with.asItem(),
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
)
|
||||
}
|
||||
|
||||
onUseWith(IntType.ITEM, added, Items.POTATO_WITH_BUTTER_6703) { player, used, with ->
|
||||
val topping = PotatoProduct.productMap[used.id] ?: return@onUseWith true
|
||||
|
||||
val product = topping.product
|
||||
val level = topping.minimumLevel
|
||||
val experience = topping.experience
|
||||
val message = ""
|
||||
val failMessage = "You need a Cooking level of at least $level in order to do this."
|
||||
|
||||
return@onUseWith standardMix(
|
||||
player,
|
||||
used.asItem(),
|
||||
with.asItem(),
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
enum class PotatoProduct(
|
||||
val added: Int,
|
||||
val product: Int,
|
||||
val minimumLevel: Int,
|
||||
val experience: Double,
|
||||
val message: String
|
||||
) {
|
||||
CHEESE_POTATO(Items.CHEESE_1985, Items.POTATO_WITH_CHEESE_6705, 47, 10.0, ""),
|
||||
CHILLI_POTATO(Items.CHILLI_CON_CARNE_7062, Items.CHILLI_POTATO_7054, 41, 15.0, ""),
|
||||
EGG_POTATO(Items.EGG_AND_TOMATO_7064, Items.EGG_POTATO_7056, 51, 50.0, ""),
|
||||
TUNA_POTATO(Items.TUNA_AND_CORN_7068, Items.TUNA_POTATO_7060, 68, 10.0, ""),
|
||||
MUSHROOM_POTATO(Items.MUSHROOM_AND_ONION_7066, Items.MUSHROOM_POTATO_7058, 64, 55.0, ""),
|
||||
;
|
||||
|
||||
companion object {
|
||||
val productMap = HashMap<Int, PotatoProduct>()
|
||||
|
||||
init {
|
||||
for (topping in PotatoProduct.values()) {
|
||||
productMap[topping.added] = topping
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
package content.global.skill.cooking.recipe;
|
||||
|
||||
import content.global.skill.cooking.recipe.pie.impl.*;
|
||||
import content.global.skill.cooking.recipe.pizza.impl.AnchovyPizza;
|
||||
import content.global.skill.cooking.recipe.pizza.impl.MeatPizza;
|
||||
import content.global.skill.cooking.recipe.pizza.impl.PineapplePizza;
|
||||
import content.global.skill.cooking.recipe.pizza.impl.PlainPizza;
|
||||
import content.global.skill.cooking.recipe.potato.impl.*;
|
||||
import content.global.skill.cooking.recipe.stew.CurryRecipe;
|
||||
import content.global.skill.cooking.recipe.stew.StewRecipe;
|
||||
import content.global.skill.cooking.recipe.topping.impl.*;
|
||||
import content.global.skill.cooking.recipe.cake.ChocolateCake;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents a cooking recipe, this is dynamic that can range from a pie to a
|
||||
* pizza.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public abstract class Recipe {
|
||||
|
||||
/**
|
||||
* Represents the array of active recipes in 2009Scape.
|
||||
*/
|
||||
// TODO:
|
||||
// - Making this an enum would drastically save on file/line count, since the recipes seem to mostly be plain-old-data classes
|
||||
// - Making pie shells a recipe would make make-x for them just work
|
||||
// - Making pineapple cutting a recipe would probably fix their make-x making all with any option
|
||||
public static final Recipe[] RECIPES = new Recipe[] {
|
||||
new RedberryPie(), new MeatPie(), new ApplePie(), new MudPie(), new GardenPie(), new FishPie(), new AdmiralPie(), new WildPie(), new SummerPie(),
|
||||
new StewRecipe(), new CurryRecipe(),
|
||||
new PlainPizza(), new MeatPizza(), new AnchovyPizza(), new PineapplePizza(),
|
||||
new ChocolateCake(),
|
||||
new ButterPotato(), new ChilliPotato(), new CheesePotato(), new EggPotato(), new MushroomPotato(), new TunaPotato(),
|
||||
new SpicySauce(), new ChilliConCarne(), new UncookedEgg(), new EggAndTomato(), new MushroomAndOnion(), new ChoppedOnion(), new SlicedMushroom(), new ChoppedTuna(), new TunaAndCorn(), new OomlieWrap()
|
||||
};
|
||||
|
||||
/**
|
||||
* Method used to get the base item.
|
||||
* @return the item.
|
||||
*/
|
||||
public abstract Item getBase();
|
||||
|
||||
/**
|
||||
* Method used to get the product item.
|
||||
* @return the product item.
|
||||
*/
|
||||
public abstract Item getProduct();
|
||||
|
||||
/**
|
||||
* Method used to get the ingredients in this recipe.
|
||||
* @return the ingredients.
|
||||
*/
|
||||
public abstract Item[] getIngredients();
|
||||
|
||||
/**
|
||||
* Method used to get the part items made from ingredients.
|
||||
* @return the part items.
|
||||
*/
|
||||
public abstract Item[] getParts();
|
||||
|
||||
/**
|
||||
* Method used to get the mixing message.
|
||||
* @param event the node usage event.
|
||||
* @return the message used to mix.
|
||||
*/
|
||||
public abstract String getMixMessage(final NodeUsageEvent event);
|
||||
|
||||
/**
|
||||
* Method used to check if this is a singular one step recipe.
|
||||
* @return <code>True</code> if so.
|
||||
*/
|
||||
public abstract boolean isSingular();
|
||||
|
||||
/**
|
||||
* Method used to mix this recipes ingredients.
|
||||
* @param player the player.
|
||||
* @param event the event.
|
||||
*/
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (getIngredients().length == 1) {
|
||||
singleMix(player, event);
|
||||
} else {
|
||||
multipleMix(player, event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to handle a single mixing.
|
||||
* @param player the player.
|
||||
* @param event the event.
|
||||
*/
|
||||
public void singleMix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getInventory().remove(event.getBaseItem()) && player.getInventory().remove(event.getUsedItem())) {
|
||||
player.getInventory().add(getProduct());
|
||||
String message = getMixMessage(event);
|
||||
if (message != null) {
|
||||
player.getPacketDispatch().sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to handle mixing multiple item recipes.
|
||||
* @param player the player.
|
||||
* @param event the event.
|
||||
*/
|
||||
public void multipleMix(final Player player, final NodeUsageEvent event) {
|
||||
Item item = null;
|
||||
int index = -1;
|
||||
for (int counter = 0; counter < getIngredients().length; counter++) {
|
||||
item = getIngredients()[counter];
|
||||
if (item.getId() == event.getUsedItem().getId() || item.getId() == event.getBaseItem().getId()) {
|
||||
index = counter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index != -1) {
|
||||
if (!player.getInventory().containItems(event.getBaseItem().getId(), event.getUsedItem().getId())) {
|
||||
return;
|
||||
}
|
||||
if (player.getInventory().remove(event.getBaseItem()) && player.getInventory().remove(event.getUsedItem())) {
|
||||
player.getInventory().add(getParts()[index + 1]);
|
||||
String message = getMixMessage(event);
|
||||
if (message != null) {
|
||||
player.getPacketDispatch().sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class StewListener : InteractionListener {
|
||||
|
||||
val base = StewProduct.values().map { it.base }.toIntArray()
|
||||
val added = StewProduct.values().map { it.added }.toIntArray()
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, base, *added) { player, used, with ->
|
||||
val stew = StewProduct.productMap[used.id] ?: return@onUseWith true
|
||||
|
||||
if (stew.added != with.id) {
|
||||
return@onUseWith false
|
||||
}
|
||||
|
||||
val product = stew.product
|
||||
val level = stew.minimumLevel
|
||||
val experience = 0.0
|
||||
val message = "You cut up the ${stew.message} and put it into the stew."
|
||||
val failMessage = "You need a Cooking level of at least ${stew.minimumLevel} in order to do this."
|
||||
|
||||
return@onUseWith standardMix(
|
||||
player,
|
||||
used.asItem(),
|
||||
with.asItem(),
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
enum class StewProduct(
|
||||
val base: Int,
|
||||
val added: Int,
|
||||
val product: Int,
|
||||
val minimumLevel: Int,
|
||||
val message: String,
|
||||
) {
|
||||
STEW_1(Items.POTATO_1942, Items.BOWL_OF_WATER_1921, Items.INCOMPLETE_STEW_1997, 25, "potato"),
|
||||
STEW_2(Items.INCOMPLETE_STEW_1997, Items.COOKED_MEAT_2142, Items.UNCOOKED_STEW_2001, 25, "meat"),
|
||||
STEW_3(Items.COOKED_MEAT_2142, Items.BOWL_OF_WATER_1921, Items.INCOMPLETE_STEW_1999, 25, "meat"),
|
||||
STEW_4(Items.INCOMPLETE_STEW_1999, Items.POTATO_1942, Items.UNCOOKED_STEW_2001, 25, "potato"),
|
||||
;
|
||||
|
||||
companion object {
|
||||
val productMap = HashMap<Int, StewProduct>()
|
||||
|
||||
init {
|
||||
for (stew in StewProduct.values()) {
|
||||
productMap[stew.base] = stew
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package content.global.skill.cooking.recipe
|
||||
|
||||
import core.api.inInventory
|
||||
import core.api.sendDialogue
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class ToppingListener : InteractionListener {
|
||||
|
||||
val base = ToppingProduct.values().map { it.base }.toIntArray()
|
||||
val added = ToppingProduct.values().map { it.added }.toIntArray()
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, base, *added) { player, used, with ->
|
||||
val topping = ToppingProduct.productMap[used.id] ?: return@onUseWith true
|
||||
val verb = if (with.id == Items.COOKED_MEAT_2142) "cut" else "slice"
|
||||
|
||||
if (topping.added != with.id) {
|
||||
return@onUseWith false
|
||||
}
|
||||
|
||||
if (topping.cut_name != "" && !inInventory(player, Items.KNIFE_946)) {
|
||||
sendDialogue(player, "You need a knife in order to $verb up the ${topping.cut_name}.")
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
val product = topping.product
|
||||
val level = topping.minimumLevel
|
||||
val experience = topping.experience
|
||||
val message = topping.message
|
||||
val failMessage = "You need a Cooking level of at least ${topping.minimumLevel} in order to do this."
|
||||
|
||||
return@onUseWith standardMix(
|
||||
player,
|
||||
used.asItem(),
|
||||
with.asItem(),
|
||||
product,
|
||||
level,
|
||||
experience,
|
||||
message,
|
||||
failMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
enum class ToppingProduct(
|
||||
val base: Int,
|
||||
val added: Int,
|
||||
val product: Int,
|
||||
val minimumLevel: Int,
|
||||
val experience: Double,
|
||||
val message: String,
|
||||
val cut_name: String
|
||||
) {
|
||||
//Tuna and Corn: https://www.youtube.com/watch?v=wAavERc9p2c
|
||||
//Uncooked Egg: https://www.youtube.com/watch?v=LiLq6PhCc2M
|
||||
//Bowl of sweetcorn (OSRS source is only I could find) https://www.youtube.com/watch?v=pz8epXjkKYE
|
||||
|
||||
UNCOOKED_EGG(Items.EGG_1944, Items.BOWL_1923, Items.UNCOOKED_EGG_7076, 1, 0.0, "You carefully break the egg into the bowl.", ""),
|
||||
BOWL_OF_SWEETCORN(Items.COOKED_SWEETCORN_5988, Items.BOWL_1923, Items.SWEETCORN_7088, 1, 0.0, "You put the cooked sweetcorn into the bowl.", ""),
|
||||
SLICED_MUSHROOM(Items.MUSHROOM_6004, Items.BOWL_1923, Items.SLICED_MUSHROOMS_7080, 1, 0.0, "You chop the mushrooms into the bowl.", "mushrooms"),
|
||||
CHOPPED_TUNA(Items.TUNA_361, Items.BOWL_1923, Items.CHOPPED_TUNA_7086, 1, 0.0, "You chop the tuna into the bowl.", "tuna"),
|
||||
CHOPPED_ONION(Items.ONION_1957, Items.BOWL_1923, Items.CHOPPED_ONION_1871, 1, 0.0, "You chop the onion into the bowl.", "onion"),
|
||||
CHOPPED_GARLIC(Items.GARLIC_1550, Items.BOWL_1923, Items.CHOPPED_GARLIC_7074, 1, 0.0, "You chop the garlic into the bowl.", "garlic"),
|
||||
SPICY_SAUCE(Items.CHOPPED_GARLIC_7074, Items.GNOME_SPICE_2169, Items.SPICY_SAUCE_7072, 9, 25.0, "You mix the ingredients to make the topping.", ""), //inauthentic, used generic mixing message
|
||||
CHILLI_CON_CARNE(Items.SPICY_SAUCE_7072, Items.COOKED_MEAT_2142, Items.CHILLI_CON_CARNE_7062, 9, 0.0, "You mix the ingredients to make the topping.", "meat"), //inauthentic, used generic mixing message
|
||||
EGG_AND_TOMATO(Items.TOMATO_1982, Items.SCRAMBLED_EGG_7078, Items.EGG_AND_TOMATO_7064, 23, 50.0, "You mix the ingredients to make the topping.", ""),
|
||||
MUSHROOM_AND_ONION(Items.FRIED_MUSHROOMS_7082, Items.FRIED_ONIONS_7084, Items.MUSHROOM_AND_ONION_7066, 57, 120.0, "You mix the ingredients to make the topping.", ""),
|
||||
TUNA_AND_CORN_1(Items.CHOPPED_TUNA_7086, Items.COOKED_SWEETCORN_5988, Items.TUNA_AND_CORN_7068, 67, 204.0, "You mix the ingredients to make the topping.", ""),
|
||||
TUNA_AND_CORN_2(Items.SWEETCORN_7088, Items.TUNA_361, Items.TUNA_AND_CORN_7068, 67, 204.0, "You mix the ingredients to make the topping.", "tuna"),
|
||||
;
|
||||
|
||||
companion object {
|
||||
val productMap = HashMap<Int, ToppingProduct>()
|
||||
|
||||
init {
|
||||
for (topping in ToppingProduct.values()) {
|
||||
productMap[topping.base] = topping
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.cake;
|
||||
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the chocolate cake recipe. This recipe consists of adding a
|
||||
* chocolate bar to a cake.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class ChocolateCake extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the cake item.
|
||||
*/
|
||||
private static final Item CAKE = new Item(1891);
|
||||
|
||||
/**
|
||||
* Represents the chocolate cake item.
|
||||
*/
|
||||
private static final Item CHOCOLATE_CAKE = new Item(1897);
|
||||
|
||||
/**
|
||||
* Represents the chocolate bar item.
|
||||
*/
|
||||
private static final Item CHOCOLATE_BAR = new Item(1973);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < 50) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of 50 in order to do that.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
player.getSkills().addExperience(Skills.COOKING, 30, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return CAKE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return CHOCOLATE_CAKE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { CHOCOLATE_BAR };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return "You add chocolate to the cake.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pie;
|
||||
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the generic recipe for a pie.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public abstract class PieRecipe extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the pie shell item.
|
||||
*/
|
||||
protected static final Item PIE_SHELL = new Item(2315);
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return PIE_SHELL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(final NodeUsageEvent event) {
|
||||
return "You fill the pie with " + (event.getBaseItem().getId() == 2315 ? event.getUsedItem().getName().toLowerCase() : event.getBaseItem().getName().toLowerCase()) + ".";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pie.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pie.PieRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the admiral pie recipe. This recipe conists of pixing a salmon,
|
||||
* tuna and potato together.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public class AdmiralPie extends PieRecipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked redberry pie.
|
||||
*/
|
||||
private static final Item UNCOOKED_PIE = new Item(7196);
|
||||
|
||||
/**
|
||||
* Represents the salmon ingredient item.
|
||||
*/
|
||||
private static final Item SALMON = new Item(329);
|
||||
|
||||
/**
|
||||
* Represents the tuna ingredient item.
|
||||
*/
|
||||
private static final Item TUNA = new Item(361);
|
||||
|
||||
/**
|
||||
* Represents the potato item.
|
||||
*/
|
||||
private static final Item POTATO = new Item(1942);
|
||||
|
||||
/**
|
||||
* Represents the part one pie item.
|
||||
*/
|
||||
private static final Item PART_ONE = new Item(7192);
|
||||
|
||||
/**
|
||||
* Represents the part two pie item.
|
||||
*/
|
||||
private static final Item PART_TWO = new Item(7194);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_PIE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { SALMON, TUNA, POTATO };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] { PIE_SHELL, PART_ONE, PART_TWO, UNCOOKED_PIE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pie.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pie.PieRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the apple pie recipe. This recipe consists of cooking apples and a
|
||||
* pie shell.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public class ApplePie extends PieRecipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked redberry pie.
|
||||
*/
|
||||
private static final Item UNCOOKED_PIE = new Item(2317);
|
||||
|
||||
/**
|
||||
* Represents the cooking apple item.
|
||||
*/
|
||||
private static final Item COOKING_APPLE = new Item(1955);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_PIE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { COOKING_APPLE };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pie.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pie.PieRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the garden pie recipe. This pie consists of mixing, tomato, onion,
|
||||
* and cabbage together.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public class FishPie extends PieRecipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked redberry pie.
|
||||
*/
|
||||
private static final Item UNCOOKED_PIE = new Item(7186);
|
||||
|
||||
/**
|
||||
* Represents the trout item ingredient.
|
||||
*/
|
||||
private static final Item TROUT = new Item(333);
|
||||
|
||||
/**
|
||||
* Represents the cod item ingredient.
|
||||
*/
|
||||
private static final Item COD = new Item(339);
|
||||
|
||||
/**
|
||||
* Represents the potato item.
|
||||
*/
|
||||
private static final Item POTATO = new Item(1942);
|
||||
|
||||
/**
|
||||
* Represents the part one pie item.
|
||||
*/
|
||||
private static final Item PART_ONE = new Item(7182);
|
||||
|
||||
/**
|
||||
* Represents the part two pie item.
|
||||
*/
|
||||
private static final Item PART_TWO = new Item(7184);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_PIE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { TROUT, COD, POTATO };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] { PIE_SHELL, PART_ONE, PART_TWO, UNCOOKED_PIE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pie.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pie.PieRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the garden pie recipe. This pie consists of mixing, tomato, onion,
|
||||
* and cabbage together.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public class GardenPie extends PieRecipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked redberry pie.
|
||||
*/
|
||||
private static final Item UNCOOKED_PIE = new Item(7176);
|
||||
|
||||
/**
|
||||
* Represents the tomato ingredient item.
|
||||
*/
|
||||
private static final Item TOMATO = new Item(1982);
|
||||
|
||||
/**
|
||||
* Represents the onion ingredient item.
|
||||
*/
|
||||
private static final Item ONION = new Item(1957);
|
||||
|
||||
/**
|
||||
* Represents the cabbage ingredient item.
|
||||
*/
|
||||
private static final Item CABBAGE = new Item(1965);
|
||||
|
||||
/**
|
||||
* Represents the part one pie item.
|
||||
*/
|
||||
private static final Item PART_ONE = new Item(7172);
|
||||
|
||||
/**
|
||||
* Represents the part two pie item.
|
||||
*/
|
||||
private static final Item PART_TWO = new Item(7174);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_PIE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { TOMATO, ONION, CABBAGE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] { PIE_SHELL, PART_ONE, PART_TWO, UNCOOKED_PIE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pie.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pie.PieRecipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the meat pie recipe.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public class MeatPie extends PieRecipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked redberry pie.
|
||||
*/
|
||||
private static final Item UNCOOKED_PIE = new Item(2319);
|
||||
|
||||
/**
|
||||
* Represents the cooked meat item.
|
||||
*/
|
||||
private static final Item COOKED_MEAT = new Item(2142);
|
||||
|
||||
/**
|
||||
* Represents the cooked chicken item.
|
||||
*/
|
||||
private static final Item COOKED_CHICKEN = new Item(2140);
|
||||
|
||||
/**
|
||||
* Represents the cooked rabbit.
|
||||
*/
|
||||
private static final Item COOKED_RABBIT = new Item(3228);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getInventory().remove(event.getUsedItem()) && player.getInventory().remove(event.getBaseItem())) {
|
||||
player.getInventory().add(getProduct());
|
||||
player.getPacketDispatch().sendMessage(getMixMessage(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_PIE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { COOKED_MEAT, COOKED_CHICKEN, COOKED_RABBIT };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(final NodeUsageEvent event) {
|
||||
return "You fill the pie with meat.";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pie.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pie.PieRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the mud pie recipe. A mud pie consists of mixing compost, water
|
||||
* and clay together.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public class MudPie extends PieRecipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked redberry pie.
|
||||
*/
|
||||
private static final Item UNCOOKED_PIE = new Item(7168);
|
||||
|
||||
/**
|
||||
* Represents the compost item.
|
||||
*/
|
||||
private static final Item COMPOST = new Item(6032);
|
||||
|
||||
/**
|
||||
* Represents the bucket of water item.
|
||||
*/
|
||||
private static final Item BUCKET_OF_WATER = new Item(1929);
|
||||
|
||||
/**
|
||||
* Represents the clay item.
|
||||
*/
|
||||
private static final Item CLAY = new Item(434);
|
||||
|
||||
/**
|
||||
* Represents the part one pie item.
|
||||
*/
|
||||
private static final Item PART_ONE = new Item(7164);
|
||||
|
||||
/**
|
||||
* Represents the part two pie item.
|
||||
*/
|
||||
private static final Item PART_TWO = new Item(7166);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_PIE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { COMPOST, BUCKET_OF_WATER, CLAY };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] { PIE_SHELL, PART_ONE, PART_TWO, UNCOOKED_PIE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pie.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pie.PieRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents a redberry pie recipe.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public class RedberryPie extends PieRecipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked redberry pie.
|
||||
*/
|
||||
private static final Item UNCOOKED_PIE = new Item(2321);
|
||||
|
||||
/**
|
||||
* Represents the redberries pie.
|
||||
*/
|
||||
private static final Item REDBERRIES = new Item(1951);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_PIE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { REDBERRIES };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pie.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pie.PieRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the summer pie recipe. This recipe consists of mixing stawberry,
|
||||
* watermelon, and an apple.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public class SummerPie extends PieRecipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked redberry pie.
|
||||
*/
|
||||
private static final Item UNCOOKED_PIE = new Item(7216);
|
||||
|
||||
/**
|
||||
* Represents the strawberry item.
|
||||
*/
|
||||
private static final Item STRAWBERRY = new Item(5504);
|
||||
|
||||
/**
|
||||
* Represents the watermelon item.
|
||||
*/
|
||||
private static final Item WATERMELON = new Item(5982);
|
||||
|
||||
/**
|
||||
* Represents the cooking apple item.
|
||||
*/
|
||||
private static final Item COOKING_APPLE = new Item(1955);
|
||||
|
||||
/**
|
||||
* Represents the part one pie item.
|
||||
*/
|
||||
private static final Item PART_ONE = new Item(7212);
|
||||
|
||||
/**
|
||||
* Represents the part two pie item.
|
||||
*/
|
||||
private static final Item PART_TWO = new Item(7214);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_PIE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { STRAWBERRY, WATERMELON, COOKING_APPLE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] { PIE_SHELL, PART_ONE, PART_TWO, UNCOOKED_PIE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pie.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pie.PieRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the wild pie recipe. This recipe consists of mixing raw beat meat,
|
||||
* raw chomp, and raw rabbit into a pie shell.
|
||||
* @author 'Vexia
|
||||
* @date 21/12/2013
|
||||
*/
|
||||
public class WildPie extends PieRecipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked redberry pie.
|
||||
*/
|
||||
private static final Item UNCOOKED_PIE = new Item(7206);
|
||||
|
||||
/**
|
||||
* Represents the raw bear meat item.
|
||||
*/
|
||||
private static final Item BEAR_MEAT = new Item(2136);
|
||||
|
||||
/**
|
||||
* Represents the raw chompy meat item.
|
||||
*/
|
||||
private static final Item CHOMPY_MEAT = new Item(2876);
|
||||
|
||||
/**
|
||||
* Represents the raw rabbit meat item.
|
||||
*/
|
||||
private static final Item RABBIT_MEAT = new Item(3226);
|
||||
|
||||
/**
|
||||
* Represents the part one pie item.
|
||||
*/
|
||||
private static final Item PART_ONE = new Item(7202);
|
||||
|
||||
/**
|
||||
* Represents the part two pie item.
|
||||
*/
|
||||
private static final Item PART_TWO = new Item(7204);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_PIE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { BEAR_MEAT, CHOMPY_MEAT, RABBIT_MEAT };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] { PIE_SHELL, PART_ONE, PART_TWO, UNCOOKED_PIE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pizza;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the generic recipe for a pizza.
|
||||
* @author ceikry
|
||||
*/
|
||||
public abstract class PizzaRecipe extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the plain pizza.
|
||||
*/
|
||||
protected static final Item PLAIN_PIZZA = new Item(2289);
|
||||
|
||||
/**
|
||||
* Method used to get the experience gained from adding the final
|
||||
* ingredient.
|
||||
* @return the experience.
|
||||
*/
|
||||
public abstract double getExperience();
|
||||
|
||||
/**
|
||||
* Method used to get the level required.
|
||||
* @return the level required.
|
||||
*/
|
||||
public abstract int getLevel();
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < getLevel()) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of at least " + getLevel() + " in order to do this.");
|
||||
return;
|
||||
}
|
||||
super.singleMix(player, event);
|
||||
player.getSkills().addExperience(Skills.COOKING, getExperience(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return PLAIN_PIZZA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(final NodeUsageEvent event) {
|
||||
return "You add " + event.getBaseItem().getName().toLowerCase() + " to the pizza.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pizza.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pizza.PizzaRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the anchovy pizza. This recipe consists of adding anchovies to a
|
||||
* plain pizza.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class AnchovyPizza extends PizzaRecipe {
|
||||
|
||||
/**
|
||||
* Represents the anchovy pizza item.
|
||||
*/
|
||||
private static final Item ANCHOVY_PIZZA = new Item(2297);
|
||||
|
||||
/**
|
||||
* Represents the anchovies item.
|
||||
*/
|
||||
private static final Item ANCHOVIES = new Item(319);
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 39;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return ANCHOVY_PIZZA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { ANCHOVIES };
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 55;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pizza.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pizza.PizzaRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the meat pizza recipe. This recipe consists of adding cooked meat
|
||||
* to a plain pizza.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class MeatPizza extends PizzaRecipe {
|
||||
|
||||
/**
|
||||
* Represents the meat pizza item.
|
||||
*/
|
||||
private static final Item MEAT_PIZZA = new Item(2293);
|
||||
|
||||
/**
|
||||
* Represents the cooked meat item.
|
||||
*/
|
||||
private static final Item COOKED_MEAT = new Item(2142);
|
||||
|
||||
/**
|
||||
* Represents the cooked chicken item.
|
||||
*/
|
||||
private static final Item COOKED_CHICKEN = new Item(2140);
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 26;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 45;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return MEAT_PIZZA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { COOKED_MEAT, COOKED_CHICKEN };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pizza.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.pizza.PizzaRecipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the pineapple pizza recipe. This recipe consists of mixing either
|
||||
* pineapple chunks or pineapple rings.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class PineapplePizza extends PizzaRecipe {
|
||||
|
||||
/**
|
||||
* Represents the pineapple pizza item.
|
||||
*/
|
||||
private static final Item PINEAPPLE_PIZZA = new Item(2301);
|
||||
|
||||
/**
|
||||
* Represents the pineapple ring item.
|
||||
*/
|
||||
private static final Item PINEAPPLE_RING = new Item(2118);
|
||||
|
||||
/**
|
||||
* Represents the pineapple chunk item.
|
||||
*/
|
||||
private static final Item PINEAPPLE_CHUNKS = new Item(2116);
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 52;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 65;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return PINEAPPLE_PIZZA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { PINEAPPLE_CHUNKS, PINEAPPLE_RING };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return "You add the " + event.getBaseItem().getName().toLowerCase() + " to the pizza.";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.pizza.impl;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the plain pizza recipe. This recipe consists of mixing tomato, and
|
||||
* cheese to a pizza base.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class PlainPizza extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the pizza base.
|
||||
*/
|
||||
private static final Item PIZZA_BASE = new Item(2283);
|
||||
|
||||
/**
|
||||
* Represents the uncooked pizza.
|
||||
*/
|
||||
private static final Item UNCOOKED_PIZZA = new Item(2287);
|
||||
|
||||
/**
|
||||
* Represents the incomplete pizza.
|
||||
*/
|
||||
private static final Item INCOMPLETE_PIZZA = new Item(2285);
|
||||
|
||||
/**
|
||||
* Represents the tomato ingredient item.
|
||||
*/
|
||||
private static final Item TOMATO = new Item(1982);
|
||||
|
||||
/**
|
||||
* Represents the cheese item.
|
||||
*/
|
||||
private static final Item CHEESE = new Item(1985);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < 35) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of at least " + 35 + " in order to do this.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return PIZZA_BASE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_PIZZA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { TOMATO, CHEESE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] { PIZZA_BASE, INCOMPLETE_PIZZA, UNCOOKED_PIZZA };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return "You add the " + event.getBaseItem().getName().toLowerCase() + " to the pizza.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.potato;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents a generic potato topping recipe.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public abstract class PotatoRecipe extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the potato with butter.
|
||||
*/
|
||||
private static final Item POTATO_WITH_BUTTER = new Item(6703);
|
||||
|
||||
/**
|
||||
* Represents the bowl item.
|
||||
*/
|
||||
protected static final Item BOWL = new Item(1923);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < getLevel()) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of at least " + getLevel() + " in order to do this.");
|
||||
return;
|
||||
}
|
||||
super.singleMix(player, event);
|
||||
if (isTopping()) {
|
||||
player.getInventory().add(BOWL);
|
||||
}
|
||||
player.getSkills().addExperience(Skills.COOKING, getExperience(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return POTATO_WITH_BUTTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to check if it is a topping recipe.
|
||||
* @return <code>True</code> if it is a topping.
|
||||
*/
|
||||
public abstract boolean isTopping();
|
||||
|
||||
/**
|
||||
* Method used to get the level required.
|
||||
* @return the level.
|
||||
*/
|
||||
public abstract int getLevel();
|
||||
|
||||
/**
|
||||
* Method used to get the experience gained.
|
||||
* @return the experience.
|
||||
*/
|
||||
public abstract double getExperience();
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.potato.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the butter potato recipe. This recipe consists of adding a pat of
|
||||
* butter to a potato.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class ButterPotato extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the baked potato.
|
||||
*/
|
||||
private static final Item BAKED_POTATO = new Item(6701);
|
||||
|
||||
/**
|
||||
* Represents the potato with butter.
|
||||
*/
|
||||
private static final Item POTATO_WITH_BUTTER = new Item(6703);
|
||||
|
||||
/**
|
||||
* Represents the pat of butter.
|
||||
*/
|
||||
private static final Item PAT_OF_BUTTER = new Item(6697);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < 39) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of at least " + 39 + " in order to do this.");
|
||||
return;
|
||||
}
|
||||
super.singleMix(player, event);
|
||||
player.getSkills().addExperience(Skills.COOKING, 40.5, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return BAKED_POTATO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return POTATO_WITH_BUTTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { PAT_OF_BUTTER };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return "You add a pat of butter to the potato.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.potato.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.potato.PotatoRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the cheese potato. This recipe consists of mixing cheese witha
|
||||
* baked potato.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class CheesePotato extends PotatoRecipe {
|
||||
|
||||
/**
|
||||
* Represents the cheese potato.
|
||||
*/
|
||||
private static final Item CHEESE_POTATO = new Item(6705);
|
||||
|
||||
/**
|
||||
* Represents the cheese item.
|
||||
*/
|
||||
private static final Item CHEESE = new Item(1985);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return CHEESE_POTATO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { CHEESE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTopping() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 47;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.potato.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.potato.PotatoRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the chilli potato recipe. This recipe consists of adding chilli
|
||||
* con carne to a baked butter potato.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class ChilliPotato extends PotatoRecipe {
|
||||
|
||||
/**
|
||||
* Represents the chilli potato item.
|
||||
*/
|
||||
private static final Item CHILLI_POTATO = new Item(7054);
|
||||
|
||||
/**
|
||||
* Represents the chilli con carne item/
|
||||
*/
|
||||
private static final Item CHILLI_CON_CARNE = new Item(7062);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return CHILLI_POTATO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { CHILLI_CON_CARNE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTopping() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 41;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.potato.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.potato.PotatoRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the egg potato recipe. This recipe consists of mixing a egg and a
|
||||
* tomato.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class EggPotato extends PotatoRecipe {
|
||||
|
||||
/**
|
||||
* Represents the egg potato.
|
||||
*/
|
||||
private static final Item EGG_POTATO = new Item(7056);
|
||||
|
||||
/**
|
||||
* Represents the topping item.
|
||||
*/
|
||||
private static final Item TOPPING = new Item(7064);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return EGG_POTATO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { TOPPING };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTopping() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 51;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.potato.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.potato.PotatoRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the mushrrom potato. This recipe consists of mixing a baked potato
|
||||
* with mushroom and onion toppings.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class MushroomPotato extends PotatoRecipe {
|
||||
|
||||
/**
|
||||
* Represents the egg potato.
|
||||
*/
|
||||
private static final Item MUSHROOM_POTATO = new Item(7058);
|
||||
|
||||
/**
|
||||
* Represents the topping item.
|
||||
*/
|
||||
private static final Item TOPPING = new Item(7066);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return MUSHROOM_POTATO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { TOPPING };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTopping() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 64;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.potato.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.potato.PotatoRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the tuna potato recipe. This recipe consists of mixing tuna and
|
||||
* corn toppings.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class TunaPotato extends PotatoRecipe {
|
||||
|
||||
/**
|
||||
* Represents the tuna potato.
|
||||
*/
|
||||
private static final Item TUNA_POTATO = new Item(7060);
|
||||
|
||||
/**
|
||||
* Represents the topping item.
|
||||
*/
|
||||
private static final Item TOPPING = new Item(7068);
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return TUNA_POTATO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { TOPPING };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTopping() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 68;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.stew;
|
||||
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the curry recipe. This recipe consists of mixing 3 curry leaves or
|
||||
* a spice into a stew.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class CurryRecipe extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked curry item.
|
||||
*/
|
||||
private static final Item UNCOOKED_CURRY = new Item(2009);
|
||||
|
||||
/**
|
||||
* Represents the uncooked stew item.
|
||||
*/
|
||||
private static final Item UNCOOKED_STEW = new Item(2001);
|
||||
|
||||
/**
|
||||
* Represents the spice item.
|
||||
*/
|
||||
private static final Item SPICE = new Item(2007);
|
||||
|
||||
/**
|
||||
* Represents the curry leaf.
|
||||
*/
|
||||
private static final Item CURRY_LEAF = new Item(5970);
|
||||
|
||||
@Override
|
||||
public void mix(Player player, NodeUsageEvent event) {
|
||||
if (event.getBaseItem().getId() == CURRY_LEAF.getId() || event.getUsedItem().getId() == CURRY_LEAF.getId()) {
|
||||
Item stew = event.getBaseItem().getId() == UNCOOKED_STEW.getId() ? event.getBaseItem() : event.getUsedItem();
|
||||
if (stew.getCharge() == 1000) {
|
||||
stew.setCharge(1);
|
||||
}
|
||||
int charge = stew.getCharge();
|
||||
if (charge < 3) {
|
||||
player.getInventory().remove(CURRY_LEAF);
|
||||
stew.setCharge(charge + 1);
|
||||
} else {
|
||||
if (player.getInventory().remove(stew) && player.getInventory().remove(CURRY_LEAF)) {
|
||||
player.getInventory().add(UNCOOKED_CURRY);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (player.getInventory().remove(event.getBaseItem()) && player.getInventory().remove(event.getUsedItem())) {
|
||||
player.getInventory().add(getProduct());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return UNCOOKED_STEW;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_CURRY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { SPICE, CURRY_LEAF };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] { UNCOOKED_STEW };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return "You mix the spice with the stew.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.stew;
|
||||
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the stew recipe. This recipe consists of mixing meat and a raw
|
||||
* potato in a bowl of water.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class StewRecipe extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the uncooked stew item.
|
||||
*/
|
||||
private static final Item UNCOOKED_STEW = new Item(2001);
|
||||
|
||||
/**
|
||||
* Represents the bowl of water item.
|
||||
*/
|
||||
private static final Item BOWL_OF_WATER = new Item(1921);
|
||||
|
||||
/**
|
||||
* Represents the meat item.
|
||||
*/
|
||||
private static final Item MEAT = new Item(2142);
|
||||
|
||||
/**
|
||||
* Represents the potato item.
|
||||
*/
|
||||
private static final Item POTATO = new Item(1942);
|
||||
|
||||
/**
|
||||
* Represents the incomplete stew.
|
||||
*/
|
||||
private static final Item INCOMPLETE_STEW = new Item(1997);
|
||||
|
||||
/**
|
||||
* Represents the second incomplete stew.
|
||||
*/
|
||||
private static final Item INCOMPLETE_STEW2 = new Item(1999);
|
||||
|
||||
@Override
|
||||
public void mix(Player player, NodeUsageEvent event) {
|
||||
Item first = event.getUsedItem();
|
||||
Item second = event.getBaseItem();
|
||||
if(first != null && second != null) {
|
||||
if (player.getInventory().remove(first) && player.getInventory().remove(second)) {
|
||||
if (first.getId() == BOWL_OF_WATER.getId() || second.getId() == BOWL_OF_WATER.getId()) {
|
||||
player.getInventory().add(first.getId() == POTATO.getId() ? INCOMPLETE_STEW : first.getId() == MEAT.getId() ? INCOMPLETE_STEW2 : second.getId() == POTATO.getId() ? INCOMPLETE_STEW : second.getId() == MEAT.getId() ? INCOMPLETE_STEW2 : null);
|
||||
} else {
|
||||
player.getInventory().add(UNCOOKED_STEW);
|
||||
}
|
||||
player.getPacketDispatch().sendMessage(getMixMessage(event));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return BOWL_OF_WATER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_STEW;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { MEAT, POTATO, MEAT, POTATO };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] { BOWL_OF_WATER, BOWL_OF_WATER, INCOMPLETE_STEW, INCOMPLETE_STEW2 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return "You cut up the " + (event.getUsedItem().getName().toLowerCase().contains("incomplete") ? event.getBaseItem().getName().toLowerCase() : event.getUsedItem().getName().toLowerCase().replace("cooked", "").trim()) + " and put it into the stew.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.topping;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents a generic topping recipe.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public abstract class ToppingRecipe extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the bowl item.
|
||||
*/
|
||||
protected static final Item BOWL = new Item(1923);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < getLevel()) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of at least " + getLevel() + " in order to do this.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
player.getSkills().addExperience(Skills.COOKING, getExperience(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return BOWL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to get the level required.
|
||||
* @return the level.
|
||||
*/
|
||||
public abstract int getLevel();
|
||||
|
||||
/**
|
||||
* Method used to get the experience gained.
|
||||
* @return the experience.
|
||||
*/
|
||||
public abstract double getExperience();
|
||||
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.topping.impl;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the chilli con carne recipe. This recipe consists of using spicy
|
||||
* sauce with cooked meat.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class ChilliConCarne extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the bowl item.
|
||||
*/
|
||||
private static final Item SPICY_SAUCE = new Item(7072);
|
||||
|
||||
/**
|
||||
* Represents the chilli con carne item.
|
||||
*/
|
||||
private static final Item CHILLI_CON_CARNE = new Item(7062);
|
||||
|
||||
/**
|
||||
* Represents the cooked meat item.
|
||||
*/
|
||||
private static final Item COOKED_MEAT = new Item(2142);
|
||||
|
||||
/**
|
||||
* Represents the knife item.
|
||||
*/
|
||||
private static final Item KNIFE = new Item(946);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < 9) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of at least " + 9 + " in order to do this.");
|
||||
return;
|
||||
}
|
||||
if (!player.getInventory().containsItem(KNIFE)) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a knife in order to cut up the meat.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
player.getSkills().addExperience(Skills.COOKING, 25, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return SPICY_SAUCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return CHILLI_CON_CARNE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { COOKED_MEAT };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return "You put the cut up meat into the bowl.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.topping.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.topping.ToppingRecipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the chopped onion recipe. This recipe consists of using an onion
|
||||
* on a bowl with a knife.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class ChoppedOnion extends ToppingRecipe {
|
||||
|
||||
/**
|
||||
* Represents the chopped onion product item.
|
||||
*/
|
||||
private static final Item CHOPPED_ONION = new Item(1871);
|
||||
|
||||
/**
|
||||
* Represents the knife used to cut the onion.
|
||||
*/
|
||||
private static final Item KNIFE = new Item(946);
|
||||
|
||||
/**
|
||||
* Represents the onion item.
|
||||
*/
|
||||
private static final Item ONION = new Item(1957);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (!player.getInventory().containsItem(KNIFE)) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a knife in order to slice up the onion.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return CHOPPED_ONION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { ONION };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.topping.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.topping.ToppingRecipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the chopped tuna recipe. This recipe consists of adding tuna to a
|
||||
* bowl with a knife.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class ChoppedTuna extends ToppingRecipe {
|
||||
|
||||
/**
|
||||
* Represents the chopped tuna item.
|
||||
*/
|
||||
private static final Item CHOPPED_TUNA = new Item(7086);
|
||||
|
||||
/**
|
||||
* Represents the tuna item.
|
||||
*/
|
||||
private static final Item TUNA = new Item(361);
|
||||
|
||||
/**
|
||||
* Represents the knife item.
|
||||
*/
|
||||
private static final Item KNIFE = new Item(946);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (!player.getInventory().containsItem(KNIFE)) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a knife in order to slice up the tuna.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return CHOPPED_TUNA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { TUNA };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.topping.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the egg and tomato recipe. This recipe consists of mixing a tomato
|
||||
* with a scrambled egg.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class EggAndTomato extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the egg and tomato.
|
||||
*/
|
||||
private static final Item EGG_AND_TOMATO = new Item(7064);
|
||||
|
||||
/**
|
||||
* Represents the scrambled egg item.
|
||||
*/
|
||||
private static final Item SCRAMBLED_EGG = new Item(7078);
|
||||
|
||||
/**
|
||||
* epresents the tomato item.
|
||||
*/
|
||||
private static final Item TOMATO = new Item(1982);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < 23) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of at least " + 23 + " in order to do this.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
player.getSkills().addExperience(Skills.COOKING, 50, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return SCRAMBLED_EGG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return EGG_AND_TOMATO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { TOMATO };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.topping.impl;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the mushroom and onion recipe. This recipe consists of using a
|
||||
* fried mushroom with a friend onion.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class MushroomAndOnion extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the mushroom and onion item.
|
||||
*/
|
||||
private static final Item MUSHROOM_AND_ONION = new Item(7066);
|
||||
|
||||
/**
|
||||
* Represents the fried onions item.
|
||||
*/
|
||||
private static final Item FRIED_ONIONS = new Item(7084);
|
||||
|
||||
/**
|
||||
* Represents the fried mushrooms item.
|
||||
*/
|
||||
private static final Item FRIED_MUSHROOMS = new Item(7082);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < 57) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of at least " + 57 + " in order to do this.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
player.getSkills().addExperience(Skills.COOKING, 120, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return FRIED_MUSHROOMS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return MUSHROOM_AND_ONION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { FRIED_ONIONS };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.topping.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.topping.ToppingRecipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the fried mushroom recipe. This recipe consists of using a
|
||||
* mushroom on a bowl.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public final class SlicedMushroom extends ToppingRecipe {
|
||||
|
||||
/**
|
||||
* Represents the sliced mushrooms item.
|
||||
*/
|
||||
private static final Item SLICED_MUSHROOMS = new Item(7080);
|
||||
|
||||
/**
|
||||
* Represents the mushroom item.
|
||||
*/
|
||||
private static final Item MUSHROOM = new Item(6004);
|
||||
|
||||
/**
|
||||
* Represents the knife item.
|
||||
*/
|
||||
private static final Item KNIFE = new Item(946);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (!player.getInventory().containsItem(KNIFE)) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a knife in order to slice up the mushrooms.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return SLICED_MUSHROOMS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { MUSHROOM };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.topping.impl;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the spicy sauce recipe. This recipe consists of mixing gnome spice
|
||||
* and garlic together.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public class SpicySauce extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the spicy sauce item.
|
||||
*/
|
||||
private static final Item SPICY_SAUCE = new Item(7072);
|
||||
|
||||
/**
|
||||
* Represents the bowl item.
|
||||
*/
|
||||
private static final Item BOWL = new Item(1923);
|
||||
|
||||
/**
|
||||
* Represents the garlic item.
|
||||
*/
|
||||
private static final Item GARLIC = new Item(1550);
|
||||
|
||||
/**
|
||||
* Represents the chopped garlic item.
|
||||
*/
|
||||
private static final Item CHOPPED_GARLIC = new Item(7074);
|
||||
|
||||
/**
|
||||
* Represents the gnome spice item.
|
||||
*/
|
||||
private static final Item GNOME_SPICE = new Item(2169);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < 9) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of at least " + 9 + " in order to do this.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
if (event.getBaseItem().getId() == GNOME_SPICE.getId() || event.getUsedItem().getId() == GNOME_SPICE.getId()) {
|
||||
player.getSkills().addExperience(Skills.COOKING, 25, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return BOWL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return SPICY_SAUCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { GARLIC, GNOME_SPICE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] { BOWL, CHOPPED_GARLIC, SPICY_SAUCE };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.topping.impl;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.cooking.recipe.Recipe;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the tuna and corn recipe. This recipe consists of adding cooked
|
||||
* sweetcorn to a bowl of chopped tuna.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public final class TunaAndCorn extends Recipe {
|
||||
|
||||
/**
|
||||
* Represents the chopped tuna item.
|
||||
*/
|
||||
private static final Item CHOPPED_TUNA = new Item(7086);
|
||||
|
||||
/**
|
||||
* Represents the cooked corn item.
|
||||
*/
|
||||
private static final Item COOKED_CORN = new Item(5988);
|
||||
|
||||
/**
|
||||
* Represents the tuna and corn item.
|
||||
*/
|
||||
private static final Item TUNA_AND_CORN = new Item(7068);
|
||||
|
||||
@Override
|
||||
public void mix(final Player player, final NodeUsageEvent event) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < 67) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Cooking level of at least " + 57 + " in order to do this.");
|
||||
return;
|
||||
}
|
||||
super.mix(player, event);
|
||||
player.getSkills().addExperience(Skills.COOKING, 204, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getBase() {
|
||||
return CHOPPED_TUNA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return TUNA_AND_CORN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { COOKED_CORN };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMixMessage(NodeUsageEvent event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
package content.global.skill.cooking.recipe.topping.impl;
|
||||
|
||||
import content.global.skill.cooking.recipe.topping.ToppingRecipe;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the uncooked egg recipe. This recipe consists of adding an
|
||||
* uncooked egg into a bowl.
|
||||
* @author 'Vexia
|
||||
* @date 22/12/2013
|
||||
*/
|
||||
public final class UncookedEgg extends ToppingRecipe {
|
||||
|
||||
/**
|
||||
* Represents the egg item.
|
||||
*/
|
||||
private static final Item EGG = new Item(1944);
|
||||
|
||||
/**
|
||||
* Represents the uncooked egg product.
|
||||
*/
|
||||
private static final Item UNCOOKED_EGG = new Item(7076);
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getExperience() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getProduct() {
|
||||
return UNCOOKED_EGG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getIngredients() {
|
||||
return new Item[] { EGG };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingular() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item[] getParts() {
|
||||
return new Item[] {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import core.game.world.update.flag.context.Graphics
|
|||
import core.tools.RandomFunction
|
||||
import core.ServerConstants
|
||||
import core.api.*
|
||||
import core.tools.SystemLogger
|
||||
import core.game.node.entity.combat.InteractionType
|
||||
import core.game.system.command.Privilege
|
||||
import core.game.world.GameWorld
|
||||
import core.game.world.map.path.Pathfinder
|
||||
|
|
@ -28,10 +28,21 @@ class RevenantController : TickListener, Commands {
|
|||
private var expectedRevAmount: Int = ServerConstants.REVENANT_POPULATION
|
||||
private var groupPatrolQueue = ArrayList<RevenantNPC>()
|
||||
|
||||
// Movement tracking for stuck detection
|
||||
private val movementStartTick = HashMap<RevenantNPC, Int>()
|
||||
private val lastKnownLocation = HashMap<RevenantNPC, Location>()
|
||||
private val failedAttempts = HashMap<RevenantNPC, Int>()
|
||||
// Stuck detector config
|
||||
private const val STUCK_CHECK_INTERVAL = 10 // ticks
|
||||
private const val MAX_FAILED_ATTEMPTS = 5
|
||||
|
||||
@JvmStatic fun registerRevenant(revenantNPC: RevenantNPC) {
|
||||
trackedRevenants.add(revenantNPC)
|
||||
taskTimeRemaining[revenantNPC] = 0
|
||||
currentTask[revenantNPC] = RevenantTask.NONE
|
||||
movementStartTick[revenantNPC] = GameWorld.ticks
|
||||
lastKnownLocation[revenantNPC] = revenantNPC.location
|
||||
failedAttempts[revenantNPC] = 0
|
||||
Repository.RENDERABLE_NPCS.add(revenantNPC)
|
||||
}
|
||||
|
||||
|
|
@ -39,19 +50,188 @@ class RevenantController : TickListener, Commands {
|
|||
trackedRevenants.remove(revenantNPC)
|
||||
taskTimeRemaining.remove(revenantNPC)
|
||||
currentTask.remove(revenantNPC)
|
||||
movementStartTick.remove(revenantNPC)
|
||||
lastKnownLocation.remove(revenantNPC)
|
||||
failedAttempts.remove(revenantNPC)
|
||||
groupPatrolQueue.remove(revenantNPC)
|
||||
if (removeRender)
|
||||
Repository.RENDERABLE_NPCS.remove(revenantNPC)
|
||||
}
|
||||
|
||||
private fun route(vararg coords: Pair<Int, Int>): Array<Location> =
|
||||
Array(coords.size) { Location.create(coords[it].first, coords[it].second) }
|
||||
|
||||
// All routes that revs attempt to path through
|
||||
val routes = listOf(
|
||||
arrayOf(Location.create(3070, 3651), Location.create(3083, 3640), Location.create(3106, 3645), Location.create(3133, 3647), Location.create(3149, 3642), Location.create(3160, 3654), Location.create(3171, 3665, 0), Location.create(3189, 3663, 0), Location.create(3202, 3675, 0), Location.create(3217, 3660, 0), Location.create(3235, 3661, 0), Location.create(3235, 3661, 0), Location.create(3279, 3650, 0), Location.create(3269, 3636, 0), Location.create(3253, 3632, 0), Location.create(3236, 3638, 0), Location.create(3220, 3637, 0), Location.create(3203, 3634, 0), Location.create(3187, 3631, 0), Location.create(3166, 3633, 0), Location.create(3160, 3616, 0), Location.create(3148, 3604, 0), Location.create(3134, 3596, 0), Location.create(3118, 3590, 0), Location.create(3104, 3597, 0)),
|
||||
arrayOf(Location.create(3077, 3565, 0), Location.create(3093, 3559, 0), Location.create(3110, 3566, 0), Location.create(3127, 3574, 0), Location.create(3146, 3571, 0), Location.create(3164, 3575, 0), Location.create(3183, 3573, 0), Location.create(3197, 3587, 0), Location.create(3215, 3584, 0), Location.create(3233, 3576, 0), Location.create(3251, 3573, 0), Location.create(3269, 3577, 0), Location.create(3287, 3569, 0), Location.create(3305, 3568, 0), Location.create(3321, 3576, 0), Location.create(3338, 3584, 0), Location.create(3352, 3573, 0), Location.create(3354, 3554, 0), Location.create(3342, 3541, 0), Location.create(3324, 3536, 0), Location.create(3306, 3543, 0), Location.create(3290, 3544, 0), Location.create(3272, 3545, 0), Location.create(3255, 3546, 0), Location.create(3239, 3539, 0), Location.create(3222, 3543, 0), Location.create(3206, 3548, 0), Location.create(3189, 3549, 0), Location.create(3173, 3552, 0), Location.create(3157, 3549, 0), Location.create(3140, 3548, 0), Location.create(3122, 3548, 0), Location.create(3110, 3555, 0)),
|
||||
arrayOf(Location.create(3318, 3691, 0), Location.create(3307, 3700, 0), Location.create(3290, 3696, 0), Location.create(3277, 3706, 0), Location.create(3260, 3706, 0), Location.create(3250, 3707, 0), Location.create(3245, 3723, 0), Location.create(3254, 3735, 0), Location.create(3251, 3754, 0), Location.create(3243, 3768, 0), Location.create(3253, 3780, 0), Location.create(3238, 3783, 0), Location.create(3224, 3793, 0), Location.create(3206, 3786, 0), Location.create(3192, 3780, 0), Location.create(3170, 3787, 0), Location.create(3156, 3800, 0), Location.create(3148, 3814, 0), Location.create(3148, 3814, 0), Location.create(3127, 3840, 0), Location.create(3124, 3856, 0), Location.create(3124, 3872, 0), Location.create(3116, 3892, 0)),
|
||||
arrayOf(Location.create(2949, 3890, 0), Location.create(2965, 3899, 0), Location.create(2984, 3900, 0), Location.create(2998, 3895, 0), Location.create(3016, 3898, 0), Location.create(3032, 3893, 0), Location.create(3048, 3897, 0), Location.create(3068, 3894, 0), Location.create(3084, 3898, 0), Location.create(3101, 3895, 0), Location.create(3118, 3897, 0), Location.create(3136, 3893, 0), Location.create(3154, 3900, 0), Location.create(3172, 3895, 0), Location.create(3189, 3892, 0), Location.create(3206, 3897, 0), Location.create(3222, 3890, 0), Location.create(3240, 3897, 0), Location.create(3259, 3892, 0), Location.create(3278, 3895, 0), Location.create(3296, 3892, 0), Location.create(3313, 3899, 0), Location.create(3331, 3888, 0), Location.create(3345, 3880, 0)),
|
||||
arrayOf(Location.create(3308, 3941, 0), Location.create(3301, 3925, 0), Location.create(3287, 3915, 0), Location.create(3276, 3922, 0), Location.create(3266, 3938, 0), Location.create(3267, 3952, 0), Location.create(3250, 3949, 0), Location.create(3235, 3944, 0), Location.create(3219, 3944, 0), Location.create(3206, 3938, 0), Location.create(3194, 3929, 0), Location.create(3182, 3921, 0), Location.create(3174, 3936, 0), Location.create(3180, 3952, 0), Location.create(3167, 3960, 0), Location.create(3155, 3959, 0), Location.create(3141, 3953, 0), Location.create(3126, 3954, 0), Location.create(3110, 3961, 0), Location.create(3093, 3962, 0), Location.create(3078, 3953, 0), Location.create(3066, 3942, 0), Location.create(3059, 3929, 0), Location.create(3049, 3916, 0), Location.create(3033, 3924, 0), Location.create(3020, 3921, 0), Location.create(3010, 3913, 0), Location.create(2993, 3906, 0), Location.create(2977, 3911, 0), Location.create(2970, 3928, 0))
|
||||
route(
|
||||
3070 to 3651, 3083 to 3640, 3106 to 3645, 3133 to 3647, 3149 to 3642,
|
||||
3160 to 3654, 3171 to 3665, 3189 to 3663, 3202 to 3675, 3217 to 3660,
|
||||
3235 to 3661, 3235 to 3661, 3279 to 3650, 3269 to 3636, 3253 to 3632,
|
||||
3236 to 3638, 3220 to 3637, 3203 to 3634, 3187 to 3631, 3166 to 3633,
|
||||
3160 to 3616, 3148 to 3604, 3134 to 3596, 3118 to 3590, 3104 to 3597,
|
||||
),
|
||||
route(
|
||||
3077 to 3565, 3093 to 3559, 3110 to 3566, 3127 to 3574, 3146 to 3571,
|
||||
3164 to 3575, 3183 to 3573, 3197 to 3587, 3215 to 3584, 3233 to 3576,
|
||||
3251 to 3573, 3269 to 3577, 3287 to 3569, 3305 to 3568, 3321 to 3576,
|
||||
3338 to 3584, 3352 to 3573, 3354 to 3554, 3342 to 3541, 3324 to 3536,
|
||||
3306 to 3543, 3290 to 3544, 3272 to 3545, 3255 to 3546, 3239 to 3539,
|
||||
3222 to 3543, 3206 to 3548, 3189 to 3549, 3173 to 3552, 3157 to 3549,
|
||||
3140 to 3548, 3122 to 3548, 3110 to 3555,
|
||||
),
|
||||
route(
|
||||
3318 to 3691, 3307 to 3700, 3290 to 3696, 3277 to 3706, 3260 to 3706,
|
||||
3250 to 3707, 3245 to 3723, 3254 to 3735, 3251 to 3754, 3243 to 3768,
|
||||
3253 to 3780, 3238 to 3783, 3224 to 3793, 3206 to 3786, 3192 to 3780,
|
||||
3170 to 3787, 3156 to 3800, 3148 to 3814, 3148 to 3814, 3127 to 3840,
|
||||
3124 to 3856, 3124 to 3872, 3116 to 3892,
|
||||
),
|
||||
route(
|
||||
2949 to 3890, 2965 to 3899, 2984 to 3900, 2998 to 3895, 3016 to 3898,
|
||||
3032 to 3893, 3048 to 3897, 3068 to 3894, 3084 to 3898, 3101 to 3895,
|
||||
3118 to 3897, 3136 to 3893, 3154 to 3900, 3172 to 3895, 3189 to 3892,
|
||||
3206 to 3897, 3222 to 3890, 3240 to 3897, 3259 to 3892, 3278 to 3895,
|
||||
3296 to 3892, 3313 to 3899, 3331 to 3888, 3345 to 3880,
|
||||
),
|
||||
route(
|
||||
3308 to 3941, 3301 to 3925, 3287 to 3915, 3276 to 3922, 3266 to 3938,
|
||||
3267 to 3952, 3250 to 3949, 3235 to 3944, 3219 to 3944, 3206 to 3938,
|
||||
3194 to 3929, 3182 to 3921, 3174 to 3936, 3180 to 3952, 3167 to 3960,
|
||||
3155 to 3959, 3141 to 3953, 3126 to 3954, 3110 to 3961, 3093 to 3962,
|
||||
3078 to 3953, 3066 to 3942, 3059 to 3929, 3049 to 3916, 3033 to 3924,
|
||||
3020 to 3921, 3010 to 3913, 2993 to 3906, 2977 to 3911, 2970 to 3928,
|
||||
),
|
||||
route(
|
||||
3308 to 3941, 3301 to 3925, 3297 to 3914, 3286 to 3910, 3259 to 3912,
|
||||
3267 to 3952, 3251 to 3921, 3236 to 3918, 3222 to 3922, 3209 to 3920,
|
||||
3190 to 3933, 3177 to 3939, 3175 to 3951, 3167 to 3960, 3155 to 3959,
|
||||
3135 to 3951, 3134 to 3921, 3126 to 3914, 3108 to 3907, 3087 to 3910,
|
||||
3077 to 3925, 3076 to 3937, 3066 to 3942, 3059 to 3929, 3049 to 3916,
|
||||
3033 to 3924, 3020 to 3921, 3010 to 3913, 2993 to 3906, 2977 to 3911,
|
||||
2970 to 3928,
|
||||
),
|
||||
)
|
||||
|
||||
val spawnLocations = listOf(Location.create(3075, 3553, 0), Location.create(3077, 3563, 0), Location.create(3077, 3578, 0), Location.create(3093, 3581, 0), Location.create(3103, 3570, 0), Location.create(3101, 3564, 0), Location.create(3030, 3596, 0), Location.create(3015, 3598, 0), Location.create(3000, 3593, 0), Location.create(2986, 3588, 0), Location.create(2969, 3701, 0), Location.create(2982, 3689, 0), Location.create(2967, 3689, 0), Location.create(2953, 3711, 0), Location.create(2966, 3759, 0), Location.create(2989, 3759, 0), Location.create(2986, 3741, 0), Location.create(2961, 3763, 0), Location.create(2969, 3808, 0), Location.create(3004, 3816, 0))
|
||||
// Routes that Dark Beasts are too fat for
|
||||
private val largeNpcIncompatibleRoutes = setOf(4)
|
||||
|
||||
val spawnLocations = listOf(
|
||||
3075 to 3553, 3077 to 3563, 3077 to 3578, 3093 to 3581, 3103 to 3570,
|
||||
3101 to 3564, 3030 to 3596, 3015 to 3598, 3000 to 3593, 2986 to 3588,
|
||||
2969 to 3701, 2982 to 3689, 2967 to 3689, 2953 to 3713, 2966 to 3759,
|
||||
2989 to 3759, 2986 to 3741, 2961 to 3763, 2969 to 3808, 3004 to 3816,
|
||||
).map { (x, y) -> Location.create(x, y) }
|
||||
|
||||
/**
|
||||
* Revenant stuck detector
|
||||
* Makes sure Revenants are either moving, intentionally waiting to act, or are in legitimate combat
|
||||
* If they aren't, they're passed to the stuck handler
|
||||
*/
|
||||
private fun checkIfStuck(revenantNPC: RevenantNPC): Boolean {
|
||||
val lastTick = movementStartTick[revenantNPC] ?: 0
|
||||
val lastLoc = lastKnownLocation[revenantNPC] ?: revenantNPC.location
|
||||
|
||||
// Period between checks - configure above
|
||||
if (lastTick == 0 || (GameWorld.ticks - lastTick) < STUCK_CHECK_INTERVAL) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if positioned exactly at a patrol route start location (likely intentionally inactive)
|
||||
val routeStartLocations = routes.map { it[0] }
|
||||
val isAtRouteStart = routeStartLocations.any { it.equals(revenantNPC.location) }
|
||||
|
||||
// Check if in legitimate combat
|
||||
val combatPulse = revenantNPC.properties.combatPulse
|
||||
val victim = combatPulse.getVictim()
|
||||
val isInLegitimateCombat = if (victim != null) {
|
||||
val interactionType = combatPulse.canInteract()
|
||||
interactionType == InteractionType.STILL_INTERACT // The merits of MOVE_INTERACT regarding establishing a legitimate combat state are covered by the distanceMoved check a few lines from now
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
if (isAtRouteStart || isInLegitimateCombat) { //If the Revenant has a good reason to not be moving, skip the movement check
|
||||
movementStartTick[revenantNPC] = GameWorld.ticks
|
||||
lastKnownLocation[revenantNPC] = revenantNPC.location
|
||||
failedAttempts[revenantNPC] = 0
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the revenant has moved
|
||||
val distanceMoved = revenantNPC.location.getDistance(lastLoc)
|
||||
val isStuck = distanceMoved <= 2
|
||||
|
||||
// Reset the timer to check if they are stuck, since we are checking now
|
||||
movementStartTick[revenantNPC] = GameWorld.ticks
|
||||
|
||||
// Clear the Revenant's demerits towards being timed out if it is not stuck
|
||||
if (!isStuck) {
|
||||
lastKnownLocation[revenantNPC] = revenantNPC.location
|
||||
failedAttempts[revenantNPC] = 0
|
||||
}
|
||||
|
||||
return isStuck
|
||||
}
|
||||
|
||||
/**
|
||||
* Revenant stuck handler
|
||||
* Tries to help the Revenant escape after giving it a demerit
|
||||
* If the Revenant gets too many demerits, it will be timed out instead
|
||||
* NOTE: times out Revenants in unloaded regions as they have no land to path to and thus cannot move
|
||||
*/
|
||||
private fun handleStuckRevenant(revenantNPC: RevenantNPC) {
|
||||
val attempts = failedAttempts[revenantNPC] ?: 0
|
||||
failedAttempts[revenantNPC] = attempts + 1
|
||||
|
||||
if (attempts + 1 > MAX_FAILED_ATTEMPTS) {
|
||||
poofClear(revenantNPC)
|
||||
revenantNPC.setAttribute("done", true)
|
||||
return
|
||||
}
|
||||
|
||||
// The stuck Revenant will attempt to unstick itself
|
||||
val escapeLocation = getNextLocation(revenantNPC)
|
||||
revenantNPC.pulseManager.run(object : MovementPulse(revenantNPC, escapeLocation, Pathfinder.SMART) {
|
||||
override fun pulse(): Boolean {
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a random location to try to move to that is within the Wilderness
|
||||
*/
|
||||
fun getNextLocation(revenantNPC: RevenantNPC): Location {
|
||||
val rawNextX = RandomFunction.random(-revenantNPC.walkRadius, revenantNPC.walkRadius)
|
||||
val nextX = maxOf(rawNextX, 2951)
|
||||
val rawNextY = RandomFunction.random(-revenantNPC.walkRadius, revenantNPC.walkRadius)
|
||||
val nextY = maxOf(rawNextY, 3523)
|
||||
return revenantNPC.location.transform(nextX, nextY, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines how far Revenants can deviate from their path
|
||||
*/
|
||||
private fun getPathVariance(revenantNPC: RevenantNPC, isGroup: Boolean): Int {
|
||||
return when {
|
||||
isGroup -> 4
|
||||
revenantNPC.size() >= 3 -> 2 // Dark Beasts are fat, so keep them close to their safe routes
|
||||
else -> 10
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a random route for patrols
|
||||
* Will not assign Dark Beasts to routes they are too fat for
|
||||
*/
|
||||
private fun getSuitableRoute(revenantNPC: RevenantNPC): Array<Location> {
|
||||
val availableRoutes = if (revenantNPC.size() >= 3) {
|
||||
routes.filterIndexed { index, _ -> index !in largeNpcIncompatibleRoutes }
|
||||
} else {
|
||||
routes
|
||||
}
|
||||
return availableRoutes.random()
|
||||
}
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
|
|
@ -113,7 +293,13 @@ class RevenantController : TickListener, Commands {
|
|||
private val MAX_ROAM_TICKS: Int = 250
|
||||
|
||||
override fun execute(revenantNPC: RevenantNPC) {
|
||||
if (!canMove(revenantNPC)) return
|
||||
|
||||
if (checkIfStuck(revenantNPC)) {
|
||||
handleStuckRevenant(revenantNPC)
|
||||
return
|
||||
}
|
||||
|
||||
if (!canMoveBasic(revenantNPC)) return
|
||||
|
||||
val nextLoc = getNextLocation(revenantNPC)
|
||||
revenantNPC.pulseManager.run(object : MovementPulse(revenantNPC, nextLoc, Pathfinder.SMART) {
|
||||
|
|
@ -123,22 +309,15 @@ class RevenantController : TickListener, Commands {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun assign(revenantNPC: RevenantNPC) {
|
||||
taskTimeRemaining[revenantNPC] = RandomFunction.random(MAX_ROAM_TICKS)
|
||||
}
|
||||
|
||||
fun canMove(revenantNPC: RevenantNPC) : Boolean {
|
||||
return !revenantNPC.walkingQueue.isMoving
|
||||
private fun canMoveBasic(revenantNPC: RevenantNPC): Boolean {
|
||||
return !revenantNPC.walkingQueue.isMoving
|
||||
&& !revenantNPC.pulseManager.hasPulseRunning()
|
||||
&& !revenantNPC.properties.combatPulse.isAttacking
|
||||
&& !revenantNPC.properties.combatPulse.isInCombat
|
||||
}
|
||||
|
||||
fun getNextLocation(revenantNPC: RevenantNPC) : Location {
|
||||
val nextX = RandomFunction.random(-revenantNPC.walkRadius, revenantNPC.walkRadius)
|
||||
val nextY = RandomFunction.random(-revenantNPC.walkRadius, revenantNPC.walkRadius)
|
||||
return revenantNPC.location.transform(nextX, nextY, 0)
|
||||
override fun assign(revenantNPC: RevenantNPC) {
|
||||
taskTimeRemaining[revenantNPC] = RandomFunction.random(MAX_ROAM_TICKS)
|
||||
}
|
||||
},
|
||||
PATROLLING_ROUTE {
|
||||
|
|
@ -148,7 +327,7 @@ class RevenantController : TickListener, Commands {
|
|||
if (canGroup(revenantNPC)) {
|
||||
addToPatrolGroup(revenantNPC)
|
||||
} else {
|
||||
revenantNPC.setAttribute("route", routes.random())
|
||||
revenantNPC.setAttribute("route", getSuitableRoute(revenantNPC))
|
||||
revenantNPC.setAttribute("routeidx", -1)
|
||||
}
|
||||
}
|
||||
|
|
@ -158,7 +337,9 @@ class RevenantController : TickListener, Commands {
|
|||
groupPatrolQueue.add(revenantNPC)
|
||||
|
||||
if (groupPatrolQueue.size == 3) {
|
||||
val groupRoute = routes.random()
|
||||
// Gets a route suitable for the largest NPC in the group
|
||||
val largestNPC = groupPatrolQueue.maxByOrNull { it.size() } ?: revenantNPC
|
||||
val groupRoute = getSuitableRoute(largestNPC)
|
||||
for (rev in groupPatrolQueue) {
|
||||
rev.setAttribute("route", groupRoute)
|
||||
rev.setAttribute("routeidx", -1)
|
||||
|
|
@ -175,7 +356,12 @@ class RevenantController : TickListener, Commands {
|
|||
val route = revenantNPC.getAttribute<Array<Location>>("route", null)
|
||||
val routeIdx = revenantNPC.getAttribute("routeidx", -1)
|
||||
|
||||
if (!canMove(revenantNPC)) return
|
||||
if (checkIfStuck(revenantNPC)) {
|
||||
handleStuckRevenant(revenantNPC)
|
||||
return
|
||||
}
|
||||
|
||||
if (!canMoveAdvanced(revenantNPC)) return
|
||||
|
||||
if (isGroup && route == null) { //if this is a grouped rev and we are waiting on more revs still
|
||||
taskTimeRemaining[revenantNPC] = 50 //just to make sure it doesn't time out roaming...
|
||||
|
|
@ -198,7 +384,7 @@ class RevenantController : TickListener, Commands {
|
|||
revenantNPC.setAttribute("done", true)
|
||||
return
|
||||
}
|
||||
val pathVariance = if (isGroup) 4 else 10
|
||||
val pathVariance = getPathVariance(revenantNPC, isGroup)
|
||||
val nextLoc = route[routeIdx].transform(
|
||||
RandomFunction.random(-pathVariance, pathVariance),
|
||||
RandomFunction.random(-pathVariance, pathVariance),
|
||||
|
|
@ -212,9 +398,8 @@ class RevenantController : TickListener, Commands {
|
|||
revenantNPC.setAttribute("routeidx", routeIdx + 1)
|
||||
}
|
||||
}
|
||||
|
||||
fun canMove(revenantNPC: RevenantNPC) : Boolean {
|
||||
return !revenantNPC.walkingQueue.isMoving
|
||||
private fun canMoveAdvanced(revenantNPC: RevenantNPC) : Boolean {
|
||||
return !revenantNPC.walkingQueue.isMoving
|
||||
&& !revenantNPC.pulseManager.hasPulseRunning()
|
||||
&& !revenantNPC.properties.combatPulse.isAttacking
|
||||
&& !revenantNPC.properties.combatPulse.isInCombat
|
||||
|
|
|
|||
2
Server/src/main/core/cache/Cache.java
vendored
2
Server/src/main/core/cache/Cache.java
vendored
|
|
@ -145,7 +145,7 @@ public final class Cache {
|
|||
buffer.putInt(0);
|
||||
continue;
|
||||
}
|
||||
buffer.putInt(cacheFileManagers[index].getInformation().getInformationContainer().getCrc());
|
||||
buffer.putInt(cacheFileManagers[index].getInformation().informationContainer.getCrc());
|
||||
buffer.putInt(cacheFileManagers[index].getInformation().getRevision());
|
||||
}
|
||||
return buffer.array();
|
||||
|
|
|
|||
2
Server/src/main/core/cache/CacheFile.java
vendored
2
Server/src/main/core/cache/CacheFile.java
vendored
|
|
@ -66,7 +66,7 @@ public final class CacheFile {
|
|||
return null;
|
||||
}
|
||||
if (xteaKeys != null && (xteaKeys[0] != 0 || xteaKeys[1] != 0 || xteaKeys[2] != 0 || xteaKeys[3] != 0)) {
|
||||
packedData = XTEACryption.decrypt(xteaKeys, ByteBuffer.wrap(packedData), 5, packedData.length).array();
|
||||
packedData = XTEACryption.Companion.decrypt(xteaKeys, ByteBuffer.wrap(packedData), 5, packedData.length).array();
|
||||
}
|
||||
return ContainersInformation.unpackCacheContainer(packedData);
|
||||
}
|
||||
|
|
|
|||
72
Server/src/main/core/cache/StoreFile.java
vendored
72
Server/src/main/core/cache/StoreFile.java
vendored
|
|
@ -1,72 +0,0 @@
|
|||
package core.cache;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Represents a file used in the server store.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class StoreFile {
|
||||
|
||||
/**
|
||||
* If the data can change during server runtime.
|
||||
*/
|
||||
private boolean dynamic;
|
||||
|
||||
/**
|
||||
* The file data.
|
||||
*/
|
||||
private byte[] data;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code StoreFile} {@code Object}.
|
||||
*/
|
||||
public StoreFile() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the data on the buffer.
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
public void put(ByteBuffer buffer) {
|
||||
byte[] data = new byte[buffer.remaining()];
|
||||
buffer.get(data);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a byte buffer containing the file data.
|
||||
* @return The buffer.
|
||||
*/
|
||||
public ByteBuffer data() {
|
||||
return ByteBuffer.wrap(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data.
|
||||
* @param data The data.
|
||||
*/
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dynamic.
|
||||
* @return The dynamic.
|
||||
*/
|
||||
public boolean isDynamic() {
|
||||
return dynamic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dynamic.
|
||||
* @param dynamic The dynamic to set.
|
||||
*/
|
||||
public void setDynamic(boolean dynamic) {
|
||||
this.dynamic = dynamic;
|
||||
}
|
||||
|
||||
}
|
||||
271
Server/src/main/core/cache/crypto/ISAACCipher.java
vendored
271
Server/src/main/core/cache/crypto/ISAACCipher.java
vendored
|
|
@ -1,271 +0,0 @@
|
|||
package core.cache.crypto;
|
||||
|
||||
/**
|
||||
* <p> An implementation of an ISAAC cipher. See <a
|
||||
* href="http://en.wikipedia.org/wiki/ISAAC_(cipher)">
|
||||
* http://en.wikipedia.org/wiki/ISAAC_(cipher)</a> for more information. </p>
|
||||
* <p> This implementation is based on the one written by Bob Jenkins, which is
|
||||
* available at <a href="http://www.burtleburtle.net/bob/java/rand/Rand.java">
|
||||
* http://www.burtleburtle.net/bob/java/rand/Rand.java</a>. </p>
|
||||
* @author Graham Edgecombe
|
||||
*/
|
||||
public class ISAACCipher {
|
||||
|
||||
/**
|
||||
* The golden ratio.
|
||||
*/
|
||||
public static final int RATIO = 0x9e3779b9;
|
||||
|
||||
/**
|
||||
* The log of the size of the results and memory arrays.
|
||||
*/
|
||||
public static final int SIZE_LOG = 8;
|
||||
|
||||
/**
|
||||
* The size of the results and memory arrays.
|
||||
*/
|
||||
public static final int SIZE = 1 << SIZE_LOG;
|
||||
|
||||
/**
|
||||
* For pseudorandom lookup.
|
||||
*/
|
||||
public static final int MASK = (SIZE - 1) << 2;
|
||||
|
||||
/**
|
||||
* The count through the results.
|
||||
*/
|
||||
private int count = 0;
|
||||
|
||||
/**
|
||||
* The results.
|
||||
*/
|
||||
private int results[] = new int[SIZE];
|
||||
|
||||
/**
|
||||
* The internal memory state.
|
||||
*/
|
||||
private int memory[] = new int[SIZE];
|
||||
|
||||
/**
|
||||
* The accumulator.
|
||||
*/
|
||||
private int a;
|
||||
|
||||
/**
|
||||
* The last result.
|
||||
*/
|
||||
private int b;
|
||||
|
||||
/**
|
||||
* The counter.
|
||||
*/
|
||||
private int c;
|
||||
|
||||
/**
|
||||
* Creates the ISAAC cipher.
|
||||
* @param seed The seed.
|
||||
*/
|
||||
public ISAACCipher(int[] seed) {
|
||||
for (int i = 0; i < seed.length; i++) {
|
||||
results[i] = seed[i];
|
||||
}
|
||||
init(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next value.
|
||||
* @return The next value.
|
||||
*/
|
||||
public int getNextValue() {
|
||||
if (count-- == 0) {
|
||||
isaac();
|
||||
count = SIZE - 1;
|
||||
}
|
||||
return 0;//results[count];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates 256 results.
|
||||
*/
|
||||
public void isaac() {
|
||||
int i, j, x, y;
|
||||
b += ++c;
|
||||
for (i = 0, j = SIZE / 2; i < SIZE / 2;) {
|
||||
x = memory[i];
|
||||
a ^= a << 13;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a >>> 6;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a << 2;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a >>> 16;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
}
|
||||
for (j = 0; j < SIZE / 2;) {
|
||||
x = memory[i];
|
||||
a ^= a << 13;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a >>> 6;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a << 2;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a >>> 16;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the ISAAC.
|
||||
* @param flag Flag indicating if we should perform a second pass.
|
||||
*/
|
||||
public void init(boolean flag) {
|
||||
int i;
|
||||
int a, b, c, d, e, f, g, h;
|
||||
a = b = c = d = e = f = g = h = RATIO;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
}
|
||||
for (i = 0; i < SIZE; i += 8) {
|
||||
if (flag) {
|
||||
a += results[i];
|
||||
b += results[i + 1];
|
||||
c += results[i + 2];
|
||||
d += results[i + 3];
|
||||
e += results[i + 4];
|
||||
f += results[i + 5];
|
||||
g += results[i + 6];
|
||||
h += results[i + 7];
|
||||
}
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
memory[i] = a;
|
||||
memory[i + 1] = b;
|
||||
memory[i + 2] = c;
|
||||
memory[i + 3] = d;
|
||||
memory[i + 4] = e;
|
||||
memory[i + 5] = f;
|
||||
memory[i + 6] = g;
|
||||
memory[i + 7] = h;
|
||||
}
|
||||
if (flag) {
|
||||
for (i = 0; i < SIZE; i += 8) {
|
||||
a += memory[i];
|
||||
b += memory[i + 1];
|
||||
c += memory[i + 2];
|
||||
d += memory[i + 3];
|
||||
e += memory[i + 4];
|
||||
f += memory[i + 5];
|
||||
g += memory[i + 6];
|
||||
h += memory[i + 7];
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
memory[i] = a;
|
||||
memory[i + 1] = b;
|
||||
memory[i + 2] = c;
|
||||
memory[i + 3] = d;
|
||||
memory[i + 4] = e;
|
||||
memory[i + 5] = f;
|
||||
memory[i + 6] = g;
|
||||
memory[i + 7] = h;
|
||||
}
|
||||
}
|
||||
isaac();
|
||||
count = SIZE;
|
||||
}
|
||||
|
||||
}
|
||||
213
Server/src/main/core/cache/crypto/ISAACCipher.kt
vendored
Normal file
213
Server/src/main/core/cache/crypto/ISAACCipher.kt
vendored
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
package core.cache.crypto
|
||||
|
||||
/**
|
||||
* An implementation of an ISAAC cipher.
|
||||
* See [http://en.wikipedia.org/wiki/ISAAC_(cipher)](http://en.wikipedia.org/wiki/ISAAC_(cipher)) for more information.
|
||||
* Based on the one written by Bob Jenkins, which is available at
|
||||
* [http://www.burtleburtle.net/bob/java/rand/Rand.java](http://www.burtleburtle.net/bob/java/rand/Rand.java).
|
||||
*/
|
||||
class ISAACCipher(seed: IntArray) {
|
||||
companion object {
|
||||
/** Golden ratio in 32 bit unsigned int. */
|
||||
const val RATIO = -0x61c88647
|
||||
/** The base 2 log of the size of the results and memory arrays. */
|
||||
const val SIZE_LOG = 8
|
||||
/** The size of the results and memory arrays. */
|
||||
const val SIZE = 1 shl SIZE_LOG
|
||||
/** For pseudorandom lookup. */
|
||||
const val MASK = SIZE - 1 shl 2
|
||||
}
|
||||
/** The count through the results. */
|
||||
private var count = 0
|
||||
/** The results. */
|
||||
private val results = IntArray(SIZE)
|
||||
/** The internal memory state. */
|
||||
private val memory = IntArray(SIZE)
|
||||
/** The accumulator. */
|
||||
private var a = 0
|
||||
/** The last result. */
|
||||
private var b = 0
|
||||
/** The counter. */
|
||||
private var c = 0
|
||||
|
||||
/**
|
||||
* Creates the ISAAC cipher.
|
||||
* @param seed The seed.
|
||||
*/
|
||||
init {
|
||||
for (i in seed.indices) {
|
||||
results[i] = seed[i]
|
||||
}
|
||||
init(true)
|
||||
}
|
||||
|
||||
val nextValue: Int
|
||||
/**
|
||||
* Gets the next value.
|
||||
* @return The next value.
|
||||
*/
|
||||
get() {
|
||||
if (count-- == 0) {
|
||||
isaac()
|
||||
count = SIZE - 1
|
||||
}
|
||||
return 0 //results[count];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates 256 results.
|
||||
*/
|
||||
fun isaac() {
|
||||
var i: Int
|
||||
var j: Int
|
||||
var x: Int
|
||||
var y: Int
|
||||
b += ++c
|
||||
i = 0
|
||||
j = SIZE / 2
|
||||
while (i < SIZE / 2) {
|
||||
x = memory[i]
|
||||
a = a xor (a shl 13)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a ushr 6)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a shl 2)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a ushr 16)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
}
|
||||
j = 0
|
||||
while (j < SIZE / 2) {
|
||||
x = memory[i]
|
||||
a = a xor (a shl 13)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a ushr 6)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a shl 2)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a ushr 16)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the ISAAC.
|
||||
* @param flag Flag indicating if we should perform a second pass.
|
||||
*/
|
||||
fun init(flag: Boolean) {
|
||||
var a = RATIO
|
||||
var b = a; var c = b; var d = c; var e = d; var f = e; var g = f; var h = g
|
||||
var i = 0
|
||||
while (i < 4) {
|
||||
a = a xor (b shl 11); d += a; b += c
|
||||
b = b xor (c ushr 2); e += b; c += d
|
||||
c = c xor (d shl 8); f += c; d += e
|
||||
d = d xor (e ushr 16); g += d; e += f
|
||||
e = e xor (f shl 10); h += e; f += g
|
||||
f = f xor (g ushr 4); a += f; g += h
|
||||
g = g xor (h shl 8); b += g; h += a
|
||||
h = h xor (a ushr 9); c += h; a += b
|
||||
++i
|
||||
}
|
||||
i = 0
|
||||
while (i < SIZE) {
|
||||
if (flag) {
|
||||
a += results[i]
|
||||
b += results[i + 1]
|
||||
c += results[i + 2]
|
||||
d += results[i + 3]
|
||||
e += results[i + 4]
|
||||
f += results[i + 5]
|
||||
g += results[i + 6]
|
||||
h += results[i + 7]
|
||||
}
|
||||
a = a xor (b shl 11); d += a; b += c
|
||||
b = b xor (c ushr 2); e += b; c += d
|
||||
c = c xor (d shl 8); f += c; d += e
|
||||
d = d xor (e ushr 16); g += d; e += f
|
||||
e = e xor (f shl 10); h += e; f += g
|
||||
f = f xor (g ushr 4); a += f; g += h
|
||||
g = g xor (h shl 8); b += g; h += a
|
||||
h = h xor (a ushr 9); c += h; a += b
|
||||
memory[i] = a
|
||||
memory[i + 1] = b
|
||||
memory[i + 2] = c
|
||||
memory[i + 3] = d
|
||||
memory[i + 4] = e
|
||||
memory[i + 5] = f
|
||||
memory[i + 6] = g
|
||||
memory[i + 7] = h
|
||||
i += 8
|
||||
}
|
||||
if (flag) {
|
||||
i = 0
|
||||
while (i < SIZE) {
|
||||
a += memory[i]
|
||||
b += memory[i + 1]
|
||||
c += memory[i + 2]
|
||||
d += memory[i + 3]
|
||||
e += memory[i + 4]
|
||||
f += memory[i + 5]
|
||||
g += memory[i + 6]
|
||||
h += memory[i + 7]
|
||||
a = a xor (b shl 11); d += a; b += c
|
||||
b = b xor (c ushr 2); e += b; c += d
|
||||
c = c xor (d shl 8); f += c; d += e
|
||||
d = d xor (e ushr 16); g += d; e += f
|
||||
e = e xor (f shl 10); h += e; f += g
|
||||
f = f xor (g ushr 4); a += f; g += h
|
||||
g = g xor (h shl 8); b += g; h += a
|
||||
h = h xor (a ushr 9); c += h; a += b
|
||||
memory[i] = a
|
||||
memory[i + 1] = b
|
||||
memory[i + 2] = c
|
||||
memory[i + 3] = d
|
||||
memory[i + 4] = e
|
||||
memory[i + 5] = f
|
||||
memory[i + 6] = g
|
||||
memory[i + 7] = h
|
||||
i += 8
|
||||
}
|
||||
}
|
||||
isaac()
|
||||
count = SIZE
|
||||
}
|
||||
}
|
||||
45
Server/src/main/core/cache/crypto/ISAACPair.java
vendored
45
Server/src/main/core/cache/crypto/ISAACPair.java
vendored
|
|
@ -1,45 +0,0 @@
|
|||
package core.cache.crypto;
|
||||
|
||||
/**
|
||||
* Represents a ISAAC key pair, for both input and output.
|
||||
* @author `Discardedx2
|
||||
*/
|
||||
public final class ISAACPair {
|
||||
|
||||
/**
|
||||
* The input cipher.
|
||||
*/
|
||||
private ISAACCipher input;
|
||||
|
||||
/**
|
||||
* The output cipher.
|
||||
*/
|
||||
private ISAACCipher output;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ISAACPair} {@code Object}.
|
||||
* @param input The input cipher.
|
||||
* @param output The output cipher.
|
||||
*/
|
||||
public ISAACPair(ISAACCipher input, ISAACCipher output) {
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input cipher.
|
||||
* @return The input cipher.
|
||||
*/
|
||||
public ISAACCipher getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the output cipher.
|
||||
* @return The output cipher.
|
||||
*/
|
||||
public ISAACCipher getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
9
Server/src/main/core/cache/crypto/ISAACPair.kt
vendored
Normal file
9
Server/src/main/core/cache/crypto/ISAACPair.kt
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package core.cache.crypto
|
||||
|
||||
/**
|
||||
* Represents a ISAAC key pair, for both input and output.
|
||||
*/
|
||||
class ISAACPair(
|
||||
val input: ISAACCipher,
|
||||
val output: ISAACCipher
|
||||
)
|
||||
124
Server/src/main/core/cache/crypto/XTEACryption.java
vendored
124
Server/src/main/core/cache/crypto/XTEACryption.java
vendored
|
|
@ -1,124 +0,0 @@
|
|||
package core.cache.crypto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Holds XTEA cryption methods.
|
||||
* @author ?
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class XTEACryption {
|
||||
|
||||
/**
|
||||
* The delta value
|
||||
*/
|
||||
private static final int DELTA = -1640531527;
|
||||
|
||||
/**
|
||||
* The sum.
|
||||
*/
|
||||
private static final int SUM = -957401312;
|
||||
|
||||
/**
|
||||
* The amount of "cryption cycles".
|
||||
*/
|
||||
private static final int NUM_ROUNDS = 32;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code XTEACryption}.
|
||||
*/
|
||||
private XTEACryption() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the contents of the buffer.
|
||||
* @param keys The cryption keys.
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
public static ByteBuffer decrypt(int[] keys, ByteBuffer buffer) {
|
||||
return decrypt(keys, buffer, buffer.position(), buffer.limit());
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the buffer data.
|
||||
* @param keys The keys.
|
||||
* @param buffer The buffer to decrypt.
|
||||
* @param offset The offset of the data to decrypt.
|
||||
* @param length The length.
|
||||
* @return The decrypted data.
|
||||
*/
|
||||
public static ByteBuffer decrypt(int[] keys, ByteBuffer buffer, int offset, int length) {
|
||||
int numBlocks = (length - offset) / 8;
|
||||
int[] block = new int[2];
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
int index = i * 8 + offset;
|
||||
block[0] = buffer.getInt(index);
|
||||
block[1] = buffer.getInt(index + 4);
|
||||
decipher(keys, block);
|
||||
buffer.putInt(index, block[0]);
|
||||
buffer.putInt(index + 4, block[1]);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deciphers the values.
|
||||
* @param keys The cryption key.
|
||||
* @param block The values to decipher.
|
||||
*/
|
||||
private static void decipher(int[] keys, int[] block) {
|
||||
long sum = SUM;
|
||||
for (int i = 0; i < NUM_ROUNDS; i++) {
|
||||
block[1] -= (keys[(int) ((sum & 0x1933) >>> 11)] + sum ^ block[0] + (block[0] << 4 ^ block[0] >>> 5));
|
||||
sum -= DELTA;
|
||||
block[0] -= ((block[1] << 4 ^ block[1] >>> 5) + block[1] ^ keys[(int) (sum & 0x3)] + sum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the contents of the byte buffer.
|
||||
* @param keys The cryption keys.
|
||||
* @param buffer The buffer to encrypt.
|
||||
*/
|
||||
public static void encrypt(int[] keys, ByteBuffer buffer) {
|
||||
encrypt(keys, buffer, buffer.position(), buffer.limit());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the buffer data.
|
||||
* @param keys The keys.
|
||||
* @param buffer The buffer to encrypt.
|
||||
* @param offset The offset of the data to encrypt.
|
||||
* @param length The length.
|
||||
* @return The encrypted data.
|
||||
*/
|
||||
public static void encrypt(int[] keys, ByteBuffer buffer, int offset, int length) {
|
||||
int numBlocks = (length - offset) / 8;
|
||||
int[] block = new int[2];
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
int index = i * 8 + offset;
|
||||
block[0] = buffer.getInt(index);
|
||||
block[1] = buffer.getInt(index + 4);
|
||||
encipher(keys, block);
|
||||
buffer.putInt(index, block[0]);
|
||||
buffer.putInt(index + 4, block[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enciphers the values of the block.
|
||||
* @param keys The cryption keys.
|
||||
* @param block The block to encipher.
|
||||
*/
|
||||
private static void encipher(int[] keys, int[] block) {
|
||||
long sum = 0;
|
||||
for (int i = 0; i < NUM_ROUNDS; i++) {
|
||||
block[0] += ((block[1] << 4 ^ block[1] >>> 5) + block[1] ^ keys[(int) (sum & 0x3)] + sum);
|
||||
sum += DELTA;
|
||||
block[1] += (keys[(int) ((sum & 0x1933) >>> 11)] + sum ^ block[0] + (block[0] << 4 ^ block[0] >>> 5));
|
||||
}
|
||||
}
|
||||
}
|
||||
97
Server/src/main/core/cache/crypto/XTEACryption.kt
vendored
Normal file
97
Server/src/main/core/cache/crypto/XTEACryption.kt
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
package core.cache.crypto
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
/** Holds XTEA(eXtended Tiny Encryption Algorithm) encryption/decryption methods. Usually used for RS Map decryption. */
|
||||
class XTEACryption {
|
||||
companion object {
|
||||
// Purely Static Class
|
||||
// XTEA consts https://scispace.com/pdf/xtea-cryptography-implementation-in-android-chatting-app-3pg6ownewx.pdf
|
||||
/** Fibonacci hashing. Math.pow(2,32) * Math.sqrt(5)-1)/2 => 32 bits(int) multiply by reciprocal of golden ratio. */
|
||||
private const val DELTA = -1640531527 // Formula cast to unsigned int.
|
||||
/** DELTA << 5. Essentially multiply DELTA by NUM_ROUNDS or number of rounds. */
|
||||
private const val SUM = -957401312 // 0xC6EF3720
|
||||
/** The amount of "cryption cycles". */
|
||||
private const val NUM_ROUNDS = 32
|
||||
/** Constant to manipulate the key index in decipher/encrypt. This was a magic number randomly selected by RS. */
|
||||
private const val KEY_SCRAMBLE = 0x1933
|
||||
|
||||
/**
|
||||
* Decrypts the buffer data.
|
||||
* @param keys The keys.
|
||||
* @param buffer The buffer to decrypt.
|
||||
* @param offset The offset of the data to decrypt.
|
||||
* @param length The length.
|
||||
* @return The decrypted data.
|
||||
*/
|
||||
fun decrypt(keys: IntArray, buffer: ByteBuffer, offset: Int, length: Int): ByteBuffer {
|
||||
val numBlocks = (length - offset) / 8
|
||||
val block = IntArray(2)
|
||||
for (i in 0 until numBlocks) {
|
||||
val index = i * 8 + offset
|
||||
block[0] = buffer.getInt(index)
|
||||
block[1] = buffer.getInt(index + 4)
|
||||
decipher(keys, block)
|
||||
buffer.putInt(index, block[0])
|
||||
buffer.putInt(index + 4, block[1])
|
||||
}
|
||||
return buffer
|
||||
}
|
||||
|
||||
/**
|
||||
* Deciphers the values of the block using the Tiny Encryption Algorithm (TEA).
|
||||
* This algorithm relies on a Feistel network, using bitwise operations and
|
||||
* modular subtraction to remove confusion(block[0] line) and diffusion(block[1] line).
|
||||
*
|
||||
* @param keys 128-bit key (4x32-bit int).
|
||||
* @param block 64-bit data block (2x32-bit int) to be decrypted.
|
||||
*/
|
||||
private fun decipher(keys: IntArray, block: IntArray) {
|
||||
var sum =
|
||||
SUM.toLong() // Running decreasing sum to ensure different round constants - should become 0 at the end.
|
||||
for (i in 0 until NUM_ROUNDS) {
|
||||
block[1] -= (keys[(sum and KEY_SCRAMBLE.toLong() ushr 11).toInt()] + sum xor (block[0] + (block[0] shl 4 xor (block[0] ushr 5))).toLong()).toInt()
|
||||
sum -= DELTA.toLong()
|
||||
block[0] -= (((block[1] shl 4 xor (block[1] ushr 5)) + block[1]).toLong() xor keys[(sum and 0x3L).toInt()] + sum).toInt()
|
||||
}
|
||||
}
|
||||
/** === Encryption functions below are not used unless you are modifying the cache. === */
|
||||
/**
|
||||
* Encrypts the buffer data.
|
||||
* @param keys The keys.
|
||||
* @param buffer The buffer to encrypt.
|
||||
* @param offset The offset of the data to encrypt.
|
||||
* @param length The length.
|
||||
* @return The encrypted data.
|
||||
*/
|
||||
fun encrypt(keys: IntArray, buffer: ByteBuffer, offset: Int, length: Int) {
|
||||
val numBlocks = (length - offset) / 8
|
||||
val block = IntArray(2)
|
||||
for (i in 0 until numBlocks) {
|
||||
val index = i * 8 + offset
|
||||
block[0] = buffer.getInt(index)
|
||||
block[1] = buffer.getInt(index + 4)
|
||||
encipher(keys, block)
|
||||
buffer.putInt(index, block[0])
|
||||
buffer.putInt(index + 4, block[1])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enciphers the values of the block using the Tiny Encryption Algorithm (TEA).
|
||||
* This algorithm relies on a Feistel network, using bitwise operations and
|
||||
* modular addition to provide confusion(block[0] line) and diffusion(block[1] line).
|
||||
*
|
||||
* @param keys 128-bit key (4x32-bit int).
|
||||
* @param block 64-bit data block (2x32-bit int) to be encrypted.
|
||||
*/
|
||||
private fun encipher(keys: IntArray, block: IntArray) {
|
||||
var sum: Long = 0 // Running sum to ensure different round constants - should match SUM at the end.
|
||||
for (i in 0 until NUM_ROUNDS) {
|
||||
block[0] += (((block[1] shl 4 xor (block[1] ushr 5)) + block[1]).toLong() xor keys[(sum and 0x3L).toInt()] + sum).toInt()
|
||||
sum += DELTA.toLong()
|
||||
block[1] += (keys[(sum and KEY_SCRAMBLE.toLong() ushr 11).toInt()] + sum xor (block[0] + (block[0] shl 4 xor (block[0] ushr 5))).toLong()).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Server/src/main/core/cache/misc/Container.java
vendored
109
Server/src/main/core/cache/misc/Container.java
vendored
|
|
@ -1,109 +0,0 @@
|
|||
package core.cache.misc;
|
||||
|
||||
/**
|
||||
* A container.
|
||||
* @author Dragonkk
|
||||
*/
|
||||
public class Container {
|
||||
|
||||
/**
|
||||
* The version.
|
||||
*/
|
||||
private int version;
|
||||
|
||||
/**
|
||||
* The CRC.
|
||||
*/
|
||||
private int crc;
|
||||
|
||||
/**
|
||||
* The name hash.
|
||||
*/
|
||||
private int nameHash;
|
||||
|
||||
/**
|
||||
* If updated.
|
||||
*/
|
||||
private boolean updated;
|
||||
|
||||
/**
|
||||
* Construct a new container.
|
||||
*/
|
||||
public Container() {
|
||||
nameHash = -1;
|
||||
version = -1;
|
||||
crc = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the version.
|
||||
* @param version
|
||||
*/
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the version.
|
||||
*/
|
||||
public void updateVersion() {
|
||||
version++;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version.
|
||||
* @return The version.
|
||||
*/
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next version.
|
||||
* @return The next version.
|
||||
*/
|
||||
public int getNextVersion() {
|
||||
return updated ? version : version + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CRC.
|
||||
* @param crc The cRC.
|
||||
*/
|
||||
public void setCrc(int crc) {
|
||||
this.crc = crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CRC.
|
||||
* @return The CRC.
|
||||
*/
|
||||
public int getCrc() {
|
||||
return crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name hash.
|
||||
* @param nameHash The name hash.
|
||||
*/
|
||||
public void setNameHash(int nameHash) {
|
||||
this.nameHash = nameHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name hash.
|
||||
* @return The name hash.
|
||||
*/
|
||||
public int getNameHash() {
|
||||
return nameHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* If is updated.
|
||||
* @return If is updated.
|
||||
*/
|
||||
public boolean isUpdated() {
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
7
Server/src/main/core/cache/misc/Container.kt
vendored
Normal file
7
Server/src/main/core/cache/misc/Container.kt
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
package core.cache.misc
|
||||
|
||||
data class Container(
|
||||
var version: Int = -1,
|
||||
var crc: Int = -1,
|
||||
var nameHash: Int = -1
|
||||
)
|
||||
|
|
@ -1,228 +0,0 @@
|
|||
package core.cache.misc;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import core.cache.bzip2.BZip2Decompressor;
|
||||
import core.cache.gzip.GZipDecompressor;
|
||||
|
||||
/**
|
||||
* A class holding the containers information.
|
||||
* @author Dragonkk
|
||||
*/
|
||||
public final class ContainersInformation {
|
||||
|
||||
/**
|
||||
* The information container.
|
||||
*/
|
||||
private Container informationContainer;
|
||||
|
||||
/**
|
||||
* The protocol.
|
||||
*/
|
||||
private int protocol;
|
||||
|
||||
/**
|
||||
* The revision.
|
||||
*/
|
||||
private int revision;
|
||||
|
||||
/**
|
||||
* The container indexes.
|
||||
*/
|
||||
private int[] containersIndexes;
|
||||
|
||||
/**
|
||||
* The containers.
|
||||
*/
|
||||
private FilesContainer[] containers;
|
||||
|
||||
/**
|
||||
* If files have to be named.
|
||||
*/
|
||||
private boolean filesNamed;
|
||||
|
||||
/**
|
||||
* If it has to be whirpool.
|
||||
*/
|
||||
private boolean whirpool;
|
||||
|
||||
/**
|
||||
* The data.
|
||||
*/
|
||||
private final byte[] data;
|
||||
|
||||
/**
|
||||
* Construct a new containers information.
|
||||
* @param informationContainerPackedData The information container data
|
||||
* packed.
|
||||
*/
|
||||
public ContainersInformation(byte[] informationContainerPackedData) {
|
||||
this.data = Arrays.copyOf(informationContainerPackedData, informationContainerPackedData.length);
|
||||
informationContainer = new Container();
|
||||
informationContainer.setVersion((informationContainerPackedData[informationContainerPackedData.length - 2] << 8 & 0xff00) + (informationContainerPackedData[-1 + informationContainerPackedData.length] & 0xff));
|
||||
CRC32 crc32 = new CRC32();
|
||||
crc32.update(informationContainerPackedData);
|
||||
informationContainer.setCrc((int) crc32.getValue());
|
||||
decodeContainersInformation(unpackCacheContainer(informationContainerPackedData));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpacks a container.
|
||||
* @param packedData The packed container data.
|
||||
* @return The unpacked data.
|
||||
*/
|
||||
public static final byte[] unpackCacheContainer(byte[] packedData) {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(packedData);
|
||||
int compression = buffer.get() & 0xFF;
|
||||
int containerSize = buffer.getInt();
|
||||
if (containerSize < 0 || containerSize > 5000000) {
|
||||
return null;
|
||||
// throw new RuntimeException();
|
||||
}
|
||||
if (compression == 0) {
|
||||
byte unpacked[] = new byte[containerSize];
|
||||
buffer.get(unpacked, 0, containerSize);
|
||||
return unpacked;
|
||||
}
|
||||
int decompressedSize = buffer.getInt();
|
||||
if (decompressedSize < 0 || decompressedSize > 20000000) {
|
||||
return null;
|
||||
// throw new RuntimeException();
|
||||
}
|
||||
byte decompressedData[] = new byte[decompressedSize];
|
||||
if (compression == 1) {
|
||||
BZip2Decompressor.decompress(decompressedData, packedData, containerSize, 9);
|
||||
} else {
|
||||
GZipDecompressor.decompress(buffer, decompressedData);
|
||||
}
|
||||
return decompressedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the container indexes.
|
||||
* @return The container indexes.
|
||||
*/
|
||||
public int[] getContainersIndexes() {
|
||||
return containersIndexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the containers.
|
||||
* @return The containers.
|
||||
*/
|
||||
public FilesContainer[] getContainers() {
|
||||
return containers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the information container.
|
||||
* @return The information container.
|
||||
*/
|
||||
public Container getInformationContainer() {
|
||||
return informationContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the revision.
|
||||
* @return The revision.
|
||||
*/
|
||||
public int getRevision() {
|
||||
return revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the containers information.
|
||||
* @param data The data.
|
||||
*/
|
||||
public void decodeContainersInformation(byte[] data) {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(data);
|
||||
protocol = buffer.get() & 0xFF;
|
||||
if (protocol != 5 && protocol != 6) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
revision = protocol < 6 ? 0 : buffer.getInt();
|
||||
int nameHash = buffer.get() & 0xFF;
|
||||
filesNamed = (0x1 & nameHash) != 0;
|
||||
whirpool = (0x2 & nameHash) != 0;
|
||||
containersIndexes = new int[buffer.getShort() & 0xFFFF];
|
||||
int lastIndex = -1;
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containersIndexes[index] = (buffer.getShort() & 0xFFFF) + (index == 0 ? 0 : containersIndexes[index - 1]);
|
||||
if (containersIndexes[index] > lastIndex) {
|
||||
lastIndex = containersIndexes[index];
|
||||
}
|
||||
}
|
||||
containers = new FilesContainer[lastIndex + 1];
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containers[containersIndexes[index]] = new FilesContainer();
|
||||
}
|
||||
if (filesNamed) {
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containers[containersIndexes[index]].setNameHash(buffer.getInt());
|
||||
}
|
||||
}
|
||||
byte[][] filesHashes = null;
|
||||
if (whirpool) {
|
||||
filesHashes = new byte[containers.length][];
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
filesHashes[containersIndexes[index]] = new byte[64];
|
||||
buffer.get(filesHashes[containersIndexes[index]], 0, 64);
|
||||
}
|
||||
}
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containers[containersIndexes[index]].setCrc(buffer.getInt());
|
||||
}
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containers[containersIndexes[index]].setVersion(buffer.getInt());
|
||||
}
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containers[containersIndexes[index]].setFilesIndexes(new int[buffer.getShort() & 0xFFFF]);
|
||||
}
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
int lastFileIndex = -1;
|
||||
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
|
||||
containers[containersIndexes[index]].getFilesIndexes()[fileIndex] = (buffer.getShort() & 0xFFFF) + (fileIndex == 0 ? 0 : containers[containersIndexes[index]].getFilesIndexes()[fileIndex - 1]);
|
||||
if (containers[containersIndexes[index]].getFilesIndexes()[fileIndex] > lastFileIndex) {
|
||||
lastFileIndex = containers[containersIndexes[index]].getFilesIndexes()[fileIndex];
|
||||
}
|
||||
}
|
||||
containers[containersIndexes[index]].setFiles(new Container[lastFileIndex + 1]);
|
||||
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
|
||||
containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]] = new Container();
|
||||
}
|
||||
}
|
||||
if (whirpool) {
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
|
||||
containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]].setVersion(filesHashes[containersIndexes[index]][containers[containersIndexes[index]].getFilesIndexes()[fileIndex]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filesNamed) {
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
|
||||
containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]].setNameHash(buffer.getInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If is whirpool.
|
||||
* @return If is whirpool {@code true}.
|
||||
*/
|
||||
public boolean isWhirpool() {
|
||||
return whirpool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data.
|
||||
* @return The data.
|
||||
*/
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
145
Server/src/main/core/cache/misc/ContainersInformation.kt
vendored
Normal file
145
Server/src/main/core/cache/misc/ContainersInformation.kt
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
package core.cache.misc
|
||||
|
||||
import core.cache.bzip2.BZip2Decompressor
|
||||
import core.cache.gzip.GZipDecompressor
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.*
|
||||
import java.util.zip.CRC32
|
||||
|
||||
class ContainersInformation(informationContainerPackedData: ByteArray) {
|
||||
@JvmField
|
||||
val informationContainer: Container
|
||||
private var protocol = 0
|
||||
var revision = 0
|
||||
var containersIndexes: IntArray = intArrayOf()
|
||||
var containers: Array<FilesContainer?> = arrayOf()
|
||||
private var filesNamed = false // If files has to be named
|
||||
private var whirpool = false // Flag for whirpool
|
||||
val data: ByteArray
|
||||
|
||||
init {
|
||||
data = Arrays.copyOf(informationContainerPackedData, informationContainerPackedData.size)
|
||||
informationContainer = Container()
|
||||
informationContainer.version =
|
||||
(informationContainerPackedData[informationContainerPackedData.size - 2].toInt() shl 8 and 0xff00) + (informationContainerPackedData[-1 + informationContainerPackedData.size].toInt() and 0xff)
|
||||
val crc32 = CRC32()
|
||||
crc32.update(informationContainerPackedData)
|
||||
informationContainer.crc = crc32.value.toInt()
|
||||
decodeContainersInformation(unpackCacheContainer(informationContainerPackedData))
|
||||
}
|
||||
|
||||
fun decodeContainersInformation(data: ByteArray?) {
|
||||
val buffer = ByteBuffer.wrap(data)
|
||||
protocol = buffer.get().toInt() and 0xFF
|
||||
if (protocol != 5 && protocol != 6) {
|
||||
throw RuntimeException()
|
||||
}
|
||||
revision = if (protocol < 6) 0 else buffer.getInt()
|
||||
val nameHash = buffer.get().toInt() and 0xFF
|
||||
filesNamed = 0x1 and nameHash != 0
|
||||
whirpool = 0x2 and nameHash != 0
|
||||
containersIndexes = IntArray(buffer.getShort().toInt() and 0xFFFF)
|
||||
var lastIndex = -1
|
||||
for (index in containersIndexes.indices) {
|
||||
val containerIndex =
|
||||
(buffer.getShort().toInt() and 0xFFFF) + if (index == 0) 0 else containersIndexes[index - 1]
|
||||
containersIndexes[index] = containerIndex
|
||||
if (containerIndex > lastIndex) {
|
||||
lastIndex = containerIndex
|
||||
}
|
||||
}
|
||||
containers = arrayOfNulls(lastIndex + 1)
|
||||
for (containerIdx in containersIndexes) {
|
||||
containers[containerIdx] = FilesContainer()
|
||||
}
|
||||
if (filesNamed) {
|
||||
for (containerIdx in containersIndexes) {
|
||||
containers[containerIdx]!!.nameHash = buffer.getInt()
|
||||
}
|
||||
}
|
||||
var filesHashes: Array<ByteArray?>? = null
|
||||
if (whirpool) {
|
||||
filesHashes = arrayOfNulls(containers.size)
|
||||
for (containerIdx in containersIndexes) {
|
||||
filesHashes[containerIdx] = ByteArray(64)
|
||||
buffer[filesHashes[containerIdx], 0, 64]
|
||||
}
|
||||
}
|
||||
for (containerIdx in containersIndexes) {
|
||||
containers[containerIdx]!!.crc = buffer.getInt()
|
||||
}
|
||||
for (containerIdx in containersIndexes) {
|
||||
containers[containerIdx]!!.version = buffer.getInt()
|
||||
}
|
||||
for (containerIdx in containersIndexes) {
|
||||
containers[containerIdx]!!.filesIndexes = IntArray(buffer.getShort().toInt() and 0xFFFF)
|
||||
}
|
||||
for (containerIdx in containersIndexes) {
|
||||
val container = containers[containerIdx]
|
||||
val filesIndexes = container!!.filesIndexes
|
||||
var lastFileIndex = -1
|
||||
for (fileIndex in filesIndexes!!.indices) {
|
||||
val fileIdx =
|
||||
(buffer.getShort().toInt() and 0xFFFF) + if (fileIndex == 0) 0 else filesIndexes[fileIndex - 1]
|
||||
filesIndexes[fileIndex] = fileIdx
|
||||
if (fileIdx > lastFileIndex) {
|
||||
lastFileIndex = fileIdx
|
||||
}
|
||||
}
|
||||
val files = arrayOfNulls<Container>(lastFileIndex + 1)
|
||||
container.files = files
|
||||
for (fileIdx in filesIndexes) {
|
||||
files[fileIdx] = Container()
|
||||
}
|
||||
}
|
||||
if (whirpool) {
|
||||
for (containerIdx in containersIndexes) {
|
||||
val container = containers[containerIdx]
|
||||
val containerHashes = filesHashes!![containerIdx]
|
||||
val files = container!!.files
|
||||
for (fileIdx in container.filesIndexes!!) {
|
||||
files!![fileIdx]!!.version = containerHashes!![fileIdx].toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filesNamed) {
|
||||
for (containerIdx in containersIndexes) {
|
||||
val container = containers[containerIdx]
|
||||
val files = container!!.files
|
||||
for (fileIdx in container.filesIndexes!!) {
|
||||
files!![fileIdx]!!.nameHash = buffer.getInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun unpackCacheContainer(packedData: ByteArray?): ByteArray? {
|
||||
val buffer = ByteBuffer.wrap(packedData)
|
||||
val compression = buffer.get().toInt() and 0xFF
|
||||
val containerSize = buffer.getInt()
|
||||
if (containerSize < 0 || containerSize > 5000000) {
|
||||
return null
|
||||
// throw new RuntimeException();
|
||||
}
|
||||
if (compression == 0) {
|
||||
val unpacked = ByteArray(containerSize)
|
||||
buffer[unpacked, 0, containerSize]
|
||||
return unpacked
|
||||
}
|
||||
val decompressedSize = buffer.getInt()
|
||||
if (decompressedSize < 0 || decompressedSize > 20000000) {
|
||||
return null
|
||||
// throw new RuntimeException();
|
||||
}
|
||||
val decompressedData = ByteArray(decompressedSize)
|
||||
if (compression == 1) {
|
||||
BZip2Decompressor.decompress(decompressedData, packedData, containerSize, 9)
|
||||
} else {
|
||||
GZipDecompressor.decompress(buffer, decompressedData)
|
||||
}
|
||||
return decompressedData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
package core.cache.misc;
|
||||
|
||||
/**
|
||||
* A class holding the file containers.
|
||||
* @author Dragonkk
|
||||
*/
|
||||
public final class FilesContainer extends Container {
|
||||
|
||||
/**
|
||||
* The file indexes.
|
||||
*/
|
||||
private int[] filesIndexes;
|
||||
|
||||
/**
|
||||
* The files.
|
||||
*/
|
||||
private Container[] files;
|
||||
|
||||
/**
|
||||
* Construct a new files container.
|
||||
*/
|
||||
public FilesContainer() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the files.
|
||||
* @param containers The files.
|
||||
*/
|
||||
public void setFiles(Container[] containers) {
|
||||
this.files = containers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the files.
|
||||
* @return The files.
|
||||
*/
|
||||
public Container[] getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file indexes.
|
||||
* @param containersIndexes The file indexes.
|
||||
*/
|
||||
public void setFilesIndexes(int[] containersIndexes) {
|
||||
this.filesIndexes = containersIndexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file indexes.
|
||||
* @return The file indexes.
|
||||
*/
|
||||
public int[] getFilesIndexes() {
|
||||
return filesIndexes;
|
||||
}
|
||||
}
|
||||
9
Server/src/main/core/cache/misc/FilesContainer.kt
vendored
Normal file
9
Server/src/main/core/cache/misc/FilesContainer.kt
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package core.cache.misc
|
||||
|
||||
data class FilesContainer(
|
||||
var version: Int = -1,
|
||||
var crc: Int = -1,
|
||||
var nameHash: Int = -1,
|
||||
var filesIndexes: IntArray? = null,
|
||||
var files: Array<Container?>? = null
|
||||
)
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
package core.cache.misc.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles the reading of data from a byte buffer.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class BufferInputStream extends InputStream {
|
||||
|
||||
/**
|
||||
* The buffer to write on.
|
||||
*/
|
||||
private final ByteBuffer buffer;
|
||||
|
||||
/**
|
||||
* The buffer input stream.
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
public BufferInputStream(ByteBuffer buffer) throws IOException {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return buffer.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer.
|
||||
* @return The buffer.
|
||||
*/
|
||||
public ByteBuffer getBuffer() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
package core.cache.misc.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles the writing of data on a byte buffer.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class BufferOutputStream extends OutputStream {
|
||||
|
||||
/**
|
||||
* The buffer to write on.
|
||||
*/
|
||||
private final ByteBuffer buffer;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BufferOutputStream} {@code Object}.
|
||||
* @param buffer The buffer to write on.
|
||||
* @throws IOException When an I/O exception occurs.
|
||||
* @throws SecurityException If a security manager exists and its
|
||||
* checkPermission method denies enabling subclassing.
|
||||
*/
|
||||
public BufferOutputStream(ByteBuffer buffer) throws IOException, SecurityException {
|
||||
super();
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
buffer.put((byte) b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer.
|
||||
* @return The buffer.
|
||||
*/
|
||||
public ByteBuffer getBuffer() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
package core.cache.misc.buffer;
|
||||
|
||||
import java.io.ObjectInputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Holds utility methods for reading/writing a byte buffer.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ByteBufferUtils {
|
||||
|
||||
/**
|
||||
* Gets a string from the byte buffer.
|
||||
* @param buffer The byte buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
public static String getString(ByteBuffer buffer) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
byte b;
|
||||
while ((b = buffer.get()) != 0) {
|
||||
sb.append((char) b);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a string on the byte buffer.
|
||||
* @param s The string to put.
|
||||
* @param buffer The byte buffer.
|
||||
*/
|
||||
public static void putString(String s, ByteBuffer buffer) {
|
||||
buffer.put(s.getBytes(StandardCharsets.UTF_8)).put((byte) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string from the byte buffer.
|
||||
* @param s The string.
|
||||
* @param buffer The byte buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
public static ByteBuffer putGJ2String(String s, ByteBuffer buffer) {
|
||||
byte[] packed = new byte[256];
|
||||
int length = packGJString2(0, packed, s);
|
||||
return buffer.put((byte) 0).put(packed, 0, length).put((byte) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the XTEA encryption.
|
||||
* @param keys The keys.
|
||||
* @param start The start index.
|
||||
* @param end The end index.
|
||||
* @param buffer The byte buffer.
|
||||
*/
|
||||
public static void decodeXTEA(int[] keys, int start, int end, ByteBuffer buffer) {
|
||||
int l = buffer.position();
|
||||
buffer.position(start);
|
||||
int length = (end - start) / 8;
|
||||
for (int i = 0; i < length; i++) {
|
||||
int firstInt = buffer.getInt();
|
||||
int secondInt = buffer.getInt();
|
||||
int sum = 0xc6ef3720;
|
||||
int delta = 0x9e3779b9;
|
||||
for (int j = 32; j-- > 0;) {
|
||||
secondInt -= keys[(sum & 0x1c84) >>> 11] + sum ^ (firstInt >>> 5 ^ firstInt << 4) + firstInt;
|
||||
sum -= delta;
|
||||
firstInt -= (secondInt >>> 5 ^ secondInt << 4) + secondInt ^ keys[sum & 3] + sum;
|
||||
}
|
||||
buffer.position(buffer.position() - 8);
|
||||
buffer.putInt(firstInt);
|
||||
buffer.putInt(secondInt);
|
||||
}
|
||||
buffer.position(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a String to an Integer?
|
||||
* @param position The position.
|
||||
* @param buffer The buffer used.
|
||||
* @param string The String to convert.
|
||||
* @return The Integer.
|
||||
*/
|
||||
public static int packGJString2(int position, byte[] buffer, String string) {
|
||||
int length = string.length();
|
||||
int offset = position;
|
||||
for (int i = 0; length > i; i++) {
|
||||
int character = string.charAt(i);
|
||||
if (character > 127) {
|
||||
if (character > 2047) {
|
||||
buffer[offset++] = (byte) ((character | 919275) >> 12);
|
||||
buffer[offset++] = (byte) (128 | ((character >> 6) & 63));
|
||||
buffer[offset++] = (byte) (128 | (character & 63));
|
||||
} else {
|
||||
buffer[offset++] = (byte) ((character | 12309) >> 6);
|
||||
buffer[offset++] = (byte) (128 | (character & 63));
|
||||
}
|
||||
} else
|
||||
buffer[offset++] = (byte) character;
|
||||
}
|
||||
return offset - position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a tri-byte from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
public static int getMedium(ByteBuffer buffer) {
|
||||
return ((buffer.get() & 0xFF) << 16) + ((buffer.get() & 0xFF) << 8) + (buffer.get() & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a smart from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
public static int getSmart(ByteBuffer buffer) {
|
||||
int peek = buffer.get() & 0xFF;
|
||||
if (peek <= Byte.MAX_VALUE) {
|
||||
return peek;
|
||||
}
|
||||
return ((peek << 8) | (buffer.get() & 0xFF)) - 32768;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a smart from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
public static int getBigSmart(ByteBuffer buffer) {
|
||||
int value = 0;
|
||||
int current = getSmart(buffer);
|
||||
while (current == 32767) {
|
||||
current = getSmart(buffer);
|
||||
value += 32767;
|
||||
}
|
||||
value += current;
|
||||
return value;
|
||||
}
|
||||
|
||||
/* *//**
|
||||
* Writes an object on the buffer.
|
||||
* @param buffer The buffer to write on.
|
||||
* @param o The object.
|
||||
*/
|
||||
/*
|
||||
* public static void putObject(ByteBuffer buffer, Object o) { ByteBuffer b;
|
||||
* try (ObjectOutputStream out = new ObjectOutputStream(new
|
||||
* BufferOutputStream(b = ByteBuffer.allocate(99999)))) {
|
||||
* out.writeObject(o); b.flip(); } catch (Throwable e) {
|
||||
* e.printStackTrace(); b = (ByteBuffer) ByteBuffer.allocate(0).flip(); }
|
||||
* buffer.putInt(b.remaining()); if (b.remaining() > 0) { buffer.put(b); } }
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets an object from the byte buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The object.
|
||||
*/
|
||||
public static Object getObject(ByteBuffer buffer) {
|
||||
int length = buffer.getInt();
|
||||
if (length > 0) {
|
||||
byte[] bytes = new byte[length];
|
||||
buffer.get(bytes);
|
||||
try (ObjectInputStream str = new ObjectInputStream(new BufferInputStream(ByteBuffer.wrap(bytes)))) {
|
||||
return (Object) str.readObject();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ByteBufferUtils} {@code Object}.
|
||||
*/
|
||||
private ByteBufferUtils() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
}
|
||||
142
Server/src/main/core/cache/misc/buffer/ByteBufferUtils.kt
vendored
Normal file
142
Server/src/main/core/cache/misc/buffer/ByteBufferUtils.kt
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
package core.cache.misc.buffer
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
object ByteBufferUtils {
|
||||
/**
|
||||
* Gets a string from the byte buffer.
|
||||
* @param buffer The byte buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getString(buffer: ByteBuffer): String {
|
||||
val sb = StringBuilder()
|
||||
var b: Byte
|
||||
while (buffer.get().also { b = it }.toInt() != 0) {
|
||||
sb.append(Char(b.toUShort()))
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a string on the byte buffer.
|
||||
* @param s The string to put.
|
||||
* @param buffer The byte buffer.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun putString(s: String, buffer: ByteBuffer) {
|
||||
buffer.put(s.toByteArray(StandardCharsets.UTF_8)).put(0.toByte())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string from the byte buffer.
|
||||
* @param s The string.
|
||||
* @param buffer The byte buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
fun putGJ2String(s: String, buffer: ByteBuffer): ByteBuffer {
|
||||
val packed = ByteArray(256)
|
||||
val length = packGJString2(0, packed, s)
|
||||
return buffer.put(0.toByte()).put(packed, 0, length).put(0.toByte())
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the XTEA encryption.
|
||||
* @param keys The keys.
|
||||
* @param start The start index.
|
||||
* @param end The end index.
|
||||
* @param buffer The byte buffer.
|
||||
*/
|
||||
fun decodeXTEA(keys: IntArray, start: Int, end: Int, buffer: ByteBuffer) {
|
||||
val l = buffer.position()
|
||||
buffer.position(start)
|
||||
val length = (end - start) / 8
|
||||
for (i in 0 until length) {
|
||||
var firstInt = buffer.getInt()
|
||||
var secondInt = buffer.getInt()
|
||||
var sum = -0x3910c8e0
|
||||
val delta = -0x61c88647
|
||||
var j = 32
|
||||
while (j-- > 0) {
|
||||
secondInt -= keys[sum and 0x1c84 ushr 11] + sum xor (firstInt ushr 5 xor (firstInt shl 4)) + firstInt
|
||||
sum -= delta
|
||||
firstInt -= (secondInt ushr 5 xor (secondInt shl 4)) + secondInt xor keys[sum and 3] + sum
|
||||
}
|
||||
buffer.position(buffer.position() - 8)
|
||||
buffer.putInt(firstInt)
|
||||
buffer.putInt(secondInt)
|
||||
}
|
||||
buffer.position(l)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a String to an Integer?
|
||||
* @param position The position.
|
||||
* @param buffer The buffer used.
|
||||
* @param string The String to convert.
|
||||
* @return The Integer.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun packGJString2(position: Int, buffer: ByteArray, string: String): Int {
|
||||
val length = string.length
|
||||
var offset = position
|
||||
var i = 0
|
||||
while (length > i) {
|
||||
val character = string[i].code
|
||||
if (character > 127) {
|
||||
if (character > 2047) {
|
||||
buffer[offset++] = (character or 919275 shr 12).toByte()
|
||||
buffer[offset++] = (128 or (character shr 6 and 63)).toByte()
|
||||
buffer[offset++] = (128 or (character and 63)).toByte()
|
||||
} else {
|
||||
buffer[offset++] = (character or 12309 shr 6).toByte()
|
||||
buffer[offset++] = (128 or (character and 63)).toByte()
|
||||
}
|
||||
} else buffer[offset++] = character.toByte()
|
||||
i++
|
||||
}
|
||||
return offset - position
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a tri-byte from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getMedium(buffer: ByteBuffer): Int {
|
||||
return (buffer.get().toInt() and 0xFF shl 16) + (buffer.get().toInt() and 0xFF shl 8) + (buffer.get()
|
||||
.toInt() and 0xFF)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a smart from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getSmart(buffer: ByteBuffer): Int {
|
||||
val peek = buffer.get().toInt() and 0xFF
|
||||
return if (peek <= Byte.MAX_VALUE) {
|
||||
peek
|
||||
} else (peek shl 8 or (buffer.get().toInt() and 0xFF)) - 32768
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a smart from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getBigSmart(buffer: ByteBuffer): Int {
|
||||
var value = 0
|
||||
var current = getSmart(buffer)
|
||||
while (current == 32767) {
|
||||
current = getSmart(buffer)
|
||||
value += 32767
|
||||
}
|
||||
value += current
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
|
@ -190,15 +190,16 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
|
|||
val dump = File("structs.txt")
|
||||
val writer = BufferedWriter(FileWriter(dump))
|
||||
val index = Cache.getIndexes()[2]
|
||||
val containers = index.information.containers[26].filesIndexes
|
||||
for(fID in containers)
|
||||
{
|
||||
val file = index.getFileData(26, fID)
|
||||
if(file != null){
|
||||
val def = Struct.parse(fID, file)
|
||||
if(def.dataStore.isEmpty()) continue //no data in struct.
|
||||
writer.write(def.toString())
|
||||
writer.newLine()
|
||||
val containers = index.information.containers[26]!!.filesIndexes
|
||||
if (containers != null) {
|
||||
for(fID in containers) {
|
||||
val file = index.getFileData(26, fID)
|
||||
if(file != null){
|
||||
val def = Struct.parse(fID, file)
|
||||
if(def.dataStore.isEmpty()) continue //no data in struct.
|
||||
writer.write(def.toString())
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
writer.flush()
|
||||
|
|
@ -214,15 +215,16 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
|
|||
|
||||
for(cID in containers)
|
||||
{
|
||||
val fileIndexes = index.information.containers[cID].filesIndexes
|
||||
for(fID in fileIndexes)
|
||||
{
|
||||
val file = index.getFileData(cID, fID)
|
||||
if(file != null){
|
||||
val def = DataMap.parse((cID shl 8) or fID, file)
|
||||
if(def.keyType == '?') continue //Empty definition - only a 0 present in the cachefile data.
|
||||
writer.write(def.toString())
|
||||
writer.newLine()
|
||||
val fileIndexes = index.information.containers[cID]!!.filesIndexes
|
||||
if (fileIndexes != null) {
|
||||
for(fID in fileIndexes) {
|
||||
val file = index.getFileData(cID, fID)
|
||||
if(file != null){
|
||||
val def = DataMap.parse((cID shl 8) or fID, file)
|
||||
if(def.keyType == '?') continue //Empty definition - only a 0 present in the cachefile data.
|
||||
writer.write(def.toString())
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue