Browse Source

global market, marvin stuff

Kajetan Johannes Hammerle 3 years ago
parent
commit
719014459a

+ 73 - 0
configs/inv_data/survival/4.96921431E8.snuvic

@@ -0,0 +1,73 @@
+chest="{Count:1b,id:"minecraft:air"}"
+eslot-0.0="{Count:1b,id:"minecraft:air"}"
+eslot-1.0="{Count:1b,id:"minecraft:air"}"
+eslot-10.0="{Count:1b,id:"minecraft:air"}"
+eslot-11.0="{Count:1b,id:"minecraft:air"}"
+eslot-12.0="{Count:1b,id:"minecraft:air"}"
+eslot-13.0="{Count:1b,id:"minecraft:air"}"
+eslot-14.0="{Count:1b,id:"minecraft:air"}"
+eslot-15.0="{Count:1b,id:"minecraft:air"}"
+eslot-16.0="{Count:1b,id:"minecraft:air"}"
+eslot-17.0="{Count:1b,id:"minecraft:air"}"
+eslot-18.0="{Count:1b,id:"minecraft:air"}"
+eslot-19.0="{Count:1b,id:"minecraft:air"}"
+eslot-2.0="{Count:1b,id:"minecraft:air"}"
+eslot-20.0="{Count:1b,id:"minecraft:air"}"
+eslot-21.0="{Count:1b,id:"minecraft:air"}"
+eslot-22.0="{Count:1b,id:"minecraft:air"}"
+eslot-23.0="{Count:1b,id:"minecraft:air"}"
+eslot-24.0="{Count:1b,id:"minecraft:air"}"
+eslot-25.0="{Count:1b,id:"minecraft:air"}"
+eslot-26.0="{Count:1b,id:"minecraft:air"}"
+eslot-3.0="{Count:1b,id:"minecraft:air"}"
+eslot-4.0="{Count:1b,id:"minecraft:air"}"
+eslot-5.0="{Count:1b,id:"minecraft:air"}"
+eslot-6.0="{Count:1b,id:"minecraft:air"}"
+eslot-7.0="{Count:1b,id:"minecraft:air"}"
+eslot-8.0="{Count:1b,id:"minecraft:air"}"
+eslot-9.0="{Count:1b,id:"minecraft:air"}"
+feet="{Count:1b,id:"minecraft:air"}"
+head="{Count:1b,id:"minecraft:air"}"
+health=15.0
+hunger=14.0
+legs="{Count:1b,id:"minecraft:air"}"
+lvl=8.0
+offhand="{Count:1b,id:"minecraft:air"}"
+saturation=0.0
+slot-0.0="{Count:64b,id:"minecraft:oak_door"}"
+slot-1.0="{Count:1b,id:"minecraft:air"}"
+slot-10.0="{Count:1b,id:"minecraft:air"}"
+slot-11.0="{Count:1b,id:"minecraft:air"}"
+slot-12.0="{Count:1b,id:"minecraft:air"}"
+slot-13.0="{Count:1b,id:"minecraft:air"}"
+slot-14.0="{Count:1b,id:"minecraft:air"}"
+slot-15.0="{Count:1b,id:"minecraft:air"}"
+slot-16.0="{Count:1b,id:"minecraft:air"}"
+slot-17.0="{Count:1b,id:"minecraft:air"}"
+slot-18.0="{Count:1b,id:"minecraft:air"}"
+slot-19.0="{Count:1b,id:"minecraft:air"}"
+slot-2.0="{Count:1b,id:"minecraft:air"}"
+slot-20.0="{Count:1b,id:"minecraft:air"}"
+slot-21.0="{Count:1b,id:"minecraft:air"}"
+slot-22.0="{Count:1b,id:"minecraft:air"}"
+slot-23.0="{Count:1b,id:"minecraft:air"}"
+slot-24.0="{Count:1b,id:"minecraft:air"}"
+slot-25.0="{Count:1b,id:"minecraft:air"}"
+slot-26.0="{Count:1b,id:"minecraft:air"}"
+slot-27.0="{Count:1b,id:"minecraft:air"}"
+slot-28.0="{Count:1b,id:"minecraft:air"}"
+slot-29.0="{Count:1b,id:"minecraft:air"}"
+slot-3.0="{Count:1b,id:"minecraft:air"}"
+slot-30.0="{Count:1b,id:"minecraft:air"}"
+slot-31.0="{Count:1b,id:"minecraft:air"}"
+slot-32.0="{Count:1b,id:"minecraft:air"}"
+slot-33.0="{Count:1b,id:"minecraft:air"}"
+slot-34.0="{Count:1b,id:"minecraft:air"}"
+slot-35.0="{Count:1b,id:"minecraft:air"}"
+slot-4.0="{Count:1b,id:"minecraft:air"}"
+slot-5.0="{Count:1b,id:"minecraft:air"}"
+slot-6.0="{Count:1b,id:"minecraft:air"}"
+slot-7.0="{Count:1b,id:"minecraft:air"}"
+slot-8.0="{Count:1b,id:"minecraft:air"}"
+slot-9.0="{Count:1b,id:"minecraft:air"}"
+xp=0.13043494522571564

+ 4 - 0
configs/market_prices.snuvic

@@ -0,0 +1,4 @@
+BEETROOT=64.0
+CARROT=99.0
+FLINT=3840.0
+WHEAT=1128.0

+ 3 - 0
configs/player_data/survival_data/1.086995138E9.snuvic

@@ -0,0 +1,3 @@
+backpos="world:-0.6292776648920858:67.0:5.0314908200899815:47.51354217529297:10.454723358154297"
+firstjoin=false
+rank="§3User"

+ 2 - 0
configs/player_data/survival_data/1.767533467E9.snuvic

@@ -0,0 +1,2 @@
+firstjoin=false
+rank="§4Owner"

+ 6 - 0
configs/player_data/survival_data/4.96921431E8.snuvic

@@ -0,0 +1,6 @@
+backpos="world_the_end:2.1249811289948886:64.0:0.2926819080436539:-178.2692108154297:25.838891983032227"
+firstjoin=false
+message.join="goes hard or goes home."
+message.leave="goes home now."
+pvp=false
+rank="§cAdmin"

+ 2 - 0
configs/server.snuvic

@@ -0,0 +1,2 @@
+mail_id=2.0
+serverspawn="world:110.8265858304995:81.0:-5.983481571867978:-179.377685546875:0.7645598649978638"

+ 211 - 0
market.txt

@@ -0,0 +1,211 @@
+stock = config.new("scripts/configs", "market_prices");
+config.load(stock);
+mainHand = read.slot("HAND");
+openMarkets = set.new();
+
+// Miner
+miner = inv.new("222222222", text.new("Miner"));
+inv.setItem(miner, 0, newItem(material.get("DIAMOND")));
+inv.setItem(miner, 1, newItem(material.get("IRON_INGOT")));
+inv.setItem(miner, 2, newItem(material.get("GOLD_INGOT")));
+inv.setItem(miner, 3, newItem(material.get("COPPER_INGOT")));
+inv.setItem(miner, 4, newItem(material.get("NETHERITE_INGOT")));
+inv.setItem(miner, 5, newItem(material.get("LAPIS_LAZULI")));
+inv.setItem(miner, 6, newItem(material.get("REDSTONE")));
+inv.setItem(miner, 7, newItem(material.get("FLINT")));
+set.add(openMarkets, inv.getId(miner));
+// Farmer
+farmer = inv.new("222222222", text.new("Farmer"));
+inv.setItem(farmer, 0, newItem(material.get("WHEAT")));
+inv.setItem(farmer, 1, newItem(material.get("CARROT")));
+inv.setItem(farmer, 2, newItem(material.get("POTATO")));
+inv.setItem(farmer, 3, newItem(material.get("BEETROOT")));
+inv.setItem(farmer, 4, newItem(material.get("MELON")));
+inv.setItem(farmer, 5, newItem(material.get("PUMPKIN")));
+set.add(openMarkets, inv.getId(farmer));
+
+event.load("entity_click");
+event.load("snuvi_click");
+
+background = material.get("BLACK_STAINED_GLASS_PANE");
+
+onStock = 0;
+buyAmount = 0;
+buySnuviAmount = 0;
+sellAmount = 0;
+sellSnuviAmount = 0;
+save = false;
+
+function save() {
+    if($save) {
+        return;
+    }
+    $save = true;
+    sgoto(100, "save");
+}
+
+function giveSnuvis(player, amount) {
+    msg(player, text.new(string.concat("§eYou got §6", string.number(amount), "§e Snuvis.")));
+    // actually remove the players snuvis
+}
+
+function removeSnuvis(player, amount) {
+    // msg(player, text.new("§cYou don't have enough snuvis."));
+    // return true if the player does not have enough snuvis
+    return false;
+}
+
+function calculatePrices(material) {
+    max = 34560;
+
+    $onStock = config.getDouble($stock, material, 0);
+    
+    $buyAmount = ($onStock + 1);
+    $buySnuviAmount = 2176;
+    $sellAmount = ($onStock + 2);
+    $sellSnuviAmount = 2048;
+    
+    if($buyAmount > $buySnuviAmount) {
+        $buyAmount /= $buySnuviAmount;
+        $buySnuviAmount = 1;
+    } else {
+        $buySnuviAmount /= $buyAmount;
+        $buyAmount = 1;
+    }
+    
+    if($sellAmount > $sellSnuviAmount) {
+        $sellAmount /= $sellSnuviAmount;
+        $sellSnuviAmount = 1;
+    } else {
+        $sellSnuviAmount /= $sellAmount;
+        $sellAmount = 1;
+    }
+    
+    $buyAmount = math.round($buyAmount);
+    $buySnuviAmount = math.round($buySnuviAmount);
+    $sellAmount = math.round($sellAmount);
+    $sellSnuviAmount = math.round($sellSnuviAmount);
+}
+
+function newItem(material) {
+    item = item.new(material);
+    lore = item.getLore(item);
+    if(lore == null) {
+        lore = list.new();
+    }
+    calculatePrices(material);
+    s = "";
+    if($buySnuviAmount > 1) {
+        s = "s";
+    }
+    list.add(lore, text.new(string.concat("§eBuy §6", string.number($buyAmount), "§e for §6", string.number($buySnuviAmount), "§e Snuvi", s)));
+    s = "";
+    if($sellSnuviAmount > 1) {
+        s = "s";
+    }
+    list.add(lore, text.new(string.concat("§eSell §6", string.number($sellAmount), "§e for §6", string.number($sellSnuviAmount), "§e Snuvi", s)));
+    list.add(lore, text.new(string.concat("§6", string.number($onStock), "§e on stock")));
+    item.setLore(item, lore);
+    return item;
+}
+
+function updateItem(inv, slot, material) {
+    calculatePrices(material);
+    inv.setItem(inv, slot, newItem(material));
+}   
+
+@loop
+wait();
+ignoreGoto(event);
+goto("loop");
+
+@save
+config.saveAsync(stock);
+print("save");
+save = false;
+goto("loop");
+
+@entity_click
+if(hand == mainHand) {
+    goto("loop");
+}
+text_name = entity.getName(entity);
+if(text_name == null) {
+    goto("loop");
+}
+name = string.text(text_name);
+
+if(string.startsWith(name, "Miner", 0)) {
+    inv.open(miner, player);
+} elseif(string.startsWith(name, "Farmer", 0)) {
+    inv.open(farmer, player);
+}
+
+goto("loop");
+
+@snuvi_click
+if(inv == null || !set.contains(openMarkets, inv.getId(inv))) {
+    goto("loop");
+}
+item = inv.getItem(inv, inv_slot);
+material = item.getType(item);
+if(material == background) {
+    goto("loop");
+}
+clicks = 1;
+ignoreGoto(click);
+goto("loop");
+
+// buying
+@SHIFT_LEFT
+clicks = 64;
+@LEFT
+lostSnuvis = 0;
+for(i = 0; i < clicks; i++) {
+    calculatePrices(material);
+    if(onStock < buyAmount || buyAmount <= 0) {
+        msg(player, text.new("§cThis item is out of stock."));
+        break;
+    }
+    // buy
+    if(removeSnuvis(player, buySnuviAmount)) {
+        break;
+    }
+    lostSnuvis += buySnuviAmount;
+    buyItem = item.new(material);
+    item.setAmount(buyItem, buyAmount);
+    player.giveItem(player, buyItem); // do this safely
+    config.set(stock, material, onStock - buyAmount);
+}
+if(lostSnuvis > 0) {
+    msg(player, text.new(string.concat("§eYou lost §6", string.number(lostSnuvis), "§e Snuvis.")));
+    updateItem(inv, inv_slot, material);
+    save();
+}
+goto("loop");
+
+// selling
+@SHIFT_RIGHT
+clicks = 64;
+@RIGHT
+gotSnuvis = 0;
+for(i = 0; i < clicks; i++) {
+    calculatePrices(material);
+    sellItem = item.new(material);
+    amount = player.getItemAmount(player, true, sellItem);
+    if(amount < sellAmount) {
+        msg(player, text.new("§cYou don't have enough of this item."));
+        break;
+    }
+    gotSnuvis += sellSnuviAmount;
+    item.setAmount(sellItem, sellAmount);
+    player.removeItem(player, sellItem);
+    config.set(stock, material, onStock + sellAmount);
+}
+if(gotSnuvis > 0) {
+    giveSnuvis(player, gotSnuvis);
+    updateItem(inv, inv_slot, material);
+    save();
+}
+goto("loop");
+

+ 11 - 14
startscript.txt

@@ -1,33 +1,30 @@
 modTimer(-3000);
 debug.setConsolePrint(true);
 clearScriptVars();
-//limit.clear();
 
 setMOTD("§d§k# §eMundus Crassus §d§k# §f-  [§d1.18.1§f]\n§fJetzt auf §c1.18.1 §fund §cohne Mod§f!");
 
-//script.start("system/init");
-//script.startNamed("Perms", "utils/u_error", "system/perms", "utils/u_general");
-//script.startNamed("Playerdata", "utils/u_error", "system/player_data", "utils/u_general");
-//script.startNamed("Chat", "utils/u_error", "system/chat", "utils/u_general");
-//script.startNamed("Commands", "startcommands");
-
+script.start("system/init");
+script.startNamed("Perms", "utils/u_error", "system/perms", "utils/u_general");
+script.startNamed("Playerdata", "utils/u_error", "system/player_data", "utils/u_general");
+script.startNamed("Chat", "utils/u_error", "system/chat", "utils/u_general");
+script.startNamed("Commands", "startcommands");
 //script.startNamed("Creative", "utils/u_error", "system/creative", "utils/u_general");
-//script.startNamed("Copyisland", "system/copyisland", "utils/u_general");
+script.startNamed("Copyisland", "system/copyisland", "utils/u_general");
 //script.startNamed("Damage", "utils/u_error", "system/damage", "utils/u_general");
-//script.startNamed("Doors", "utils/u_error", "system/doors", "utils/u_general");
+script.startNamed("Doors", "utils/u_error", "system/doors", "utils/u_general");
 //script.startNamed("Harvest", "utils/u_error", "survival/harvest", "utils/u_general");
 //script.startNamed("Hawkeye", "utils/u_error", "system/hawkeye", "utils/u_general");
 //script.startNamed("Herobrine", "utils/u_error", "survival/herobrine", "utils/u_general");
 //script.startNamed("Playtime", "system/playtime");
-//script.startNamed("Pumpkin", "utils/u_error", "survival/pumpkin", "utils/u_general");
-//script.startNamed("Voxel", "system/voxel");
+script.startNamed("Pumpkin", "utils/u_error", "survival/pumpkin", "utils/u_general");
 //script.startNamed("Mobspawning", "survival/mobspawning");
 //script.startNamed("Fixitems", "utils/u_error", "system/fixitems", "utils/u_general");
 //script.startNamed("Trader", "utils/u_error", "survival/trader", "utils/u_general");
 //script.startNamed("Gemstones", "utils/u_error", "survival/gemstones", "utils/u_general");
 //script.startNamed("Sitting", "utils/u_error", "system/sitting", "utils/u_general");
-//script.startNamed("Ticket", "utils/u_error", "system/tickets", "utils/u_general");
-//script.startNamed("Mails", "utils/u_error", "system/mailsystem", "utils/u_general");
+script.startNamed("Ticket", "utils/u_error", "system/tickets", "utils/u_general");
+script.startNamed("Mails", "utils/u_error", "system/mailsystem", "utils/u_general");
 //script.startNamed("Shops", "utils/u_error", "system/chestshops", "utils/u_general");
 //script.startNamed("Survival", "utils/u_error", "survival/survival", "utils/u_general");
 //script.startNamed("Gamecenter", "utils/u_error", "system/gamecenter", "utils/u_general", "utils/u_games");
@@ -42,7 +39,7 @@ setMOTD("§d§k# §eMundus Crassus §d§k# §f-  [§d1.18.1§f]\n§fJetzt auf §
 //script.startNamed("Lectern", "utils/u_error", "survival/lectern", "utils/u_general");
 //script.startNamed("Mobarena", "utils/u_error", "survival/mobarena", "utils/u_general");
 //script.startNamed("TicTacToe", "utils/u_error", "minigames/tictactoe/tictactoe", "utils/u_general");
-//script.startNamed("TipLoop", "utils/u_error", "system/tiploop", "utils/u_general");
+script.startNamed("TipLoop", "utils/u_error", "system/tiploop", "utils/u_general");
 //script.startNamed("Gamerules", "system/gamerules");
 //script.startNamed("Scheduler", "utils/u_error", "system/scheduler", "utils/u_general");
 

+ 66 - 0
survival/harvest.txt

@@ -0,0 +1,66 @@
+event.load("block_break");
+event.load("block_drop");
+
+crops_tag = block.getTag("minecraft:crops");
+hoe_tag = item.getTag("km:hoe");
+
+auto_farm_set = set.new();
+set.add(auto_farm_set, "WHEAT_SEEDS");
+set.add(auto_farm_set, "CARROT");
+set.add(auto_farm_set, "POTATO");
+set.add(auto_farm_set, "BEETROOT_SEEDS");
+
+auto_farm_set2 = set.new();
+set.add(auto_farm_set2, material.get("WHEAT"));
+set.add(auto_farm_set2, material.get("CARROTS"));
+set.add(auto_farm_set2, material.get("POTATIES"));
+set.add(auto_farm_set2, material.get("BEETROOTS"));
+
+msg.string("dev", "§bHarvest §rloaded.");
+@wait
+wait();
+if(event == "block_drop") {
+	loc = location;
+} else {
+	loc = entity.getLocation(player);
+}
+world_name = world.getName(loc.getWorld(loc));
+if(world.isSurvName(world_name)) {
+	ignoreGoto(event);
+}
+goto("wait");
+
+@block_break
+if(!block.hasTag(block, crops_tag)) {
+	goto("wait");
+}
+block_type = block.getType(block_loc);
+if(!set.contains(auto_farm_set2, block_type)) {
+	goto("wait");
+}
+if(player.checkHandsForTag(player, hoe_tag)) {
+	cancel = false;
+}
+goto("wait");
+
+@block_drop
+item = living.getEquip(player);
+if(!block.hasTag(block, crops_tag)) {
+	goto("wait");
+}
+if(!item.hasTag(item, hoe_tag)) {
+	goto("wait");
+}
+for(i = 0; i < list.getSize(drops); i++) {
+	drop_item_entity = list.getIndex(drops, i);
+	drop_item = item.entity.get(drop_item_entity);
+	if(set.contains(auto_farm_set, item.getType(drop_item))) {
+		amount = item.getAmount(drop_item);
+		if(amount > 0) {
+			item.setAmount(drop_item, amount - 1);
+		}
+	}
+}
+block.setData(location, concat(block_type, "[age=0]"));
+player.damageItem(player, 1);
+goto("wait");

+ 74 - 0
survival/herobrine.txt

@@ -0,0 +1,74 @@
+event.load("block_break");
+event.load("human_hurt");
+event.load("entity_join");
+herobrines = list.new();
+
+msg("dev", "§bHerobrine §rloaded.");
+@wait
+wait();
+if(event == "entity_join") {
+	if(entity.getType(entity) != "human") {
+		goto("wait");
+	}
+	if(entity.getName(entity) != "Herobrine") {
+		goto("wait");
+	}
+	if(list.contains(herobrines, entity)) {
+		goto("wait");
+	}
+	entity.remove(entity);
+	goto("wait");
+}
+if(event == "human_hurt") {
+	entity_name = entity.getName(human);
+	if(list.contains(herobrines, human)) {
+		if(entity == null) {
+			goto("wait");
+		}
+		if(!isLiving(entity)) {
+			goto("wait");
+		}
+		living.damage(entity, 10, damage.get("thorns", human));
+	}
+	goto("wait");
+}
+if(event == "block_break") {
+	player_loc = entity.getLocation(player);
+	world_name = world.getName(loc.getWorld(player_loc));
+	if(!world.isSurvName(world_name)) {
+		goto("wait");
+	}
+	r = math.random(1, 2000);
+	if(r == 1) {
+		spawnHerobrine(player);
+	}
+	goto("wait");
+}
+goto("wait");
+
+function spawnHerobrine(player) {
+	player_loc = entity.getLocation(player);
+	dist = math.random(4, 20);
+	alpha = math.random(0, 360);
+	alpha *= math.pi() / 180;
+	x = math.round(math.sin(alpha) * dist) + 0.5;
+	z = math.round(math.cos(alpha) * dist) + 0.5;
+	y = 255;
+	hero_loc = loc.mod(player_loc, x, y, z);
+	while(block.isAir(hero_loc)) {
+		loc.setY(hero_loc, y);
+		y--;
+	}					
+	loc.addY(hero_loc, 1);
+	ent = human.spawn(hero_loc);
+	list.add($herobrines, ent);
+	human.setSkin(ent, "herobrine");
+	entity.setName(ent, "Herobrine");
+	sgoto(400, "deleteHerobrine");
+}
+
+@deleteHerobrine
+ent = list.getIndex(herobrines, 0);
+list.removeIndex(herobrines, 0);
+entity.remove(ent);
+goto("wait");

+ 33 - 0
survival/pumpkin.txt

@@ -0,0 +1,33 @@
+event.load("block_click");
+
+times = map.new();
+pumpkin_wait_time = 3; //seconds
+
+lore_list = list.new();
+list.add(lore_list, text.new("An almost whole pumpkin pie"));
+list.add(lore_list, text.new("Herobrine has already eaten a piece."));
+pumpkin = item.create("minecraft:pumpkin_pie", 1, "PumpkinMinusOneEighthCake", lore_list);
+
+pumpkin_loc = loc.new(world.getOverWorld(), 109, 94, -23);
+
+msg.string("dev", "§bPumpkinPie §rloaded.");
+@main
+wait();
+if(event == "block_click") {
+	if(block == null) {
+		goto("main");
+	}
+	if(block.getLocation(block) == pumpkin_loc && action == "RIGHT_CLICK_BLOCK" && hand == read.slot("HAND")) {
+		player_uuid = player.getUuid(player);
+		now_time = time.getMillis();
+		time = map.getOrDefault(times, player_uuid, 0);
+		diff_time = (now_time - time) / 1000;
+		if(diff_time > pumpkin_wait_time) {
+			map.add(times, player_uuid, now_time);
+			player.giveItem(player, pumpkin);
+		} else {
+			msg.prefix(player, "§6FoodGiver", string.concat("Please wait for ", string.number(math.round(pumpkin_wait_time - diff_time)), " seconds."));
+		}
+	}
+}
+goto("main");

+ 1214 - 0
survival/survival.txt

@@ -0,0 +1,1214 @@
+event.load("entity_click");
+event.load("container_click");
+event.load("inv_click");
+event.load("player_pre_respawn");
+event.load("player_post_respawn");
+event.load("player_login");
+event.load("player_move");
+event.load("block_break");
+event.load("block_click");
+event.load("living_death");
+event.load("living_pre_hurt");
+event.load("pre_explosion");
+event.load("mob_griefing");
+event.load("item_air_click");
+event.load("projectile_hit");
+event.load("ender_teleport");
+
+setScriptVar("skills", list.new());
+skill.add("Keep Inventory", "skill.subcu_inv", "minecraft:chest", "Keeps the inventory on death", 100, false, false, true);
+skill.add("Comeback", "skill.comeback", "km:skill55", "Respawn at your death location", 100, false, false, true);
+skill.add("Head Hunter", "skill.head_human", "minecraft:player_head", "Drops a player's head with a 20% chance if you kill a player (5% if a staff member is killed)", 1000, true, false, false);
+skill.add("Mobheads", "skill.head_monster", "minecraft:zombie_head", "Drops a mobs's head with a 20% chance (zombie / skeleton / creeper)", 500, true, false, false);
+skill.add("Fly 10min", "skill.fly10min", "minecraft:elytra", "You can fly for 10 minutes", 4096, false, true, false);
+skill.add("Grow", "skill.grow", "minecraft:farmland", "Grow seeds in radius 5", 25, false, true, false);
+skill.add("Haste", "skill.haste", "minecraft:iron_pickaxe", "Haste for 2 minutes", 25, false, true, false);
+skill.add("Speed", "skill.speed", "minecraft:iron_boots", "Speed for 2 minutes", 25, false, true, false);
+skill.add("Jump Boost", "skill.jump_boost", "minecraft:rabbit_foot", "JumpBoost Lvl.2 for 2 minutes", 25, false, true, false);
+skill.add("Dolphin", "skill.dolphin", "minecraft:fire_coral", "Swim like a dolphin for a minute", 25, false, true, false);
+skill.add("Block Up", "skill.block_up", "minecraft:diamond_pickaxe", "Break a block and the block above for a minute", 25, false, true, false);
+skill.add("Block Down", "skill.block_down", "minecraft:diamond_pickaxe", "Break a block and the block below for a minute", 25, false, true, false);
+skill.add("Timber", "skill.timber", "minecraft:iron_axe", "Break whole trees with an axe for a minute", 128, false, true, false);
+skill.add("Fire Arrow", "skill.fire_arrow", "minecraft:arrow", "For a minute with an flame enchanted bow your arrows ignite hit blocks", 50, false, true, false);
+skill.add("Better Shears", "skill.better_shears", "minecraft:shears", "Sharpness enchanted shears increase the radius for destruction of leaves", 500, true, false, true);
+skill.add("Cobweb Miner", "skill.cobweb_miner", "minecraft:cobweb", "Swords increase the radius for destruction of cobwebs", 250, true, false, true);
+
+clan.loadData();
+
+tp_list = list.new();
+tp_map = map.new();
+tp_set = set.new();
+afk_loop_map = map.new();
+death_loc_map = map.new();
+survival_respawn = set.new();
+
+overworld = world.getOverWorld();
+moveid_storyspawn = event.addMoveData(loc.new(overworld, 167, 70, 241), loc.new(overworld, 169, 72, 243), 5, -1);
+moveid_gamesspawn = event.addMoveData(loc.new(overworld, 219, 66, 253), loc.new(overworld, 223, 69, 258), 5, -1);
+
+move_id_afk_loop = event.addMoveData(loc.new(overworld, 208, 69, 226), loc.new(overworld, 209, 69.5, 227), 5, -1);
+move_id_afk_loop_2 = event.addMoveData(loc.new(overworld, 208, 62, 242), loc.new(overworld, 209, 62.5, 243), 5, -1);
+move_id_afk_loop_3 = event.addMoveData(loc.new(overworld, 210, 62, 242), loc.new(overworld, 211, 62.5, 243), 5, -1);
+move_id_afk_loop_4 = event.addMoveData(loc.new(overworld, 206, 62, 246), loc.new(overworld, 207, 62.5, 247), 5, -1);
+move_id_afk_loop_5 = event.addMoveData(loc.new(overworld, 212, 62, 246), loc.new(overworld, 213, 62.5, 247), 5, -1);
+
+afk_loop_ids = set.new();
+set.add(afk_loop_ids, move_id_afk_loop);
+set.add(afk_loop_ids, move_id_afk_loop_2);
+set.add(afk_loop_ids, move_id_afk_loop_3);
+set.add(afk_loop_ids, move_id_afk_loop_4);
+set.add(afk_loop_ids, move_id_afk_loop_5);
+
+config = getScriptVar("server_config");
+survival_spawn = read.location(config.getString(config, "surv_spawn", "games:0:0:0"));
+adventure_chest_loc = loc.new(overworld, 177, 74, 237);
+adventure_aim_loc = loc.new(overworld, 180, 70, 241);
+lottery_loc_1 = loc.new(overworld, 186, 69, 227);
+lottery_loc_2 = loc.new(overworld, 186, 69, 223);
+gambler_loc = loc.new(overworld, 185, 68, 225);
+prefix_money = "§2Money";
+prefix_skill = "§2Skill";
+
+sword_tag = item.getTag("km:sword");
+dye_tag = item.getTag("km:dye");
+leaves_tag = block.getTag("minecraft:leaves");
+sign_tag = block.getTag("minecraft:signs");
+prop_persistent = block.getProperty("persistent");
+
+ench_flame = enchantment.get("flame");
+ench_unbreaking = enchantment.get("unbreaking");
+ench_sharpness = enchantment.get("sharpness");
+piston_sound = sound.get("block.piston.extend");
+adv_tp_sound = sound.get("block.portal.travel");
+sound_category_ambient = sound.getCategory("ambient");
+
+sound_category_master = sound.getCategory("master");
+sound_flute = sound.get("block.note_block.flute");
+sound_harp = sound.get("block.note_block.harp");
+sound_pling = sound.get("block.note_block.pling");
+sound_cat = sound.get("entity.cat.ambient");
+sound_stray_cat = sound.get("entity.cat.stray_ambient");
+sound_purreow = sound.get("entity.cat.purreow");
+sound_drink_milk = sound.get("entity.wandering_trader.drink_milk");
+sound_slime_place = sound.get("block.slime_block.place");
+sound_eating = sound.get("entity.generic.eat");
+
+music_chirp = sound.get("music_disc.chirp");
+
+Sound_Pitch_List = list.new();
+for(a = -12; a <= 12; a++){
+	list.add(Sound_Pitch_List, math.pow(2, -a / 12));
+}
+
+gambler_inv = inv.new("020202020");
+gambler_inv_id = inv.getId(gambler_inv);
+inv.setItem(gambler_inv, 0, read.item("km:coin_copper", 1, "§f1 snuvi"));
+inv.setItem(gambler_inv, 1, read.item("km:coin_silver", 1, "§f64 snuvis"));
+inv.setItem(gambler_inv, 2, read.item("km:coin_gold", 1, "§f4096 snuvis"));
+inv.setItem(gambler_inv, 3, read.item("minecraft:netherite_block", 1, "§fAll in"));
+
+//bankmenu = inv.new("233302332233302332");
+bankmenu = inv.new("233330000233330000000000000233200000233200000");
+//bankmenu = inv.new("233330000 233330000 000000000 233200000 233200000");
+bankinvid = inv.getId(bankmenu);
+coin_gold = read.item("km:coin_gold");
+coin_silver = read.item("km:coin_silver");
+coin_copper = read.item("km:coin_copper");
+coin_silver64 = read.item("km:coin_silver", 64);
+coin_copper64 = read.item("km:coin_copper", 64);
+arrow_left = read.item("km:arrow_left", 1, "§fchange to");
+arrow_right = read.item("km:arrow_right", 1, "§fchange to");
+
+inv.setItem(bankmenu, 0, read.item("km:plus_green", 1, "§fDeposit..."));
+inv.setItem(bankmenu, 1, read.item("km:coin_copper", 1, "§f1 snuvi"));
+inv.setItem(bankmenu, 2, read.item("km:coin_silver", 1, "§f64 snuvis"));
+inv.setItem(bankmenu, 3, read.item("km:coin_gold", 1, "§f4096 snuvis"));
+inv.setItem(bankmenu, 4, read.item("minecraft:netherite_block", 1, "§fAll snuvis"));
+inv.setItem(bankmenu, 5, read.item("km:minus_red", 1, "§fWithdraw..."));
+inv.setItem(bankmenu, 6, read.item("km:coin_copper", 1, "§f1 snuvi"));
+inv.setItem(bankmenu, 7, read.item("km:coin_silver", 1, "§f64 snuvis"));
+inv.setItem(bankmenu, 8, read.item("km:coin_gold", 1, "§f4096 snuvis"));
+inv.setItem(bankmenu, 9, read.item("minecraft:netherite_block", 1, "§fAll snuvis"));
+inv.setItem(bankmenu, 10, read.item("km:coin_copper", 64, "§f64 snuvis"));
+inv.setItem(bankmenu, 11, arrow_left);
+inv.setItem(bankmenu, 12, arrow_right);
+inv.setItem(bankmenu, 13, read.item("km:coin_silver", 1, "§f64 snuvis"));
+inv.setItem(bankmenu, 14, read.item("km:coin_silver", 64, "§f4096 snuvis"));
+inv.setItem(bankmenu, 15, arrow_left);
+inv.setItem(bankmenu, 16, arrow_right);
+inv.setItem(bankmenu, 17, read.item("km:coin_gold", 1, "§f4096 snuvis"));
+
+msg("dev", "§bSurvival §rloaded.");
+@wait
+wait();
+if(event == "player_move") {
+	if(id == moveid_storyspawn) {
+		player.setBackPosLoc(player, world.getServerSpawn());
+		player.teleport(player, world.getStorySpawn(), false);
+		goto("wait");
+	}
+	if(id == moveid_gamesspawn) {
+		player.setBackPosLoc(player, world.getServerSpawn());
+		player.teleport(player, world.getGamesSpawn(), false);
+		goto("wait");
+	}
+	if(set.contains(afk_loop_ids, id)) {
+		player_uuid = player.getUuid(player);
+		now_time = time.getMillis();
+		time = map.getOrDefault(afk_loop_map, player_uuid, 0);
+		if(now_time - time > 9000) { //9 Sekunden
+			map.add(afk_loop_map, player_uuid, now_time);
+			money.addBoost(player, 1);
+		}
+		goto("wait");
+	}
+	goto("wait");
+}
+//Wenn Event aus Survival-Welten, dann wird er verarbeitet
+if(event == "living_death" || event == "living_pre_hurt") {
+	loc = entity.getLocation(living_entity);
+} elseif(event == "ender_teleport") {
+	loc = location;
+} elseif(event == "pre_explosion") {
+	loc = location;
+} elseif(event == "mob_griefing") {
+	if(entity == null) {
+		goto("wait");
+	}
+	loc = entity.getLocation(entity);
+} else {
+	loc = entity.getLocation(player);
+}
+world_name = world.getName(loc.getWorld(loc));
+if(world.isSurvName(world_name)) {
+	ignoreGoto(event);
+}
+goto("wait");
+
+@ender_teleport
+if(!isPlayer(living_entity)) {
+	goto("wait");
+}
+player = living_entity;
+if(player.isOnAdventure(player)) {
+	cancel = true;
+	msg.prefix(player, "§5Adventure", "Using Enderpearls during adventures? Nope!");
+	goto("wait");
+}
+//Verhindert während eines (Abenteuer-)Teleports, die Benutzung der Enderperle
+player_uuid = player.getUuid(player);
+if(set.contains(tp_set, player_uuid)) {
+	cancel = true;
+	msg.prefix(player, "§5Adventure", "Using Enderpearls during adventures? Nope!");
+}
+goto("wait");
+
+@item_air_click
+player_loc = entity.getLocation(player);
+world = loc.getWorld(player_loc);
+if(world.getName(world) != "overworld") {
+	goto("wait");
+}
+item = living.getEquip(player, "hand");
+if(item.getType(item) != "minecraft:clock") {
+	goto("wait");
+}
+time = world.getTime(world);
+time_h = math.roundDown(time/1000) + 6;
+while(time_h >= 24) {
+	time_h -= 24;
+}
+//m min = t ticks * 60m / 1000 ticks
+time_m = time%1000;
+time_m = math.roundDown(time_m * 60 / 1000);
+if(time_m < 10) {
+	time_m = concat("0", text.number(time_m));
+} else {
+	time_m = text.number(time_m);
+}
+msg.prefix(player, "§eClock", concat(text.number(time_h), ":", time_m));
+goto("wait");
+
+@mob_griefing
+if(entity.getType(entity) == "enderman") {
+	cancel = true;
+}
+goto("wait");
+
+@pre_explosion
+plot_list = plot.get(location);
+for(i = 0; i < list.getSize(plot_list); i++) {
+	plot = list.getIndex(plot_list, i);
+	if(plot.isExplosive(plot)) {
+		cancel = false;
+	}
+}
+//Kein Grundstück existiert
+if(i == 0) {
+	cancel = false;
+}
+goto("wait");
+
+@living_pre_hurt
+if(!isPlayer(living_entity)) {
+	damager = player.getFromDamageSource(damage_source);
+	if(!isPlayer(damager)) {
+		goto("wait");
+	}
+	pet_type = entity.getType(living_entity);
+	if(pet_type == "wolf" || pet_type == "cat" || pet_type == "parrot" || pet_type == "horse") {
+		if(pet.isTamed(living_entity)) {
+			owner_uuid = pet.getOwner(living_entity);
+			if(owner_uuid == player.getUuid(damager)) {
+				if(player.getNoPetDamage(damager)) {
+					cancel = true;
+				}
+			}
+		}
+	}
+	goto("wait");
+}
+player = living_entity;
+damager = player.getFromDamageSource(damage_source);
+if(!isPlayer(damager)) {
+	player_loc = entity.getLocation(player);
+	if(loc.hasPlotId(player_loc, 128) && damage.getType(damage_source) == "fall") {
+		cancel = true;
+	}
+	goto("wait");
+}
+if(player == damager) {
+	goto("wait");
+}
+if(!hasPvpOn(damager)) {
+	cancel = true;
+	msg.prefix(damager, "§5PvP", "You have PvP disabled.");
+	goto("wait");
+}
+if(!hasPvpOn(player)) {
+	cancel = true;
+	msg.prefix(damager, "§5PvP", concat(player.getName(player), " has PvP disabled."));
+	goto("wait");
+}
+goto("wait");
+
+@entity_click
+if(hand == "OFF_HAND") {
+	goto("wait");
+}
+if(entity.getType(entity) == "human") {
+	entity_name = entity.getName(entity);
+	if(entity_name == "Administrator\n§cmarvinius") {
+		item = living.getHand(player);
+		item_name = item.getName(item);
+		if(removeFormat(item_name) == "Beer") {
+			sound.spawnForPlayer(player, $sound_drink_milk, $sound_category_master, 1, 1);
+			msg.prefix(player, "§cmarvinius", "Prost!");
+		}
+		else{
+			msg.prefix(player, "§cmarvinius", "Ich mag Gösser.");
+		}
+		goto("wait");
+	}
+	if(entity_name == "Owner\n§4kajetanjohannes") {
+		item = living.getHand(player);
+		item_type = item.getType(item);
+		sound.spawnForPlayer(player, $sound_slime_place, $sound_category_master, 1, 1);
+		if(item_type == "minecraft:redstone") {
+			rand_number = math.roundup(math.random(0,3));
+			if(rand_number == 0){
+				temp_message = "WUSIWUSIWUSIWUSIWUSIWUSIWUSIWUSI";
+			}
+			if(rand_number == 1){
+				temp_message = "Wusi!";
+			}
+			if(rand_number == 2){
+				temp_message = "Wusi?";
+			}
+			if(rand_number == 3){
+				temp_message = "Wusi.";
+			}
+			msg.prefix(player, "§4kajetanjohannes", temp_message);
+			goto("wait");
+		}
+		if(item_type == "minecraft:ice" || item_type == "minecraft:blue_ice" || item_type == "minecraft:packed_ice"){
+			msg.prefix(player, "§4kajetanjohannes", "§bDas sieht nach mir aus.");
+		}else{
+			msg.prefix(player, "§4kajetanjohannes", "wusi");
+		}
+	goto("wait");
+	}
+	if(entity_name == "Supporter\n§bImKillerKatze") {
+		rand_number = math.roundup(math.random(0,25));
+		if(rand_number > 13){
+			sound.spawnForPlayer(player, $sound_cat, $sound_category_master, 1, 1);
+			msg.prefix(player, "§bImKillerKatze", "Miau");
+			goto("wait");
+		}
+		if(rand_number < 12){
+			sound.spawnForPlayer(player, $sound_stray_cat, $sound_category_master, 1, 1);
+			msg.prefix(player, "§bImKillerKatze", "Miau!");
+			goto("wait");
+		}
+		else{
+			sound.spawnForPlayer(player, $sound_purreow, $sound_category_master, 1, 1);
+			msg.prefix(player, "§bImKillerKatze", "Schnurrr!");
+			goto("wait");
+		}
+	}
+	if(entity_name == "Administrator\n§cwertibaldi") {
+			msg.prefix(player, "§cwertibaldi", "Kann grad nicht, bin im Einsatz für den Katastrophenschutz.");
+		goto("wait");
+	}
+	if(entity_name == "Administrator\n§cMentorMentos") {
+		item = living.getHand(player);
+		item_name = item.getName(item);
+		if(removeFormat(item_name) == "Beer") {
+			msg.prefix(player, "§cMentorMentos", "Folg mir auf Twitch! ");
+			msg(player, text.link("Klick mich an :D","https://www.twitch.tv/Mentor_Mentos"));
+		}
+		else{
+			msg.prefix(player, "§cMentorMentos", "Ich mag Kölsch.");
+		}
+		goto("wait");
+	}
+	if(entity_name == "Moderator\n§9SirTerence7") {
+		rand_number = math.roundup(math.random(0,7));
+		if(rand_number < 4){
+			msg.prefix(player, "§9SirTerence7", "Mathe bla... bla... bla...");
+		}
+		if(rand_number == 4){
+			msg.prefix(player, "§9SirTerence7", "Fraktale bla... bla... bla...");
+		}
+		if(rand_number == 5){
+			msg.prefix(player, "§9SirTerence7", "Höhere Dimensionen bla... bla... bla...");
+		}
+		if(rand_number == 6){
+			msg.prefix(player, "§9SirTerence7", "*redet mit Händen weiter*");
+		}
+		if(rand_number == 7){
+			msg.prefix(player, "§9SirTerence7", "*wechselt voller Faszination zwischen scheinbar zusammenhangslosen Themen hin und her*");
+		}
+
+
+		rand_number = math.roundup(math.random(0,500));
+		if(rand_number <= 2){
+			sound.spawnForPlayer(player, $music_chirp, $sound_category_master, 1, 1);
+		}else{
+			rand_pitch = math.roundup(math.random(4, list.getSize(Sound_Pitch_List)-5));
+			if(rand_number < 200){
+				pitch1 = list.getIndex(Sound_Pitch_List, rand_pitch-4);
+				pitch2 = list.getIndex(Sound_Pitch_List, rand_pitch);
+				pitch3 = list.getIndex(Sound_Pitch_List, rand_pitch+3);
+			}else{
+				if(rand_number < 300){
+					pitch1 = list.getIndex(Sound_Pitch_List, rand_pitch-4);
+					pitch1_2 = list.getIndex(Sound_Pitch_List, rand_pitch-2);
+					pitch2 = list.getIndex(Sound_Pitch_List, rand_pitch);
+					pitch3_2 = list.getIndex(Sound_Pitch_List, rand_pitch+1);
+					pitch3 = list.getIndex(Sound_Pitch_List, rand_pitch+3);
+					sound.spawnForPlayer(player, $sound_harp, $sound_category_master, 0.5, pitch1_2);
+					sound.spawnForPlayer(player, $sound_harp, $sound_category_master, 0.5, pitch3_2);
+					sound.spawnForPlayer(player, $sound_flute, $sound_category_master, 0.75, pitch1_2);
+					sound.spawnForPlayer(player, $sound_flute, $sound_category_master, 0.75, pitch3_2);
+				}else{
+					pitch1 = list.getIndex(Sound_Pitch_List, rand_pitch-3);
+					pitch2 = list.getIndex(Sound_Pitch_List, rand_pitch);
+					pitch3 = list.getIndex(Sound_Pitch_List, rand_pitch+4);
+				}
+			}
+			sound.spawnForPlayer(player, $sound_harp, $sound_category_master, 0.8, pitch1);
+			sound.spawnForPlayer(player, $sound_harp, $sound_category_master, 0.9, pitch2);
+			sound.spawnForPlayer(player, $sound_harp, $sound_category_master, 0.8, pitch2);
+			sound.spawnForPlayer(player, $sound_flute, $sound_category_master, 0.9, pitch1);
+			sound.spawnForPlayer(player, $sound_flute, $sound_category_master, 1, pitch2);
+			sound.spawnForPlayer(player, $sound_flute, $sound_category_master, 0.9, pitch3);
+		}
+		goto("wait");
+	}
+	if(entity_name == "Moderator\n§9Mareeeen") {
+		rand_number = math.roundup(math.random(0,5));
+		if(rand_number > 1){
+			msg.prefix(player, "§9Mareeeen", "Wo ist die Schokolade versteckt!?");
+		}else{
+			msg.prefix(player, "§9Mareeeen", "Ich esse deine Schokolade!");
+			sound.spawnForPlayer(player, $sound_eating, $sound_category_master, 1, 1);
+		}
+		goto("wait");
+	}
+	
+	if(entity_name == "Info-Point") {
+		msg(player, string.getSpacer());
+		msg(player, text.click("§r [§cclick§r] [§eSurvival§r]", "/infopoint1"));
+		msg(player, text.click("§r [§cclick§r] [§eAdventure§r]", "/infopoint2"));
+		msg(player, text.click("§r [§cclick§r] [§ePlots§r]", "/infopoint3"));
+		msg(player, text.click("§r [§cclick§r] [§eClans§r]", "/infopoint4"));
+		msg(player, text.click("§r [§cclick§r] [§eCities§r]", "/infopoint5"));
+		msg(player, text.click("§r [§cclick§r] [§eShops§r]", "/infopoint6"));
+		msg(player, text.click("§r [§cclick§r] [§eMinigames§r]", "/infopoint7"), " ", text.click("§f[§bTeleport§f]", "/games"));
+		msg(player, text.click("§r [§cclick§r] [§eQuests§r]", "/infopoint8"), " ", text.click("§f[§bTeleport§f]", "/story"));
+		msg(player, text.click("§r [§cclick§r] [§eCreative§r]", "/infopoint12"), " ", text.click("§f[§bTeleport§f]", "/creative"));
+		msg(player, text.click("§r [§cclick§r] [§eRanking§r]", "/infopoint9"), " ", text.link("§f[§bRanks§f]", "https://minecraft.hammerle.me/?site=ranks"));
+		msg(player, text.click("§r [§cclick§r] [§eRules§r]", "/infopoint10"), " ", text.link("§f[§bFake Rules§f]", "https://minecraft.hammerle.me/?site=rules"));
+		msg(player, text.click("§r [§cclick§r] [§eNote§r]", "/infopoint11"));
+		goto("wait");
+	}
+	if(entity_name == "Banker") {
+		inv.open(bankmenu, player, "Banker");
+		goto("wait");
+	}
+	if(entity_name == "Adventure") {
+		if(!player.isOnAdventure(player)) {
+			msg.prefix(player, "§5Adventure", "You aren't on an adventure. Click the chest in the teleporter to start an adventure.");
+			goto("wait");
+		}
+		player.setAdventure(player, false);
+		adventures = player.getAdventureAmounts(player);
+		if(adventures == null) {
+			adventures = 0;
+		}
+		player.setAdventureAmounts(player, ++adventures);
+		msg.prefix(player, "§5Adventure", "Congratulations, you finished your adventure, here ist your reward!");
+		if(adventures == 10) {
+			offerRank(player, "rank.pioneer");
+		} elseif(adventures == 5) {
+			offerRank(player, "rank.explorer");
+		} elseif(adventures == 1) {
+			offerRank(player, "rank.adventurer");
+		}
+		removeAdventureDisplay(player);
+		player.safeGiveItem(player, item.getAmber());
+		money.addBoost(player, 4096);
+		goto("wait");
+	}
+}
+goto("wait");
+
+@player_login
+if(player.isOnAdventure(player)) {
+	addAdventureDisplay(player, adventure_aim_loc);
+}
+goto("wait");
+
+@container_click
+//Verhindert während eines (Abenteuer-)Teleports, die Benutzung des Spielerinventars (inkl. Crafting-Bereich!)
+player_uuid = player.getUuid(player);
+if(set.contains(tp_set, player_uuid)) {
+	cancel = true;
+}
+goto("wait");
+
+@inv_click
+if(inv_id == bankinvid) { //Bankmenü
+	factor = 1;
+	if(click_type == "QUICK_MOVE") {
+		factor = 8;
+	}
+	gold_inv = player.getItemAmount(player, false, coin_gold);
+	silver_inv = player.getItemAmount(player, false, coin_silver);
+	copper_inv = player.getItemAmount(player, false, coin_copper);
+	//Wechseln
+	if(inv_slot == 11 || inv_slot == 12 || inv_slot == 15 || inv_slot == 16)  {
+		if(inv_slot == 11) {
+			//1 Silbermünze --> 64 Kupfermünzen
+			from_item = coin_silver;
+			to_item = coin_copper64;
+			message = "Not enough silvercoins in inventory.";
+			item_type = "km:coin_copper";
+			needed_inv_coins = silver_inv;
+		}
+		elseif(inv_slot == 12) {
+			//64 Kupfermünzen --> 1 Silbermünze
+			from_item = coin_copper64;
+			to_item = coin_silver;
+			message = "Not enough coppercoins in inventory.";
+			item_type = "km:coin_silver";
+			needed_inv_coins = copper_inv;
+		}
+		elseif(inv_slot == 15) {
+			//1 Goldmünze --> 64 Silbermünzen
+			from_item = coin_gold;
+			to_item = coin_silver64;
+			message = "Not enough goldcoins in inventory.";
+			item_type = "km:coin_silver";
+			needed_inv_coins = gold_inv;
+		}
+		elseif(inv_slot == 16) {
+			//64 Silbermünzen --> 1 Goldmünze
+			from_item = coin_silver64;
+			to_item = coin_gold;
+			message = "Not enough silvercoins in inventory.";
+			item_type = "km:coin_gold";
+			needed_inv_coins = silver_inv;
+		}
+		item_1 = item.clone(from_item);
+		item.setAmount(item_1, item.getAmount(item_1) * factor);
+		item_2 = item.clone(to_item);
+		item.setAmount(item_2, item.getAmount(item_2) * factor);
+		amount1 = item.getAmount(item_1);
+		amount2 = item.getAmount(item_2);
+		if(needed_inv_coins * factor < amount1 * factor) {
+			msg.prefix(player, prefix_money, message);
+			goto("wait");
+		}
+		player.removeItemNbt(player, item_1);
+		notgiven = player.giveItem(player, item_2);
+		if(item.getType(notgiven) != "minecraft:air") {
+			amount = item.getAmount(notgiven);
+			player.removeItemNbt(player, read.item(item_type, amount2 - amount));
+			player.giveItem(player, item_1);
+			msg.prefix(player, prefix_money, "Not enough space in inventory.");
+			goto("wait");
+		}
+		inv.update(player);
+		msg.prefix(player, prefix_money, "Exchange succesfull.");
+		goto("wait");
+	}
+	//Kontobewegungen
+	if(inv_slot == 1 || inv_slot == 6) {
+		betrag = 1 * factor;
+		coin_inv = copper_inv;
+	}
+	elseif(inv_slot == 2 || inv_slot == 7) {
+		betrag = 64 * factor;
+		coin_inv = silver_inv;
+	}
+	elseif(inv_slot == 3 || inv_slot == 8) {
+		betrag = 4096 * factor;
+		coin_inv = gold_inv;
+	}
+	elseif(inv_slot == 4 || inv_slot == 9) {
+		if(inv_slot == 4) {
+			betrag = copper_inv + silver_inv * 64 + gold_inv * 4096;
+			coin_inv = 8;
+		} elseif(inv_slot == 9) {
+			betrag = getMoney(player);
+			coin_inv = 8;
+		}
+	}
+	//Einzahlen
+	if(inv_slot > 0 && inv_slot < 5) {
+		if(coin_inv < 1 * factor) {
+			msg.prefix(player, prefix_money, "Coins not in inventory.");
+			goto("wait");
+		}
+		if(betrag == 0) {
+			msg.prefix(player, prefix_money, "No coins in your inventory.");
+			goto("wait");
+		}
+		addMoney(player, betrag);
+		if(inv_slot == 4) {
+			player.removeItemNbt(player, read.item("km:coin_gold", gold_inv));
+			player.removeItemNbt(player, read.item("km:coin_silver", silver_inv));
+			player.removeItemNbt(player, read.item("km:coin_copper", copper_inv));
+		} else {
+			remove_item = item.clone(inv.getItem(bankmenu, inv_slot));	
+			item.setAmount(remove_item, item.getAmount(remove_item) * factor);
+			player.removeItemNbt(player, remove_item);
+		}
+		inv.update(player);
+		goto("wait");
+	}
+	//Auszahlen
+	if(inv_slot > 5 && inv_slot < 10) {
+		if(!hasEnoughMoney(player, betrag)) {
+			msg.prefix(player, prefix_money, "Not enough snuvis on your account.");
+		} else {
+			subMoney(player, betrag);
+			if(inv_slot == 9) {
+				gold_amount = math.roundDown(betrag / 4096);
+				betrag %= 4096;
+				silver_amount = math.roundDown(betrag / 64);
+				copper_amount = math.roundDown(betrag % 64);
+				coin_item = read.item("km:coin_gold", gold_amount);
+				player.safeGiveItem(player, coin_item);
+				coin_item = read.item("km:coin_silver", silver_amount);
+				player.safeGiveItem(player, coin_item);
+				coin_item = read.item("km:coin_copper", copper_amount);
+				player.safeGiveItem(player, coin_item);
+			} else {
+				item = inv.getItem(bankmenu, inv_slot);
+				new_item = read.item(item.getType(item), item.getAmount(item) * factor);
+				player.safeGiveItem(player, new_item);
+			}
+			inv.update(player);
+		}
+		goto("wait");
+	}
+	goto("wait");
+}
+if(inv_id == gambler_inv_id) {
+	if(inv_slot == 0) {
+		amount = 1;
+	} elseif(inv_slot == 1) {
+		amount = 64;
+	} elseif(inv_slot == 2) {
+		amount = 4096;
+	} elseif(inv_slot == 3) {
+		amount = getMoney(player);
+		if(amount == 0) {
+			msg.prefix(player, prefix_money, "You need at least 1 snuvi on your account.");
+			goto("wait");
+		}
+	}
+	if(!hasEnoughMoney(player, amount)) {
+		msg.prefix(player, prefix_money, "Not enough snuvis on your account.");
+		goto("wait");
+	}
+	win = math.random(1, 2);
+	if(win == 1) {
+		addMoney(player, amount);
+		temp = " won ";
+	} else {
+		subMoney(player, amount);
+		temp = " lost ";
+	}
+	if(amount == 1) {
+		message = concat(player.getName(player), temp, text.number(amount), " snuvi.");
+	} else {
+		message = concat(player.getName(player), temp, text.number(amount), " snuvis.");
+	}
+	if(amount < 64) {
+		msg.prefix(player, "§2Gambler", message);
+	} elseif(amount >= 131072) {
+		msg.online("§2Gambler", message);
+	} else {
+		msg.radius("§2Gambler", message, entity.getLocation(player), 10);
+	}
+	goto("wait");
+}
+goto("wait");
+
+@projectile_hit
+if(!isPlayer(shooter)) {
+	goto("wait");
+}
+player = shooter;
+duration = data.getTimer(player, "skill.fire_arrow");
+if(duration > 0) {
+	if(loc_hit == null) {
+		goto("wait");
+	}
+	flame = enchantment.getLevel(ench_flame, living.getHand(player));
+	if(flame <= 0) {
+		goto("wait");
+	}
+	if(!plot.check(loc_hit, player, 3, true) && !perm.has(player, "plot.bypass")) {
+		msg.prefix(player, prefix_skill, "You have no permissions on this plot.");
+		goto("wait");
+	}
+	ent_loc = entity.getLocation(projectile);
+	if(block.isAir(ent_loc)){
+		block.set(ent_loc, "minecraft:fire");
+	}
+	fire_ring(ent_loc, "minecraft:fire", 0);
+}
+goto("wait");
+
+function fire_ring(location, block_string, radius){
+	loc_x = loc.getX(location);
+	loc_y = loc.getY(location);
+	loc_z = loc.getZ(location);
+	for(a = -radius; a < radius + 1; a++){
+		loc.setX(location, loc_x + a);
+		for(b = -radius; b < radius + 1; b++){
+			loc.setY(location, loc_y + b);
+			for(c = -radius; c < radius + 1; c++){
+				loc.setZ(location, loc_z + c);
+				if(block.isAir(location)){
+					block.set(location, block_string);
+				}
+			}
+		}
+	}
+}
+
+@block_break
+duration = data.getTimer(player, "block_down");
+if(duration > 0) {
+	do = true;
+	loc = loc.mod(block_loc, 0, -1, 0);
+	b_type = block.getType(loc);
+	if(b_type == "minecraft:bedrock" || b_type == "minecraft:end_portal_frame") {
+		do = false;
+	}
+	if(!plot.check(loc, player, 2, true)) {
+		do = false;
+	}
+	if(do) {
+		block.break(loc, player);
+	}
+}
+duration = data.getTimer(player, "block_up");
+if(duration > 0) {
+	do = true;
+	loc = loc.mod(block_loc, 0, 1, 0);
+	b_type = block.getType(loc);
+	if(b_type == "minecraft:bedrock" || b_type == "minecraft:end_portal_frame") {
+		do = false;
+	}
+	if(!plot.check(loc, player, 2, true)) {
+		do = false;
+	}
+	if(do) {
+		block.break(loc, player);
+	}
+}
+if(block_type == "minecraft:cobweb") {
+	if(cancel) {
+		goto("wait");
+	}
+	hand_item = living.getHand(player);
+	if(!item.hasTag(sword_tag, hand_item)) {
+		goto("wait");
+	}
+	amount = skill.getAmount(player, "skill.cobweb_miner");
+	if(amount <= 0) {
+		goto("wait");
+	}
+	if(!skill.isActivated(player, "skill.cobweb_miner")) {
+		goto("wait");
+	}
+	location = loc.mod(block_loc, 0, 0, 0);
+	cobweb_X = loc.getX(location);
+	cobweb_Y = loc.getY(location);
+	cobweb_Z = loc.getZ(location);
+	cobweb_radius = 1;
+	unbreaking_level = enchantment.getLevel(ench_unbreaking, hand_item);
+	for(a = -cobweb_radius; a < cobweb_radius + 1; a++) {
+		loc.setX(location, cobweb_X + a);
+		for(b = -cobweb_radius; b < cobweb_radius + 1; b++) {
+			loc.setY(location, cobweb_Y + b);
+			for(c = -cobweb_radius; c < cobweb_radius + 1; c++) {
+				loc.setZ(location, cobweb_Z + c);
+				if(math.abs(a) + math.abs(b) + math.abs(c) + math.random(0, 2) < cobweb_radius + 2) {
+					shear_cobweb(location, block_type, player, unbreaking_level);
+				}
+			}
+		}
+	}
+	goto("wait");
+}
+if(block.hasTag(leaves_tag, block)) {
+	if(cancel) {
+		goto("wait");
+	}
+	hand_item = living.getHand(player);
+	if(item.getType(hand_item) != "minecraft:shears") {
+		goto("wait");
+	}
+	if(block.property.getValue(block_loc, prop_persistent)){
+		goto("wait");
+	}
+	amount = skill.getAmount(player, "skill.better_shears");
+	if(amount <= 0) {
+		goto("wait");
+	}
+	if(!skill.isActivated(player, "skill.better_shears")) {
+		goto("wait");
+	}
+	location = loc.mod(block_loc, 0, 0, 0);
+	shears_X = loc.getX(location);
+	shears_Y = loc.getY(location);
+	shears_Z = loc.getZ(location);
+	unbreaking_level = enchantment.getLevel(ench_unbreaking, hand_item);
+	radius = enchantment.getLevel(ench_sharpness, hand_item);
+	if(radius > 0) {
+		cancel = true;
+	}
+	orig_item = block.toStack(location);
+	for(a = -radius; a < radius + 1; a++){
+		loc.setX(location, shears_X + a);
+		for(b = -radius; b < radius + 1; b++){
+			loc.setY(location, shears_Y + b);
+			for(c = -radius; c < radius + 1; c++){
+				loc.setZ(location, shears_Z + c);
+				if(math.abs(a) + math.abs(b) + math.abs(c) + math.random(0, 2) < radius + 2) {
+					shear_leave(location, block_type, orig_item, player, unbreaking_level);
+				}
+			}
+		}
+	}
+	goto("wait");
+}
+goto("wait");
+
+function shear_leave(block_loc, original_block_type, original_item, player, unbreaking_level){
+	if(block.getType(block_loc) != original_block_type) {
+		return;
+	}
+	if(block.property.getValue(block_loc, $prop_persistent)) {
+		return;
+	}
+	block.set(block_loc, "minecraft:air");
+	item.drop(block_loc, original_item);
+	if(player.isSurvival(player)) {
+		player.damageItem(player, 1);
+	}
+}
+
+function shear_cobweb(block_loc, original_block_type, player, unbreaking_level) {
+	if(block.getType(block_loc) != original_block_type) {
+		return;
+	}
+	block.break(block_loc, player);
+	if(math.random(0, 99) < 100 / (unbreaking_level + 1)) {
+		player.damageItem(player, 1);
+	}	
+}
+
+@block_click
+if(action == "right" && player.checkHandsForTag(player, dye_tag)) {
+	/*if(block.hasTag(sign_tag, block)) {
+		if(!perm.has(player, "plot.bypass")) {
+			if(!plot.check(block_loc, player, 3, true)) {
+				cancel = true;
+				goto("wait");
+			}
+		}
+	}*/
+}
+if(hand == "OFF_HAND") {
+	goto("wait");
+}
+if(block_type == "minecraft:chest") {
+	if(isATpReceiver(block_loc)) {
+		tp_item = read.item("km:gear", 1, "§rTeleport");
+		list = list.new();
+		list.add(list, world.getName(loc.getWorld(block_loc)));
+		list.add(list, text.number(loc.getX(block_loc)));
+		list.add(list, text.number(loc.getY(block_loc)));
+		list.add(list, text.number(loc.getZ(block_loc)));
+		item.setLore(tp_item, list);
+		player.giveItem(player, tp_item);
+		goto("wait");
+	}
+	if(isATpTransmitter(block_loc)) {
+		player_uuid = player.getUuid(player);
+		clicked = map.getOrDefault(tp_map, player_uuid, 0);
+		now_time = time.getMillis();
+		if(now_time - clicked < 5000) {
+			msg.prefix(player, "§5Adventure", "Wait 5 seconds!");
+			goto("wait");
+		}
+		map.add(tp_map, player_uuid, now_time);
+		//Abenteuer-Teleport
+		if(block_loc == adventure_chest_loc) {
+			if(!player.isOnAdventure(player)) {
+				if(!player.hasClearInventory(player)) {
+					msg.prefix(player, "§5Adventure", "Your inventory needs to be empty!");
+					goto("wait");
+				}
+				alpha = math.random(0, 360);
+				alpha *= math.pi() / 180;
+				x = math.round(math.sin(alpha) * 10000) + 0.5;
+				z = math.round(math.cos(alpha) * 10000) + 0.5;
+				y = 255;
+				tp_loc = loc.new(world.getOverWorld(), x, y, z);
+				while(block.isAir(tp_loc)) {
+					loc.setY(tp_loc, y);
+					y--;
+				}					
+				tp_loc = loc.mod(tp_loc, 0, 1, 0);
+				setTpWallX(block_loc, "minecraft:lime_stained_glass");
+				sound.spawn(block_loc, piston_sound, sound_category_ambient);
+				player_uuid = player.getUuid(player);
+				array = array.new(4);
+				array[0] = player_uuid;
+				array[1] = block_loc;
+				array[2] = tp_loc;
+				array[3] = true;
+				list.add(tp_list, array);
+				set.add(tp_set, player_uuid);
+				sgoto(30, "tp_ticker");
+			}
+			goto("wait");
+		}
+		//Normaler Teleport
+		temp = false;
+		inv = block.getInv(block_loc);
+		inv_size = inv.getSize(inv);
+		for(i = 0; i < inv_size; i++) {
+			item = inv.getItem(inv, i);
+			if(item.getType(item) == "km:gear") {
+				if(item.getName(item) == "§rTeleport") {
+					temp = true;
+					break;
+				}
+			}
+		}
+		if(!temp) {
+			msg.prefix(player, "§5Adventure", "No receiver found!");
+			goto("wait");
+		}
+		
+		lore_list = item.getLore(item);
+		if(list.getSize(lore_list) != 4) {
+			msg.prefix(player, "§5Adventure", "No receiver found!");
+			goto("wait");
+		}
+		world = world.get(list.getIndex(lore_list, 0));
+		x = read.number(list.getIndex(lore_list, 1));
+		y = read.number(list.getIndex(lore_list, 2));
+		z = read.number(list.getIndex(lore_list, 3));
+		tp_loc = loc.new(world, x, y, z);
+		if(!isATpReceiver(tp_loc)) {
+			msg.prefix(player, "§5Adventure", "No receiver found!");
+			goto("wait");
+		}
+		loc.add(tp_loc, 0.5, -3, 0.5);
+		
+		setTpWallX(block_loc, "minecraft:lime_stained_glass");
+		sound.spawn(block_loc, piston_sound, sound_category_ambient);
+		array = array.new(4);
+		array[0] = player.getUuid(player);
+		array[1] = block_loc;
+		array[2] = tp_loc;
+		array[3] = false;
+		list.add(tp_list, array);
+		sgoto(30, "tp_ticker");
+	}
+	goto("wait");
+}
+if(block_loc == gambler_loc) {
+	cancel = true;
+	inv.open(gambler_inv, player, "Choose your amount to bet with");
+	goto("wait");
+}
+if(block_loc == lottery_loc_1 || block_loc == lottery_loc_2) {
+	if(!hasEnoughMoney(player, 1)) {
+		msg.prefix(player, prefix_money, "Not enough snuvis on your account.");
+		goto("wait");
+	}
+	subMoney(player, 1);
+	amount = lottery.add(block_loc, 1);
+	if(amount == null) {
+		goto("wait");
+	}
+	if(block_loc == lottery_loc_1) {
+		winrate = 1000;
+	} else {
+		winrate = 10000;
+	}
+	win = math.random(1, winrate);
+	if(win == 1) {
+		addMoney(player, amount);
+		lottery.set(block_loc, 0);
+		message = concat(player.getName(player), " has won ", text.number(amount), " snuvis.");
+		msg.radius(prefix_money, message, block_loc, 50);
+	}
+	goto("wait");
+}
+goto("wait");
+
+@living_death
+if(isPlayer(living_entity)) {
+	player = living_entity;
+	setDeathLoc(player);
+	loc = entity.getLocation(player);
+	amount = skill.getAmount(player, "skill.subcu_inv");
+	if(skill.isActivated(player, "skill.subcu_inv") && amount > 0) {
+		new_amount = amount - 1;
+		skill.setAmount(player, "skill.subcu_inv", new_amount);
+		msg.prefix(player, prefix_skill, concat("Used Subcutaneous Inventory. New amount: ", text.number(new_amount)));
+	} else {
+		player.dropInventory(player, loc);
+	}
+	killer = player.getFromDamageSource(damage_source);
+	if(isPlayer(killer)) {
+		amount = skill.getAmount(player, "skill.head_human");
+		if(amount >= 1) {
+			if(perm.has(player, "isTeam")) {
+				temp = math.random(1, 20);
+			} else {
+				temp = math.random(1, 5);
+			}
+			if(temp == 1) {
+				item.drop(loc, player.getHead(player.getUuid(player), player.getName(player)));
+			}
+		}
+	}
+	goto("wait");
+}
+killer = player.getFromDamageSource(damage_source);
+if(isPlayer(killer)) {
+	r = math.random(1, 20);
+	if(r == 1) {
+		amount = skill.getAmount(killer, "skill.head_monster");
+		if(amount >= 1) {
+			entity_type = entity.getType(living_entity);
+			if(entity_type == "creeper") {
+				item.drop(loc, read.item("minecraft:creeper_head"));
+				goto("wait");
+			}
+			if(entity_type == "zombie") {
+				item.drop(loc, read.item("minecraft:zombie_head"));
+				goto("wait");
+			}
+			if(entity_type == "skeleton") {
+				item.drop(loc, read.item("minecraft:skeleton_skull"));
+				goto("wait");
+			}
+		}
+	}
+}
+goto("wait");
+
+@player_pre_respawn
+if(loc.isInSurvWorld(entity.getLocation(player))) {
+	set.add(survival_respawn, player.getUuid(player));
+}
+goto("wait");
+
+@player_post_respawn
+player_uuid = player.getUuid(player);
+if(set.contains(survival_respawn, player_uuid)) {
+	set.remove(survival_respawn, player_uuid);
+	if(player.isOnAdventure(player)) {
+		tp_loc = player.getAdventureStart(player);
+		entity.teleport(player, tp_loc);
+		goto("wait");
+	}
+	amount = skill.getAmount(player, "skill.comeback");
+	if(skill.isActivated(player, "skill.comeback") && amount > 0) {
+		new_amount = amount - 1;
+		skill.setAmount(player, "skill.comeback", new_amount);
+		msg.prefix(player, prefix_skill, concat("Used Comeback. New amount: ", text.number(new_amount)));
+		entity.teleport(player, getDeathLoc(player));
+		goto("wait");
+	}
+	entity.teleport(player, world.getServerSpawn());
+}
+goto("wait");
+
+@tp_ticker
+array = list.getIndex(tp_list, 0);
+list.removeIndex(tp_list, 0);
+block_loc = array[1];
+list.add(tp_list, array);
+setTpWallFull(block_loc, "minecraft:lime_stained_glass");
+sound.spawn(block_loc, piston_sound, sound_category_ambient);
+sgoto(30, "tp_final");
+goto("wait");
+
+@tp_final
+array = list.getIndex(tp_list, 0);
+list.removeIndex(tp_list, 0);
+player_uuid = array[0];
+block_loc = array[1];
+tp_loc = array[2];
+adventure = array[3];
+set.remove(tp_set, player_uuid);
+sound.spawn(block_loc, piston_sound, sound_category_ambient);
+setTpWallFull(block_loc, "minecraft:air");
+player = player.get(player_uuid);
+if(player == null) {
+	goto("wait");
+}
+sound.spawn(tp_loc, adv_tp_sound, sound_category_ambient);
+if(adventure) {
+	//Party
+	if(player.isInParty(player) && player.isPartyLeader(player)) {
+		party_id = player.getPartyId(player);
+		party_list = party.getList(party_id);
+		iter = list.iterator(party_list);
+		while(hasNext(iter)) {
+			p = player.get(next(iter));
+			p_name = player.getName(p);
+			p_loc = entity.getLocation(p);
+			if(!loc.isSameWorld(adventure_chest_loc, p_loc)) {
+				msg.prefix(player, "§5Party", concat(p_name, "§c is in another world."));
+				msg.prefix(p, "§5Party", "§cYou are in another world.");
+				continue;
+			}
+			if(loc.distance(adventure_chest_loc, p_loc) > 5) {
+				msg.prefix(player, "§5Party", concat(p_name, "§c is too far away."));
+				msg.prefix(p, "§5Party", "§cYou are too far away.");
+				continue;
+			}
+			if(player.hasMinigame(p)) {
+				msg.prefix(player, "§5Party", concat(p_name, "§c is in a game."));
+				msg.prefix(p, "§5Party", "§cYou are in a game.");
+				continue;
+			}
+			if(player.hasQuest2(p)) {
+				msg.prefix(player, "§5Party", concat(p_name, "§c is doing a quest."));
+				msg.prefix(p, "§5Party", "§cYou are doing a quest.");
+				continue;
+			}
+			if(player.isOnAdventure(p)) {
+				msg.prefix(player, "§5Party", concat(p_name, "§c is already on an adventure."));
+				msg.prefix(p, "§5Party", "§cYou are already on an adventure.");
+				continue;
+			}
+			if(player.isAfk(p)) {
+				msg.prefix(player, "§5Party", concat(p_name, "§c is afk."));
+				msg.prefix(p, "§5Party", "§cYou are afk.");
+				continue;
+			}
+			if(!player.hasClearInventory(p)) {
+				msg.prefix(player, "§5Party", concat(p_name, "§c has no clear inventory."));
+				msg.prefix(p, "§5Party", "§cYou have no clear inventory.");
+				continue;
+			}
+			player.teleport(p, tp_loc, false);
+			player.setAdventure(p, true);
+			player.setAdventureStart(p, tp_loc);
+			addAdventureDisplay(p, adventure_aim_loc);
+			title.reset(p);
+			title.setSub(p, "Have fun!");
+			title.send(p, "§cAdventure");
+			msg.prefix(p, "§5Adventure", "To complete your adventure, go to the survival spawn. You cannot teleport. If you die, you start again!");
+		}
+		goto("wait");
+	}
+	if(!player.hasClearInventory(player)) {
+		msg.prefix(player, "§5Adventure", "Your inventory needs to be empty!");
+		goto("wait");
+	}
+	player.teleport(player, tp_loc, false);
+	player.setAdventure(player, true);
+	player.setAdventureStart(player, tp_loc);
+	addAdventureDisplay(player, adventure_aim_loc);
+	title.reset(player);
+	title.setSub(player, "Have fun!");
+	title.send(player, "§cAdventure");
+	msg.prefix(player, "§5Adventure", "To complete your adventure, go to the survival spawn. You cannot teleport. If you die, you start again!");
+	goto("wait");
+}
+player.teleport(player, tp_loc, false);
+goto("wait");
+
+function lottery.set(location, amount) {
+	location = loc.mod(location, 0.5, 0, 0.5);
+	list = living.near(location, 0.1);
+	text_entity = list.getIndex(list, 0);
+	name = entity.getName(text_entity);
+	if(!text.startsWith(name, "Snuvis to win: ", 0)) {
+		snuvi.debug("Lottery error");
+		return;
+	}
+	entity.setName(text_entity, concat("Snuvis to win: ", text.number(amount)), true);
+}
+
+function lottery.add(location, amount) {
+	location = loc.mod(location, 0.5, 0, 0.5);
+	list = living.near(location, 0.1);
+	text_entity = list.getIndex(list, 0);
+	name = entity.getName(text_entity);
+	if(!text.startsWith(name, "Snuvis to win:", 0)) {
+		snuvi.debug("Lottery error");
+		return null;
+	}
+	amount = text.convert(text.subString(name, 15, text.length(name))) + 1;
+	entity.setName(text_entity, concat("Snuvis to win: ", text.number(amount)), true);
+	return amount;
+}
+
+function setDeathLoc(player) {
+	map.add($death_loc_map, player.getUuid(player), entity.getLocation(player));
+}
+
+function getDeathLoc(player) {
+	return map.getOrDefault($death_loc_map, player.getUuid(player), world.getServerSpawn());
+}

+ 19 - 0
survival/trader.txt

@@ -0,0 +1,19 @@
+event.load("entity_click");
+
+msg("dev", text.new("§bTrader §rloaded."));
+@wait
+wait();
+if(event == "entity_click") {
+	entity_name = entity.getName(entity);
+	shop_name = concat(string.text(entity_name), "'s shop");
+	if(string.text(entity_name) == "TestTrader") {
+		shop = shop.new(text.new(shop_name));
+		buy_item = item.custom.new(item.custom.get("GOLD_COIN"), 5);
+		sell_item = item.new(material.get("DIRT"));
+		shop.addOffer(shop, buy_item, sell_item, 999);
+		shop.addOffer(shop, sell_item, buy_item, 999);
+		shop.open(shop, player);
+		goto("wait");
+	}
+}
+goto("wait");

+ 82 - 86
system/chat.txt

@@ -1,23 +1,23 @@
 event.load("chat");
 event.load("player_join");
-event.load("player_logout");
-//event.load("living_death");
+event.load("player_quit");
+event.load("living_death");
 
 cookie_time = 0;
 cookie = item.new(material.get("minecraft:cookie"));
-//serverspawn = world.getServerSpawn();
+serverspawn = world.getServerSpawn();
 
-/*joinmessages = list.new();
-list.add(joinmessages, concat("joined Mundus Crassus."));
-list.add(joinmessages, concat("entered the sick world."));
-list.add(joinmessages, concat("is ready to discover new ores."));
-list.add(joinmessages, concat("turns everything upside down."));
+joinmessages = list.new();
+list.add(joinmessages, string.concat("joined Mundus Crassus."));
+list.add(joinmessages, string.concat("entered the sick world."));
+list.add(joinmessages, string.concat("is ready to discover new ores."));
+list.add(joinmessages, string.concat("turns everything upside down."));
 
 leavemeassages = list.new();
-list.add(leavemeassages, concat("has left Mundus Crassus."));
-list.add(leavemeassages, concat("has left the sick world."));
-list.add(leavemeassages, concat("came, saw and won."));
-list.add(leavemeassages, concat("faded in the face of copper."));
+list.add(leavemeassages, string.concat("has left Mundus Crassus."));
+list.add(leavemeassages, string.concat("has left the sick world."));
+list.add(leavemeassages, string.concat("came, saw and won."));
+list.add(leavemeassages, string.concat("faded in the face of copper."));
 
 colorcodedeath = "§9";
 
@@ -25,40 +25,40 @@ death_prefix = "§0§lx §r";
 rank_playtime_list = list.new();
 
 defaultdeaths = list.new();
-list.add(defaultdeaths, concat(colorcodedeath, " bled out."));
-list.add(defaultdeaths, concat(colorcodedeath, " wanted to die."));
-list.add(defaultdeaths, concat(colorcodedeath, " isn't hungry anymore."));
-list.add(defaultdeaths, concat(colorcodedeath, " f***ing died."));
-list.add(defaultdeaths, concat(colorcodedeath, " now dines with ghosts."));
-list.add(defaultdeaths, concat(colorcodedeath, " visits kajetan in his heaven."));
-list.add(defaultdeaths, concat(colorcodedeath, " is judged by kajetan (god)."));
+list.add(defaultdeaths, string.concat(colorcodedeath, " bled out."));
+list.add(defaultdeaths, string.concat(colorcodedeath, " wanted to die."));
+list.add(defaultdeaths, string.concat(colorcodedeath, " isn't hungry anymore."));
+list.add(defaultdeaths, string.concat(colorcodedeath, " f***ing died."));
+list.add(defaultdeaths, string.concat(colorcodedeath, " now dines with ghosts."));
+list.add(defaultdeaths, string.concat(colorcodedeath, " visits kajetan in his heaven."));
+list.add(defaultdeaths, string.concat(colorcodedeath, " is judged by kajetan (god)."));
 
 drowndeaths = list.new();
-list.add(drowndeaths, concat(colorcodedeath, " drowned."));
-list.add(drowndeaths, concat(colorcodedeath, " drank too much water."));
-list.add(drowndeaths, concat(colorcodedeath, " didn't grow gills fast enough."));
-list.add(drowndeaths, concat(colorcodedeath, " wanted to visit cthulhu."));
-list.add(drowndeaths, concat(colorcodedeath, " forgot they were in survival."));
-list.add(drowndeaths, concat(colorcodedeath, " believed they can fly."));
+list.add(drowndeaths, string.concat(colorcodedeath, " drowned."));
+list.add(drowndeaths, string.concat(colorcodedeath, " drank too much water."));
+list.add(drowndeaths, string.concat(colorcodedeath, " didn't grow gills fast enough."));
+list.add(drowndeaths, string.concat(colorcodedeath, " wanted to visit cthulhu."));
+list.add(drowndeaths, string.concat(colorcodedeath, " forgot they were in survival."));
+list.add(drowndeaths, string.concat(colorcodedeath, " believed they can fly."));
 
 falldeaths = list.new();
-list.add(falldeaths, concat(colorcodedeath, " fell victim to gravitation."));
-list.add(falldeaths, concat(colorcodedeath, " tripped on a banana peal."));
-list.add(falldeaths, concat(colorcodedeath, " jumped into the depths."));
-list.add(falldeaths, concat(colorcodedeath, " jumped into death."));
-list.add(falldeaths, concat(colorcodedeath, " forgot their wings."));
-list.add(falldeaths, concat(colorcodedeath, " forgot their RedBull."));
+list.add(falldeaths, string.concat(colorcodedeath, " fell victim to gravitation."));
+list.add(falldeaths, string.concat(colorcodedeath, " tripped on a banana peal."));
+list.add(falldeaths, string.concat(colorcodedeath, " jumped into the depths."));
+list.add(falldeaths, string.concat(colorcodedeath, " jumped into death."));
+list.add(falldeaths, string.concat(colorcodedeath, " forgot their wings."));
+list.add(falldeaths, string.concat(colorcodedeath, " forgot their RedBull."));
 
 firedeaths = list.new();
-list.add(firedeaths, concat(colorcodedeath, " looks hot today."));
+list.add(firedeaths, string.concat(colorcodedeath, " looks hot today."));
 
 flydeaths = list.new();
-list.add(flydeaths, concat(colorcodedeath, " wanted to be a pilot."));
-list.add(flydeaths, concat(colorcodedeath, " is now a mashed potato."));
-list.add(flydeaths, concat(colorcodedeath, " returns to their nest."));
-list.add(flydeaths, concat(colorcodedeath, " made a crash landing."));
-list.add(flydeaths, concat(colorcodedeath, " needs a flight training."));
-list.add(flydeaths, concat(colorcodedeath, " was cast from heaven."));
+list.add(flydeaths, string.concat(colorcodedeath, " wanted to be a pilot."));
+list.add(flydeaths, string.concat(colorcodedeath, " is now a mashed potato."));
+list.add(flydeaths, string.concat(colorcodedeath, " returns to their nest."));
+list.add(flydeaths, string.concat(colorcodedeath, " made a crash landing."));
+list.add(flydeaths, string.concat(colorcodedeath, " needs a flight training."));
+list.add(flydeaths, string.concat(colorcodedeath, " was cast from heaven."));
 
 //andere damagecauses: fall, outOfWorld, arrow, drown (ertrinken), player, inWall, mob, magic, starve
 causetolist = map.new();
@@ -68,17 +68,17 @@ map.add(causetolist, "inFire", firedeaths);
 map.add(causetolist, "onFire", firedeaths);
 map.add(causetolist, "lava", firedeaths);
 map.add(causetolist, "flyIntoWall", flydeaths);
-map.add(causetolist, "player", list.new());*/
+map.add(causetolist, "player", list.new());
 
-/*online_list = players.toList();
+online_list = players.toList();
 iter = list.iterator(online_list);
 while(hasNext(iter)) {
 	rank.offerTimeScheduled(next(iter));
-}*/
+}
 
-//sgoto(1200, "minute_loop");
+sgoto(1200, "minute_loop");
 	
-msg.text("dev", "§bChat §rloaded");
+msg.string("dev", "§bChat §rloaded");
 @wait
 wait();
 if(event == "living_death") {
@@ -91,7 +91,7 @@ player_name = player.getName(player);
 nickname = player.getNickname(player);
 player_id = player.getId(player);
 //Wenn der Spieler keinen Nicknamen hat, werden die personalisierten Nachrichten geschickt, falls solche vorhanden sind
-if(removeFormat(nickname) == player_name) {
+if(string.removeFormat(nickname) == player_name) {
 	send_personally_messages = true;
 } else {
 	send_personally_messages = false;
@@ -104,81 +104,77 @@ goto("wait");
 first_join = player.isFirstJoin(player_id);
 if(first_join) {
 	entity.teleport(player, serverspawn);
-	msg.text("online", concat(" §d§k# §eWelcome to our sick world §b", player_name, " §e!!! §d§k#"));
+	msg.string("online", string.getSpacer());
+	msg.string("online", string.concat(" §d§k# §eWelcome to our sick world §b", player_name, " §e!!! §d§k#"));
+	msg.string("online", string.getSpacer());
 	player.setFirstJoin(player_id, true);
 }
 player.setHeadName(player);
 silentjoin = player.getSilentJoin(player);
 if(!silentjoin) {
-	message = text.convert(player.getJoinMessage(player));
-	if(message == null || !send_personally_messages) {
-		message = concat("§a§l> §r", fullname, " §9", list.getIndex(joinmessages, math.random(0, list.getSize(joinmessages) - 1)));
+	own_message = player.getJoinMessage(player);
+	if(own_message == null || !send_personally_messages) {
+		message = text.new(string.concat("§a§l> §r", fullname, " §9", list.getIndex(joinmessages, math.random(0, list.getSize(joinmessages) - 1))));
 	} else {
-		message = concat("§a§l> §r", fullname, " §9", message);
+		message = text.new(string.concat("§a§l> §r", fullname, " §9", own_message));
 	}
-	msg.text("online", message);
 }
-
 player_loc = entity.getLocation(player);
 //Inventory
-inv.loadFromPlayer(player, player, loc.getWorld(player_loc));
-//Keks geben, wenn man als einziger Spieler auf den Server joint und im Survival-Mode ist und der letzte Keks seit 5 Minuten vergeben wurde
+//inv.loadFromPlayer(player, player, loc.getWorld(player_loc));
+//Keks geben, wenn man als einziger Spieler auf den Server joint und im Survival-Mode ist und der letzte Keks vor 5 Minuten vergeben wurde
 if(players.getAmount() == 1) {
 	if(!loc.isInGamesWorld(player_loc)) {
 		if(player.isSurvival(player)) {
 			now_time = time.getMillis();
 			if(now_time - cookie_time > 300000) {
 				cookie_time = now_time;
-				msg.text(player, "§dHere is a cookie for you :D");
+				msg.string(player, "§dHere is a cookie for you :D");
 				player.safeGiveItem(player, cookie);
 			}
 		}
 	}
 }
 player.setTabName(player);
-player.greet(player);
-player.showDefaultStacks(player);
-stacks.setActive(player, true);
+//player.greet(player);
 rank.offerTimeScheduled(player);
-displayMoney(player, getMoney(player));
-//send marvinius and sirterence amount of errors
-if(player_id == 2 || player_id == 35) {
+//displayMoney(player, getMoney(player));
+if(perm.has("isDev", player)) {
 	error_size = error.getSize();
 	if(error_size > 0) {
-		msg.prefix(player, "§cError", concat("There are ", text.number(error_size), " errors."));
+		msg.prefix(player, "§cError", string.concat("There are ", string.number(error_size), " errors."));
 	}
 }
 goto("wait");
 
-@player_logout
-message = text.convert(player.getLeaveMessage(player));
+@player_quit
+message = player.getLeaveMessage(player);
 if(message == null || !send_personally_messages) {
-	message = concat("§c§l> §r", fullname, " §9", list.getIndex(leavemeassages, math.random(0, list.getSize(leavemeassages) - 1)));
+	message = text.new(string.concat("§c§l> §r", fullname, " §9", list.getIndex(leavemeassages, math.random(0, list.getSize(leavemeassages) - 1))));
 } else {
-	message = concat("§c§l> §r", fullname, " §9", message);
+	message = text.new(string.concat("§c§l> §r", fullname, " §9", message));
 }
-msg.text("online", message);
-inv.saveForPlayer(player, player, loc.getWorld(entity.getLocation(player)));
+//inv.saveForPlayer(player, player, loc.getWorld(entity.getLocation(player)));
 player.clearBackPos(player);
 rank.removeTimeOffert(player);
 goto("wait");
 
 @chat
-if(text.startsWith(message, "%", 0)) {
+if(string.startsWith(message, "%", 0)) {
 	cancel = true;
 	goto("wait");
 }
-if(text.startsWith(message, "7", 0)) {
-	length = text.length(message);
-	space_index = read.number(text.indexOf(message, " ", 1));
+if(string.startsWith(message, "7", 0)) {
+	length = string.length(message);
+	space_index = read.number(string.indexOf(message, " ", 1));
 	if(length > 1 && space_index == -1 || length > 1 && space_index > 1) {
 		cancel = true;
 		if(space_index == -1) {
-			word = text.subString(message, 1, length);
+			word = string.subString(message, 1, length);
 		} else {
-			word = text.subString(message, 1, space_index);
+			word = string.subString(message, 1, space_index);
 		}
-		msg.prefix(player, "§6Commands", concat("You meant /", word, "?"));
+		msg.prefix(player, "§6Commands", string.concat("You meant /", word, "?"));
 		goto("wait");
 	}
 }
@@ -187,11 +183,11 @@ if(player.isMuted(player)) {
 	msg.prefix(player, "§6Commands", "You are muted.");
 	goto("wait");
 }
-if(perm.has(player, "color")) {
-	message = text.replace(message, "&", "§");
+if(perm.has("color", player)) {
+	//message = string.replace(message, "&", "§");
 }
-if(text.startsWith(message, "https://", 0)) {
-	message = text.link(message, message);
+if(string.startsWith(message, "https://", 0)) {
+	message = string.getLinkText(message, message);
 }
 msg.chat(player, message);
 goto("wait");
@@ -212,19 +208,19 @@ if(damage_type == "player") {
 	killer_name = player.getName(killer);
 	item = living.getEquip(killer, "hand");
 	if(item.hasName(item)) {
-		message1 = concat(death_prefix, fullname, colorcodedeath, " killed by ", killer_name, " with ");
+		message1 = string.concat(death_prefix, fullname, colorcodedeath, " killed by ", killer_name, " with ");
 		message2 = item.getFullText(item);
-		message = text.concat2(message1, message2);
+		//message = text.concat2(message1, message2);
 	} else {
 		list.clear(list);
-		list.add(list, concat(death_prefix, fullname, colorcodedeath, " got their last honour from ", killer_name, "."));
-		list.add(list, concat(death_prefix, fullname, colorcodedeath, " died by ", killer_name, "'s hand."));
-		list.add(list, concat(death_prefix, fullname, colorcodedeath, " was killed by ", killer_name, "."));
-		list.add(list, concat(death_prefix, fullname, colorcodedeath, " lost a bet to ", killer_name, "."));
+		list.add(list, string.concat(death_prefix, fullname, colorcodedeath, " got their last honour from ", killer_name, "."));
+		list.add(list, string.concat(death_prefix, fullname, colorcodedeath, " died by ", killer_name, "'s hand."));
+		list.add(list, string.concat(death_prefix, fullname, colorcodedeath, " was killed by ", killer_name, "."));
+		list.add(list, string.concat(death_prefix, fullname, colorcodedeath, " lost a bet to ", killer_name, "."));
 		message = list.getIndex(list, math.random(0, list.getSize(list) - 1));
 	}
 } else {
-	message = concat(death_prefix, fullname, list.getIndex(list, math.random(0, list.getSize(list) - 1)));
+	message = string.concat(death_prefix, fullname, list.getIndex(list, math.random(0, list.getSize(list) - 1)));
 }
 msg.survival(message);
 msg.creative(message);
@@ -234,7 +230,7 @@ goto("wait");
 function player.greet(player) {
 	player_name = player.getName(player);
 	title.reset(player);
-	title.setSub(player, concat("§cNice to see you §6", player_name));
+	title.setSub(player, string.concat("§cNice to see you §6", player_name));
 	title.send(player, "");
 }
 

+ 488 - 0
system/chestshops.txt

@@ -0,0 +1,488 @@
+event.load("custom_command");
+event.load("inv_click");
+event.load("inv_close");
+event.load("block_click");
+
+prefix_shop = "§6Shop";
+wall_signs_tag = block.getTag("minecraft:wall_signs");
+invid_to_sign_loc = map.new();
+
+msg.text("dev", "§bChestShops §rloaded.");
+@wait
+wait();
+ignoreGoto(event);
+goto("wait");
+
+@inv_click
+if(inv_slot == 10) {
+	map.remove(invid_to_sign_loc, inv_id);
+	inv.close(player);
+	goto("wait");
+}
+sign_loc = map.get(invid_to_sign_loc, inv_id);
+if(sign_loc == null) {
+	inv.close(player);
+	msg.prefix(player, prefix_shop, "Defect shop.");
+	goto("wait");
+}
+if(!isAWallSign(sign_loc)) {
+	map.remove(invid_to_sign_loc, inv_id);
+	inv.close(player);
+	msg.prefix(player, prefix_shop, "No longer a shop.");
+	goto("wait");
+}
+factor = 1;
+if(click_type == "QUICK_MOVE") {
+	factor = 8;
+}
+adminshop = isAdminShop(sign_loc);
+buy_price = shop.getBuyPrice(inv) * factor;
+sell_price = shop.getSellPrice(inv) * factor;
+chestloc1 = loc.mod(sign_loc, 0, -1, 0);
+chestloc2 = block.getSecChest(chestloc1);
+if(!isAChest(chestloc1)) {
+	map.remove(invid_to_sign_loc, inv_id);
+	inv.close(player);
+	msg.prefix(player, prefix_shop, "No longer a shop.");
+	goto("wait");
+}
+if(inv_slot == 3) { //Buy
+	itemstack = inv.getItem(inv, 4);
+	itemstack_2 = item.clone(itemstack);
+	if(click_type == "QUICK_MOVE") {
+		item.setAmount(itemstack_2, item.getAmount(itemstack_2) * factor);
+	}
+	//Check players money
+	if(!hasEnoughMoney(player, buy_price)) {
+		msg.prefix(player, prefix_shop, "You do not have enough money.");
+		goto("wait");
+	}
+	if(!adminshop) {
+		itemamount2 = 0;
+		if(chestloc2 != null) {
+			itemamount2 = block.getItemAmount(chestloc2, true, itemstack);
+		}
+		itemamount1 = block.getItemAmount(chestloc1, true, itemstack);
+		if(itemamount1 + itemamount2 < item.getAmount(itemstack_2)) {
+			msg.prefix(player, prefix_shop, "Not enough items in chest.");
+			goto("wait");
+		}
+	}
+	//Items ins Inventar geben oder droppen
+	notgiven = player.giveItem(player, itemstack_2);
+	if(notgiven != null) {
+		item.drop(entity.getLocation(player), notgiven);
+	}
+	//In einem AdminShop werden keine Items abgelegt
+	if(!adminshop) {
+		itemstack_temp = item.clone(itemstack_2);
+		notremoved = block.subItem(chestloc1, itemstack_temp);
+		if(chestloc2 != null) {
+			block.subItem(chestloc2, notremoved);
+		}
+		owner_player_id = text.convert(block.getSign(sign_loc, 3));
+		if(!isDouble(owner_player_id)) {
+			msg.prefix(player, prefix_shop, "Invalid shop owner.");
+			goto("wait");
+		}
+		if(player.getNameFromId(owner_player_id) == null) {
+			msg.prefix(player, prefix_shop, "Invalid shop owner.");
+			goto("wait");
+		}
+		addMoney(owner_player_id, buy_price);
+	}
+	subMoney(player, buy_price);
+	inv.update(player);
+}  elseif(inv_slot == 6) { //Sell
+	itemstack = inv.getItem(inv, 5);
+	itemstack_2 = item.clone(itemstack);
+	if(click_type == "QUICK_MOVE") {
+		item.setAmount(itemstack_2, item.getAmount(itemstack_2) * factor);
+	}
+	if(!adminshop) {
+		owner_player_id = text.convert(block.getSign(sign_loc, 3));
+		if(!isDouble(owner_player_id)) {
+			msg.prefix(player, prefix_shop, "Invalid shop owner.");
+			goto("wait");
+		}
+		if(player.getNameFromId(owner_player_id) == null) {
+			msg.prefix(player, prefix_shop, "Invalid shop owner.");
+			goto("wait");
+		}
+		if(!hasEnoughMoney(owner_player_id, sell_price)) {
+			msg.prefix(player, prefix_shop, "Shop owner does not have enough money.");
+			goto("wait");
+		}
+	}
+	//Items des Spielers checken
+	if(player.getItemAmount(player, true, itemstack) < item.getAmount(itemstack_2)) {
+		msg.prefix(player, prefix_shop, "You do not have enough items.");
+		goto("wait");
+	}
+	//Platz in der Kiste checken
+	if(!adminshop) {
+		//Versuche den ganzen ItemStack in der 1.Kiste unterzubringen
+		itemstack_temp = item.clone(itemstack_2);
+		notinchest1 = block.addItem(chestloc1, itemstack_temp);
+		if(item.getType(notinchest1) != "minecraft:air") {
+			//Versuche den Rest des ItemStack in der 2.Kiste unterzubringen
+			notinchest2 = block.addItem(chestloc2, notinchest1);
+			if(item.getType(notinchest1) != "minecraft:air") {
+				//Entferne die ItemStacks wieder
+				msg.prefix(player, prefix_shop, "Not enough space in chest.");
+				block.subItem(chestloc1, itemstack_temp);
+				block.addItem(chestloc1, notinchest2);
+				goto("wait");
+			}
+		}
+		subMoney(owner_player_id, sell_price);
+	}
+	addMoney(player, sell_price);
+	player.removeItem(player, itemstack_2);
+	inv.update(player);
+}
+goto("wait");
+
+@inv_close
+map.remove(invid_to_sign_loc, inv_id);
+goto("wait");
+
+@custom_command
+if(!isPlayer(sender)) {
+	goto("wait");
+}
+player = sender;
+if(command == "shop") {
+	size = list.getSize(args);
+	if(size == 0) {
+		@syntax
+		msg.prefix(player, prefix_shop, "/shop ...");
+		msg.text(player, "§6 - create §rCreates a shop");
+		msg.text(player, "§6 - buy <amount> <price> §rSet buy settings");
+		msg.text(player, "§6 - sell <amount> <price> §rSet sell settings");
+		msg.text(player, "§6 - remove <buy/sell> §rRemove settings");
+		if(perm.has("adminshop", player)) {
+			msg.text(player, "§6 - admin §rSet to adminshop");
+		}
+		goto("wait");
+	}
+	arg0 = text.toLowerCase(list.getIndex(args, 0));
+	if(arg0 == "create") {
+		if(size != 1) {
+			msg.prefix(player, prefix_shop, "§6/shop create");
+			goto("wait");
+		}
+		sign_loc = player.getTarget(player, 5, false, false);
+		if(!isAWallSign(sign_loc)) {
+			msg.prefix(player, prefix_shop, "Look at a sign.");
+			goto("wait");
+		}
+		chest_loc = loc.mod(sign_loc, 0, -1, 0);
+		if(!isAChest(chest_loc)) {
+			msg.prefix(player, prefix_shop, "No chest under sign.");
+			goto("wait");
+		}
+		if(!plot.check(sign_loc, player, 0, false)) {
+			msg.prefix(player, prefix_shop, "Not your plot.");
+			goto("wait");
+		}
+		block.setSign(sign_loc, 0, "[Shop]");
+		block.setSign(sign_loc, 3, text.number(player.getId(player)));
+		msg.prefix(player, prefix_shop, "§rCreated Shop.");
+		goto("wait");
+	}
+	if(arg0 == "admin") {
+		if(!perm.has("adminshop", player)) {
+			msg.prefix(player, prefix_shop, "§6No Permission.");
+			goto("wait");
+		}
+		if(size != 1) {
+			msg.prefix(player, prefix_shop, "§6/shop admin");
+			goto("wait");
+		}
+		sign_loc = player.getTarget(player, 5, false, false);
+		if(!isAWallSign(sign_loc)) {
+			msg.prefix(player, prefix_shop, "Look at a sign.");
+			goto("wait");
+		}
+		chest_loc = loc.mod(sign_loc, 0, -1, 0);
+		if(!isAChest(chest_loc)) {
+			msg.prefix(player, prefix_shop, "No chest under sign.");
+			goto("wait");
+		}
+		block.setSign(sign_loc, 0, "[Admin Shop]");
+		block.setSign(sign_loc, 3, "");
+		msg.prefix(player, prefix_shop, "§rCreated Admin Shop.");
+		goto("wait");
+	}
+	if(arg0 == "buy" || arg0 == "sell") {
+		if(size != 3) {
+			msg.prefix(player, prefix_shop, concat("§6/shop ", arg0, " <amount> <price>"));
+			goto("wait");
+		}
+		amount = list.getIndex(args, 1);
+		price = list.getIndex(args, 2);
+		if(!isDouble(amount) || !isDouble(amount)) {
+			msg.prefix(player, prefix_shop, "§rNumber expected.");
+			goto("wait");
+		}
+		if(price < 0) {
+			msg.prefix(player, prefix_shop, "§rPositive number expected.");
+			goto("wait");
+		}
+		sign_loc = player.getTarget(player, 5, false, false);
+		if(!isAWallSign(sign_loc)) {
+			msg.prefix(player, prefix_shop, "Look at a sign.");
+			goto("wait");
+		}
+		chest_loc = loc.mod(sign_loc, 0, -1, 0);
+		if(!isAChest(chest_loc)) {
+			msg.prefix(player, prefix_shop, "No chest under sign.");
+			goto("wait");
+		}
+		if(!shop.isOwner(player, sign_loc)) {
+			msg.prefix(player, prefix_shop, "You are not the owner.");
+			goto("wait");
+		}
+		if(arg0 == "buy") {
+			block.setSign(sign_loc, 1, concat("Buy ", text.number(amount), " for ", text.number(price)));
+		} else {
+			block.setSign(sign_loc, 2, concat("Sell ", text.number(amount), " for ", text.number(price)));
+		}
+		msg.prefix(player, prefix_shop, "§rPrice set.");
+		goto("wait");
+	}
+	if(arg0 == "remove") {
+		if(size != 2) {
+			msg.prefix(player, prefix_shop, concat("§6/shop remove <buy/sell>"));
+			goto("wait");
+		}
+		sign_loc = player.getTarget(player, 5, false, false);
+		if(!isAWallSign(sign_loc)) {
+			msg.prefix(player, prefix_shop, "Look at a sign.");
+			goto("wait");
+		}
+		chest_loc = loc.mod(sign_loc, 0, -1, 0);
+		if(!isAChest(chest_loc)) {
+			msg.prefix(player, prefix_shop, "No chest under sign.");
+			goto("wait");
+		}
+		if(!shop.isOwner(player, sign_loc)) {
+			msg.prefix(player, prefix_shop, "You are not the owner.");
+			goto("wait");
+		}
+		arg1 = text.toLowerCase(list.getIndex(args, 1));
+		if(arg1 == "buy") {
+			block.setSign(sign_loc, 1, "");
+		} elseif(arg1 == "sell") {
+			block.setSign(sign_loc, 2, "");
+		} else {
+			msg.prefix(player, prefix_shop, concat("§6/shop remove <buy/sell>"));
+			goto("wait");
+		}
+		msg.prefix(player, prefix_shop, "§rPrice removed.");
+		goto("wait");
+	}
+	goto("syntax");
+}
+goto("wait");
+
+@block_click
+if(block == null) {
+	goto("wait");
+}
+if(isAChest(block_loc)) {
+	chest_loc = block_loc;
+	sign_loc = loc.mod(chest_loc, 0, 1, 0);
+	if(!isAWallSign(sign_loc)) {
+		chest_loc = block.getSecChest(chest_loc);
+		if(chest_loc == null) {
+			goto("wait");
+		}
+		sign_loc = loc.mod(chest_loc, 0, 1, 0);
+		if(!isAWallSign(sign_loc)) {
+			goto("wait");
+		}
+	}
+	line0 = block.getSign(sign_loc, 0);
+	if(line0 != "[Shop]" && line0 != "[Admin Shop]") {
+		goto("wait");
+	}
+	if(shop.isOwner(player, sign_loc)) {
+		goto("wait");
+	}
+	if(perm.has("plot.bypass", player)) {
+		goto("wait");
+	}
+	cancel = true;
+	goto("wait");
+}
+if(isAWallSign(block_loc)) {
+	sign_loc = block_loc;
+	chest_loc = loc.mod(sign_loc, 0, -1, 0);
+	if(!isAChest(chest_loc)) {
+		goto("wait");
+	}
+	line0 = block.getSign(sign_loc, 0);
+	if(line0 != "[Shop]" && line0 != "[Admin Shop]") {
+		goto("wait");
+	}
+	buy_line = block.getSign(sign_loc, 1);
+	sell_line = block.getSign(sign_loc, 2);
+	owner_player_id = text.convert(block.getSign(sign_loc, 3));
+	if(isDouble(owner_player_id)) {
+		owner_name = player.getNameFromId(owner_player_id);
+		if(owner_name == null) {
+			msg.prefix(player, prefix_shop, "Invalid shop owner.");
+			goto("wait");
+		}
+		inv_title = concat("§8Shop von ", owner_name);
+	} elseif(owner_player_id == "") {
+		inv_title = "Admin Shop";
+	} else {
+		msg.prefix(player, prefix_shop, "Invalid shop owner.");
+		goto("wait");
+	}
+	item_stack = shop.getItem(chest_loc);
+	if(item_stack == null) {
+		buy_line = "";
+		sell_line = "";
+	}
+	inv = inv.new("222320000002322203");
+	if(buy_line != "") {
+		split_list = text.split(" ", buy_line);
+		buy_amount = list.getIndex(split_list, 1);
+		if(!isDouble(buy_amount)) {
+			msg.prefix(player, prefix_shop, "Invalid buy amount.");
+			goto("wait");
+		}
+		buy_amount = read.number(buy_amount);
+		buy_price = list.getIndex(split_list, 3);
+		if(!isDouble(buy_price)) {
+			msg.prefix(player, prefix_shop, "Invalid buy price.");
+			goto("wait");
+		}
+		buy_price = read.number(buy_price);
+		buy_stack = item.clone(item_stack);
+		item.setAmount(buy_stack, buy_amount);
+		a = money.split(buy_price);
+		gold = a[0];
+		silver = a[1];
+		bronze = a[2];
+		index = 2;
+		if(bronze != 0) {
+			inv.setItem(inv, index--, read.item("km:coin_copper", bronze));
+		}
+		if(silver != 0) {
+			inv.setItem(inv, index--, read.item("km:coin_silver", silver));
+		}
+		if(gold != 0) {
+			inv.setItem(inv, index, read.item("km:coin_gold", gold));
+		}
+		inv.setItem(inv, 3, read.item("km:arrow_right", 1, "§rBuy"));
+		inv.setItem(inv, 4, buy_stack);
+	}
+	if(sell_line != "") {
+		split_list = text.split(" ", sell_line);
+		sell_amount = list.getIndex(split_list, 1);
+		if(!isDouble(sell_amount)) {
+			msg.prefix(player, prefix_shop, "Invalid buy amount.");
+			goto("wait");
+		}
+		sell_amount = read.number(sell_amount);
+		sell_price = list.getIndex(split_list, 3);
+		if(!isDouble(sell_price)) {
+			msg.prefix(player, prefix_shop, "Invalid buy price.");
+			goto("wait");
+		}
+		sell_price = read.number(sell_price);
+		sell_stack = item.clone(item_stack);
+		item.setAmount(sell_stack, sell_amount);
+		a = money.split(sell_price);
+		gold = a[0];
+		silver = a[1];
+		bronze = a[2];
+		inv.setItem(inv, 5, sell_stack);
+		inv.setItem(inv, 6, read.item("km:arrow_right", 1, "§rSell"));
+		index = 7;
+		if(bronze != 0) {
+			inv.setItem(inv, index++, read.item("km:coin_copper", bronze));
+		}
+		if(silver != 0) {
+			inv.setItem(inv, index++, read.item("km:coin_silver", silver));
+		}
+		if(gold != 0) {
+			inv.setItem(inv, index, read.item("km:coin_gold", gold));
+		}
+	}
+	inv.setItem(inv, 10, read.item("km:cross_red", 1, "§rCancel"));
+	inv.open(inv, player, inv_title);
+	map.add(invid_to_sign_loc, inv.getId(inv), sign_loc);
+}
+goto("wait");
+
+function shop.getItem(chest_loc) {
+	inv = block.getInv(chest_loc);
+	for(i = 0; i < inv.getSize(inv); i++) {
+		item_stack = item.clone(inv.getItem(inv, i));
+		if(item.getType(item_stack) != "minecraft:air") {
+			return item_stack;
+		}
+	}
+	return null;
+}
+
+function isAChest(location) {
+	return block.getType(location) == "minecraft:chest";
+}
+
+function isAWallSign(location) {
+	if(location == null) {
+		return false;
+	}
+	return block.hasTag($wall_signs_tag, block.get(location));
+}
+
+function shop.isOwner(player, sign_loc) {
+	owner_player_id = text.convert(block.getSign(sign_loc, 3));
+	if(owner_player_id == "") {
+		return perm.has("adminshop", player);
+	}
+	if(isDouble(owner_player_id)) {
+		owner_name = player.getNameFromId(owner_player_id);
+		if(owner_name == null) {
+			return false;
+		}
+		return owner_player_id == player.getId(player);
+	}
+	return false;
+}
+
+function shop.getItemAmount(item) {
+	if(item.getType(item) == "km:coin_gold") {
+		return item.getAmount(item) * 64 * 64;
+	}
+	if(item.getType(item) == "km:coin_silver") {
+		return item.getAmount(item) * 64;
+	}
+	if(item.getType(item) == "km:coin_copper") {
+		return item.getAmount(item);
+	}
+	return 0;
+}
+
+function shop.getBuyPrice(inv) {
+	snuvis = 0;
+	snuvis += shop.getItemAmount(inv.getItem(inv, 0));
+	snuvis += shop.getItemAmount(inv.getItem(inv, 1));
+	snuvis += shop.getItemAmount(inv.getItem(inv, 2));
+	return snuvis;
+}
+
+function shop.getSellPrice(inv) {
+	snuvis = 0;
+	snuvis += shop.getItemAmount(inv.getItem(inv, 7));
+	snuvis += shop.getItemAmount(inv.getItem(inv, 8));
+	snuvis += shop.getItemAmount(inv.getItem(inv, 9));
+	return snuvis;
+}

File diff suppressed because it is too large
+ 210 - 196
system/commands.txt


+ 230 - 0
system/copyisland.txt

@@ -0,0 +1,230 @@
+event.load("block_click");
+event.load("block_break");
+event.load("custom_command");
+
+mark_item_type = "GOLDEN_SHOVEL";
+air_material = material.getAir();
+
+msg.string("dev", "§bCopyisland §rloaded.");
+@main
+wait();
+ignoreGoto(event);
+goto("main");
+
+@block_break
+if(player.checkHandForType(player, mark_item_type)) {
+	if(perm.has("copyisland", player)) {
+		if(!isTheCloningPlayer(player.getId(player))) {
+			goto("main");
+		}
+		cancel = true;
+	}
+}
+goto("main");
+
+@block_click
+if(block == null) {
+	goto("main");
+}
+if(player.checkHandForType(player, mark_item_type)) {
+	if(perm.has("copyisland", player)) {
+		player_id = player.getId(player);
+		if(!isTheCloningPlayer(player_id)) {
+			goto("main");
+		}
+		if(action == "LEFT_CLICK_BLOCK") {
+			setPos1(player_id, block_loc);
+		} elseif(action == "RIGHT_CLICK_BLOCK") {
+			setPos2(player_id, block_loc);
+		}
+	}
+}
+goto("main");
+
+@custom_command
+if(command == "copyisland" || command == "ci") {
+	if(!isPlayer(sender)) {
+		goto("main");
+	}
+	player = sender;
+	if(!perm.has("copyisland", player)) {
+		goto("main");
+	}
+	size = list.getSize(args);
+	if(size == 0) {
+		msg.prefix(player, "§3CopyIsland", "/copyisland");
+		msg.string(player, "§3 - copy §rSpeichert die Player-Location relativ zur Auswahl");
+		msg.string(player, "§3 - paste §rKopiert relativ zur Location, an der 'copy' ausgeführt wurde");
+		msg.string(player, "§3 - pos1 §rSetzt Pos1 auf deine aktuelle Position");
+		msg.string(player, "§3 - pos2 §rSetzt Pos2 auf deine aktuelle Position");
+		goto("main");
+	}
+	arg0 = list.getIndex(args, 0);
+	player_id = player.getId(player);
+	if(!isTheCloningPlayer(player_id)) {
+		msg.prefix(player, "§3CopyIsland", concat("Copyisland wird von ", player.getNameFromId(cloningplayer), " verwendet."));
+		goto("main");
+	}
+	if(arg0 == "pos1") {
+		location = entity.getLocation(player);
+		setPos1(player_id, location);
+		goto("main");
+	}
+	if(arg0 == "pos2") {
+		location = entity.getLocation(player);
+		setPos2(player_id, location);
+		goto("main");
+	}
+	if(arg0 == "air") {
+		if(world1 == null || world2 == null) {
+			msg.prefix(player, "§3CopyIsland", "Auswahl inkorrekt.");
+			goto("main");
+		}
+		loc.sort(location1, location2);
+		x1 = loc.getBlockX(location1);
+		y1 = loc.getBlockY(location1);
+		z1 = loc.getBlockZ(location1);
+		x2 = loc.getBlockX(location2);
+		y2 = loc.getBlockY(location2);
+		z2 = loc.getBlockZ(location2);
+		
+		loc = loc.new(world1, x1, y1, z1); //Start-Location
+		x_length = x2 - x1 + 1; //Kantenlänge x-Achse
+		y_length = y2 - y1 + 1; //Kantenlänge y-Achse
+		z_length = z2 - z1 + 1; //Kantenlänge z-Achse
+		
+		//Zeitberechnung
+		volume = x_length * y_length * z_length; //Volumen des ausgewählten Bereichs (oder Anzahl der Blöcke)
+		calc_time = math.round((volume / 30000) * 1.633);
+		msg.prefix(player, "§3CopyIsland", concat("§r", string.number(volume), " §eBlöcke werden gesetzt."));
+		msg.prefix(player, "§3CopyIsland", concat("§3Geschätzte Dauer: §r", string.number(calc_time), "§e Sekunden."));
+		start_time = time.getMillis();
+
+		x1 = math.roundDown(x1 / 16) * 16;
+		z1 = math.roundDown(z1 / 16) * 16;
+		x2 = math.roundDown(x2 / 16) * 16;
+		z2 = math.roundDown(z2 / 16) * 16;
+
+		counter = 0;
+		for(cx = x1; cx <= x2; cx += 16) {
+			for(cz = z1; cz <= z2; cz += 16) {
+				for(y = y2; y >= y1; y--) {
+					loc.setY(loc, y);
+					for(x = 0; x < 16; x++) {
+						loc.setX(loc, x + cx);
+						for(z = 0; z < 16; z++) {
+							loc.setZ(loc, z + cz);
+							block.setMaterial(loc, air_material);
+							counter++;
+						}
+					}
+				}
+			}
+		}
+
+		msg.prefix(player, "§3CopyIsland", concat("§3Done: §r", string.number(counter), "§e blocks affected."));
+		end_time = time.getMillis();
+		msg.prefix(player, "§3CopyIsland", concat("§3Benötigte Zeit: §r", string.number(math.round(((end_time - start_time) / 1000))), "§e Sekunden."));
+		cloningplayer = null;
+		world1 = null;
+		world2 = null;
+		goto("main");
+	}
+	if(arg0 == "copy") {
+		if(world1 == null || world2 == null) {
+			msg.prefix(player, "§3CopyIsland", "Auswahl inkorrekt.");
+			goto("main");
+		}
+		from_loc = entity.getLocation(player);
+		msg.prefix(player, "§3CopyIsland", "§rBereit zum Kopieren.");
+		goto("main");
+	}
+	if(arg0 == "paste") {
+		if(world1 == null || world2 == null) {
+			msg.prefix(player, "§3CopyIsland", "Auswahl inkorrekt.");
+			goto("main");
+		}
+		if(from_loc == null) {
+			msg.prefix(player, "§3CopyIsland", "Zuerst die Location relativ zur Auswahl setzen /ci copy.");
+			goto("main");
+		}
+		loc.sort(location1, location2);
+		x1 = loc.getBlockX(location1);
+		y1 = loc.getBlockY(location1);
+		z1 = loc.getBlockZ(location1);
+		x2 = loc.getBlockX(location2);
+		y2 = loc.getBlockY(location2);
+		z2 = loc.getBlockZ(location2);
+
+		copy_from = loc.new(world1, x1, y1, z1); //Von hier wird der 1.Block kopiert
+		x_length = x2 - x1 + 1; //Kantenlänge x-Achse
+		y_length = y2 - y1 + 1; //Kantenlänge y-Achse
+		z_length = z2 - z1 + 1; //Kantenlänge z-Achse
+		
+		//Zeitberechnung
+		volume = x_length * y_length * z_length; //Volumen des ausgewählten Bereichs (oder Anzahl der Blöcke)
+		calc_time = math.round((volume / 30000) * 1.633);
+		msg.prefix(player, "§3CopyIsland", concat("§r", string.number(volume), " §eBlöcke werden kopiert."));
+		msg.prefix(player, "§3CopyIsland", concat("§3Geschätzte Dauer: §r", string.number(calc_time), "§e Sekunden."));
+		start_time = time.getMillis();
+
+		//Distanzen zwischen Spieler-Loc von /copy und 1.Block der kopiert wird
+		x_distance1 = x1 - loc.getBlockX(from_loc);
+		y_distance1 = y1 - loc.getBlockY(from_loc);
+		z_distance1 = z1 - loc.getBlockZ(from_loc);
+
+		//Berechnung wohin der 1.Block gesetzt wird (Spieler-Loc von /paste + Distanzen s.o.)
+		player_loc = entity.getLocation(player); //Paste-Location des Spielers
+		world_copy_to = loc.getWorld(player_loc);
+		x_copy_to = x_distance1 + loc.getBlockX(player_loc);
+		y_copy_to = y_distance1 + loc.getBlockY(player_loc);
+		z_copy_to = z_distance1 + loc.getBlockZ(player_loc);
+		copy_to = loc.new(world_copy_to, x_copy_to, y_copy_to, z_copy_to); //Hier wird der 1.Block gesetzt
+		
+		counter = 0;
+		for(x = 0; x < x_length; x++) {
+			for(y = 0; y < y_length; y++) {
+				for(z = 0; z < z_length; z++) {
+					loc.add(copy_from, x, y, z);
+					loc.add(copy_to, x, y, z);
+					block.clone(block.get(copy_from), copy_to);
+					counter++;
+				}
+			}
+		}
+		
+		msg.prefix(player, "§3CopyIsland", concat("§3Done: §r", string.number(counter), "§e blocks affected."));
+		end_time = time.getMillis();
+		msg.prefix(player, "§3CopyIsland", concat("§3Benötigte Zeit: §r", string.number(math.round(((end_time - start_time) / 1000))), "§e Sekunden."));
+		cloningplayer = null;
+		world1 = null;
+		world2 = null;
+		from_loc = null;
+		goto("main");
+	}
+}
+goto("main");
+	
+function setPos1(player_id, location) {
+	x1 = string.number(loc.getBlockX(location));
+	y1 = string.number(loc.getBlockY(location));
+	z1 = string.number(loc.getBlockZ(location));
+	$world1 = loc.getWorld(location);
+	msg.prefix($player, "§3CopyIsland", concat("§3Pos1: ", $x1, ", ", y1, ", ", z1)); 
+}
+
+function setPos2(player_id, location) {
+	x1 = string.number(loc.getBlockX(location));
+	y1 = string.number(loc.getBlockY(location));
+	z1 = string.number(loc.getBlockZ(location));
+	$world2 = loc.getWorld(location);
+	msg.prefix($player, "§3CopyIsland", concat("§3Pos2: ", x2, ", ", y2, ", ", z2)); 
+}
+
+function isTheCloningPlayer(player_id) {
+	if($cloningplayer == null) {
+		$cloningplayer = player_id;
+		return true;
+	}
+	return player_id == $cloningplayer;
+}

+ 123 - 0
system/damage.txt

@@ -0,0 +1,123 @@
+event.load("animal_tame");
+event.load("living_hurt");
+event.load("living_heal");
+event.load("entity_join");
+
+entities_list = list.new();
+
+permanent_name = set.new();
+set.add(permanent_name, "villager");
+set.add(permanent_name, "wandering_trader");
+
+permanent_tamed_name = set.new();
+set.add(permanent_tamed_name, "wolf");
+set.add(permanent_tamed_name, "cat");
+set.add(permanent_tamed_name, "horse");
+set.add(permanent_tamed_name, "donkey");
+set.add(permanent_tamed_name, "mule");
+set.add(permanent_tamed_name, "skeleton_horse");
+set.add(permanent_tamed_name, "zombie_horse");
+set.add(permanent_tamed_name, "parrot");
+
+msg("dev", "§bDamage §rloaded.");
+@wait
+wait();
+ignoreGoto(event);
+goto("wait");
+
+@animal_tame
+if(isLiving(animal) && !isPlayer(animal)) {
+	if(list.getSize(entities_list) == 0) {
+		sgoto(1, "sgoto_updateEntityName");
+	}
+	list.add(entities_list, animal);
+}
+goto("wait");
+
+@entity_join
+if(isLiving(entity) && !isPlayer(entity)) {
+	updateEntityName(entity);
+}
+goto("wait");
+
+@living_heal
+cancel = true;
+if(heal_amount <= 0) {
+	goto("wait");
+}
+health = living.getHealth(living_entity);
+if(health <= 0) {
+	goto("wait");
+}
+new_health = health + heal_amount;
+living.setHealth(living_entity, new_health);
+if(isLiving(living_entity) && !isPlayer(living_entity)) {
+	updateEntityName(living_entity);
+}
+goto("wait");
+
+@living_hurt
+if(isPlayer(living_entity) || !isLiving(living_entity)) {
+	goto("wait");
+}
+if(list.getSize(entities_list) == 0) {
+	sgoto(1, "sgoto_updateEntityName");
+}
+list.add(entities_list, living_entity);
+goto("wait");
+
+@sgoto_updateEntityName
+iter = list.iterator(entities_list);
+while(hasNext(iter)) {
+	updateEntityName(next(iter));
+}
+list.clear(entities_list);
+goto("wait");
+
+function updateEntityName(living_entity) {
+	if(!isLiving(living_entity)) {
+		return;
+	}
+	entity_type = entity.getType(living_entity);
+	if(entity_type == "nobody" || entity_type == "armor_stand" || entity_type == "human") {
+		return;
+	}
+
+	entity_name = entity.getName(living_entity);
+	max_health = living.getMaxHealth(living_entity);
+	health = text.number(math.round(living.getHealth(living_entity)));
+	max_health = text.number(math.roundComma(max_health, 1));
+	
+	heart_index = text.indexOf(entity_name, "❤", 0);
+	if(heart_index == -1) {
+		//Kein Herz gefunden
+		setEntityName(living_entity, health, max_health, entity_name);
+		return;
+	}
+		
+	next_new_line = text.indexOf(entity_name, "\n", heart_index);
+	if(next_new_line == -1) {
+		//Rechts vom Herz keine New-Line gefunden
+		setEntityName(living_entity, health, max_health, null);
+		return;
+	}
+	entity_name = text.subString(entity_name, next_new_line + 1, text.length(entity_name));
+	setEntityName(living_entity, health, max_health, entity_name);
+}
+
+function setEntityName(living_entity, health, max_health, entity_name) {
+	entity_type = entity.getType(living_entity);
+	permanent = false;
+	if(set.contains($permanent_name, entity_type)) {
+		permanent = true;
+	} elseif(set.contains($permanent_tamed_name, entity_type)) {
+		if(pet.isTamed(living_entity)) {
+			permanent = true;
+		}
+	}
+	if(entity_name == null) {
+		entity.setName(living_entity, concat(health, "/", max_health, " §c❤"), permanent);
+		return;
+	}
+	entity.setName(living_entity, concat(health, "/", max_health, " §c❤\n", entity_name), permanent);
+}

+ 169 - 0
system/doors.txt

@@ -0,0 +1,169 @@
+event.load("block_click");
+
+doors = list.new();
+orig_value_map = map.new();
+
+auto_door_tag = block.getTag("km:auto_door");
+doors_tag = block.getTag("minecraft:wooden_doors");
+trapdoors_tag = block.getTag("minecraft:wooden_trapdoors");
+fencegates_tag = block.getTag("minecraft:fence_gates");
+
+block_sound_category = sound.getCategory("BLOCKS");
+open_door_sound = sound.get("BLOCK_WOODEN_DOOR_OPEN");
+close_door_sound = sound.get("BLOCK_WOODEN_DOOR_CLOSE");
+open_trapdoor_sound = sound.get("BLOCK_WOODEN_TRAPDOOR_OPEN");
+close_trapdoor_sound = sound.get("BLOCK_WOODEN_TRAPDOOR_CLOSE");
+open_fencegate_sound = sound.get("BLOCK_FENCE_GATE_OPEN");
+close_fencegate_sound = sound.get("BLOCK_FENCE_GATE_CLOSE");
+
+msg.string("dev", "§bDoors §rloaded.");
+@main
+wait();
+loc = entity.getLocation(player);
+world_name = world.getName(loc.getWorld(loc));
+if(world.isSurvName(world_name) || world.isStoryName(world_name)) {
+	ignoreGoto(event);
+}
+goto("main");
+
+@block_click
+if(block == null) {
+	goto("main");
+}
+if(block.hasTag(block, auto_door_tag) && action == "RIGHT_CLICK_BLOCK") {
+	player_spec = player.getAutoCloseDoor(player);
+	open_value = block.isOpen(block);
+	if(block.hasTag(block, doors_tag)) {
+		if(!open_value) {
+			if(player_spec) {
+				list.add(doors, block);
+				sgoto(60, "closedoor");
+			}
+		}
+		//Double door
+		door_block_2 = block.getSecondDoor(block);
+		if(door_block_2 == null) {
+			goto("main");
+		}
+		open_value_2 = block.isOpen(door_block_2);
+		if(open_value && open_value_2) {
+			door.open(door_block_2, false);
+		} elseif(!open_value && !open_value_2) {
+			door.open(door_block_2, true);
+			if(player_spec) {
+				list.add(doors, door_block_2);
+				sgoto(60, "closedoor");
+			}
+		}
+		goto("main");
+	}
+	if(player_spec) {
+		block_loc = block.getLocation(block);
+		if(!map.contains(orig_value_map, block_loc)) {
+			map.add(orig_value_map, block_loc, open_value);
+		}
+		list.add(doors, block);
+		sgoto(60, "closedoor");
+	}
+}
+goto("main");
+
+@closedoor
+block = list.getIndex(doors, 0);
+list.removeIndex(doors, 0);
+if(block.hasTag(block, auto_door_tag)) {
+	//close door
+	open_value = block.isOpen(block);
+	if(block.hasTag(block, doors_tag)) {
+		if(open_value) {
+			door.open(block, false);
+		}
+		goto("main");
+	}
+	//toggle door
+	door_loc = block.getLocation(block);
+	orig_value = map.get(orig_value_map, door_loc);
+	if(orig_value == null) {
+		goto("main");
+	}
+	map.remove(orig_value_map, door_loc);
+	if(orig_value == open_value) {
+		goto("main");
+	}
+	if(open_value) {
+		door.open(block, false);
+		goto("main");
+	}
+	door.open(block, true);
+}
+goto("main");
+
+function door.open(block, boolean) {
+	block.setOpen(block, boolean);
+	//sound
+	location = block.getLocation(block);
+	if(boolean) {
+		if(block.hasTag(block, $doors_tag)) {
+			sound.spawn(location, $open_door_sound, $block_sound_category);
+		} elseif(block.hasTag(block, $trapdoors_tag)) {
+			sound.spawn(location, $open_trapdoor_sound, $block_sound_category);
+		} elseif(block.hasTag(block, $fencegates_tag)) {
+			sound.spawn(location, $open_fencegate_sound, $block_sound_category);
+		}
+	} else {
+		if(block.hasTag(block, $doors_tag)) {
+			sound.spawn(location, $close_door_sound, $block_sound_category);
+		} elseif(block.hasTag(block, $trapdoors_tag)) {
+			sound.spawn(location, $close_trapdoor_sound, $block_sound_category);
+		} elseif(block.hasTag(block, $fencegates_tag)) {
+			sound.spawn(location, $close_fencegate_sound, $block_sound_category);
+		}
+	}
+}
+
+function block.getSecondDoor(door_block_1) {
+	door_loc_1 = block.getLocation(door_block_1);
+	state_facing = block.getDirectionalFace(door_block_1);
+	state_hinge = block.getDoorHinge(door_block_1);
+	if(state_facing == "NORTH") {
+		if(state_hinge == "RIGHT") {
+			door_loc_2 = loc.mod(door_loc_1, -1, 0, 0);
+		} else {
+			door_loc_2 = loc.mod(door_loc_1, 1, 0, 0);
+		}
+	} elseif(state_facing == "EAST") {
+		if(state_hinge == "RIGHT") {
+			door_loc_2 = loc.mod(door_loc_1, 0, 0, -1);
+		} else {
+			door_loc_2 = loc.mod(door_loc_1, 0, 0, 1);
+		}
+	} elseif(state_facing == "SOUTH") {
+		if(state_hinge == "RIGHT") {
+			door_loc_2 = loc.mod(door_loc_1, 1, 0, 0);
+		} else {
+			door_loc_2 = loc.mod(door_loc_1, -1, 0, 0);
+		}
+	} else {
+		if(state_hinge == "RIGHT") {
+			door_loc_2 = loc.mod(door_loc_1, 0, 0, 1);
+		} else {
+			door_loc_2 = loc.mod(door_loc_1, 0, 0, -1);
+		}
+	}
+	door_block_2 = block.get(door_loc_2);
+	if(block.hasTag(door_block_2, $doors_tag)) {
+		if(block.isSameDoorHalf(door_block_1, door_block_2)) {
+			state_hinge_2 = block.getDoorHinge(door_block_2);
+			if(state_hinge == "LEFT" && state_hinge_2 == "RIGHT" || state_hinge == "RIGHT" && state_hinge_2 == "LEFT") {
+				return door_block_2;
+			}
+		}
+	}
+	return null;
+}
+
+function block.isSameDoorHalf(door_block_1, door_block_2) {
+	state_half = block.getBisectedHalf(door_block_1);
+	state_half_2 = block.getBisectedHalf(door_block_2);
+	return state_half == state_half_2;
+}

+ 4 - 0
system/init.txt

@@ -1,3 +1,5 @@
+//---------- ScriptVars ----------
+
 config = config.new("scripts/configs", "server");
 if(config.exists(config)) {
 	config.load(config);
@@ -10,6 +12,8 @@ setScriptVar("rmInventories", map.new());
 setScriptVar("quest_ids", map.new());
 setScriptVar("lobbylastpos", map.new());
 
+//---------- Tables ----------
+
 table.setsize("f", 5);
 table.setsize("k", 5);
 table.setsize("I", 4);

+ 197 - 0
system/mailsystem.txt

@@ -0,0 +1,197 @@
+event.load("custom_command");
+event.load("player_join");
+
+databank.workerExecute(databank.prepare("
+	CREATE TABLE IF NOT EXISTS mails 
+	(
+		mail_id INT NOT NULL PRIMARY KEY, 
+		from_id INT NOT NULL, 
+		to_id INT NOT NULL, 
+		readed TINYINT NOT NULL, 
+		time BIGINT NOT NULL, 
+		del_time BIGINT, 
+		message VARCHAR(255) NOT NULL
+	);
+"));
+
+sgoto(200, "timerloop");
+prefix_mail = "§bMail";
+prefix_commands = "§6Commands";
+
+msg.string("dev", "§bMailsystem §rloaded.");
+@wait
+wait();
+ignoreGoto(event);
+goto("wait");
+
+@custom_command
+if(command == "mail") {
+	if(!isPlayer(sender)) {
+		goto("wait");
+	}
+	player = sender;
+	size = list.getSize(args);
+	if(size == 0) {
+		msg.prefix(player, prefix_mail, "/mail ...");
+		msg.string(player, "§b - <player> <message> §rSends a mail");
+		msg.string(player, "§b - new §rShows all new mails");
+		msg.string(player, "§b - inbox §rShows inbox");
+		msg.string(player, "§b - outbox §rShows outbox");
+		if(perm.has("mail.reset", player)) {
+			msg.string(player, "§b - reset §rDeletes ALL mails.");
+		}
+		goto("wait");
+	}
+	arg0 = list.getIndex(args, 0);
+	if(arg0 == "new") {
+		if(size != 1) {
+			msg.prefix(player, prefix_mail, "/mail new");
+			goto("wait");
+		}
+		mail.showNew(player);
+		goto("wait");
+	}
+	if(arg0 == "inbox" || arg0 == "outbox") {
+		if(size != 1) {
+			msg.prefix(player, prefix_mail, "/mail inbox/outbox");
+			goto("wait");
+		}
+		mail.showBox(player, arg0);
+		goto("wait");
+	}
+	if(arg0 == "reset") {
+		if(size != 1) {
+			msg.prefix(player, prefix_mail, "/mail reset");
+			goto("wait");
+		}
+		if(!perm.has("mail.reset", player)) {
+			msg.prefix(player, prefix_mail, "No permission.");
+			goto("wait");
+		}
+		mail.reset();
+		msg.prefix(player, prefix_mail, "All mails reset.");
+		goto("wait");
+	}
+	//send a mail
+	if(player.isMuted(player)) {
+		msg.prefix(player, prefix_commands, "You are muted.");
+		goto("wait");
+	}
+	p_uuid = player.getUuid(arg0);
+	if(p_uuid == null) {
+		msg.prefix(player, prefix_mail, "This player has never been online.");
+		goto("wait");
+	}
+	if(size == 1) {
+		msg.prefix(player, prefix_mail, "/mail <player> <message>");
+		goto("wait");
+	}
+	p_name = player.getName(p_uuid);
+	mail.send(player.getName(player), p_name, concatList(string_args, " ", 1, size - 1));
+	msg.prefix(player, prefix_mail, concat("Mail sent to ", p_name, "."));
+}
+goto("wait");
+
+@player_join
+mail.checkForNew(player);
+goto("wait");
+
+@timerloop
+mail.timedReset();
+sgoto(72000, "timerloop"); //Stundentakt
+goto("wait");
+
+function mail.showNew(player) {
+	stmt = databank.prepare("SELECT mail_id, from_id, time, message FROM mails WHERE to_id = ? AND readed = false;");
+	to_id = player.getId(player);
+	databank.setInt(stmt, 1, to_id);
+	result = databank.execute(stmt);
+	nextrow = databank.next(result);
+	if(!nextrow) {
+		msg.prefix(player, $prefix_mail, "You have no new mails.");
+		databank.close(result);
+		databank.close(stmt);
+		return;
+	}
+	msg.string(player, "[§bMail-New§r]");
+	while(nextrow) {
+		mail_id = databank.getInt(result, 1);
+		from = player.getNameFromId(databank.getInt(result, 2));
+		time = databank.getLong(result, 3);
+		message = databank.getString(result, 4);
+		
+		msg(player, text.merge(text.new(" - "), string.getHoverText(concat("§e", from), getTimeString(time)), text.new(text.concat(" §r§l", message))));
+		
+		nextrow = databank.next(result);
+	}
+	databank.close(result);
+	databank.close(stmt);
+	mail.readedAll(to_id);
+}
+
+function mail.showBox(player, box) {
+	if(box == "inbox") {
+		header = "[§bMail-Inbox§r]";
+		stmt = databank.prepare("SELECT mail_id, from_id, to_id, readed, time, message FROM mails WHERE to_id = ?;");
+		to_id = player.getId(player);
+		databank.setInt(stmt, 1, to_id);
+	} else {
+		header = "[§bMail-Outbox§r]";
+		stmt = databank.prepare("SELECT mail_id, from_id, to_id, readed, time, message FROM mails WHERE from_id = ?;");
+		from_id = player.getId(player);
+		databank.setInt(stmt, 1, from_id);
+	}
+	result = databank.execute(stmt);
+	nextrow = databank.next(result);
+	if(!nextrow) {
+		msg.prefix(player, $prefix_mail, "You have no mails in this box.");
+		databank.close(result);
+		databank.close(stmt);
+		return;
+	}
+	msg.string(player, header);
+	while(nextrow) {
+		mail_id = databank.getInt(result, 1);
+		from = player.getNameFromId(databank.getInt(result, 2));
+		to = player.getNameFromId(databank.getInt(result, 3));
+		readed = databank.getBool(result, 4);
+		if(readed) {
+			colorcode = "§r";
+		} else {
+			colorcode = "§l";
+		}
+		time = databank.getLong(result, 5);
+		message = databank.getString(result, 6);
+		if(box == "inbox") {
+			msg(player, text.merge(text.new(" - "), string.getHoverText(concat("§e", from), getTimeString(time)), text.new(text.concat(" §r", colorcode, message))));
+		} else {
+			msg(player, text.merge(text.new(" - "), string.getHoverText(concat("§e", to), getTimeString(time)), text.new(text.concat(" §r", colorcode, message))));
+		}
+		nextrow = databank.next(result);
+	}
+	databank.close(result);
+	databank.close(stmt);
+	if(box == "inbox") {
+		mail.readedAll(to_id);
+	}
+}
+
+function mail.readedAll(player_id) {
+	stmt = databank.prepare("UPDATE mails SET readed = true, del_time = ? WHERE to_id = ? AND readed = false;");
+	databank.setLong(stmt, 1, time.getMillis() + 1209600000); //+2 weeks
+	databank.setInt(stmt, 2, player_id);
+	databank.workerExecute(stmt);
+}
+
+function mail.timedReset() {
+	stmt = databank.prepare("DELETE FROM mails WHERE del_time < ?");
+	databank.setLong(stmt, 1, time.getMillis());
+	databank.workerExecute(stmt);
+}
+
+function mail.reset() {
+	databank.workerExecute(databank.prepare("DELETE FROM mails"));
+	server_config = getScriptVar("server_config");
+	config.set(server_config, "mail_id", 0);
+	config.saveAsync(server_config);
+}

+ 3 - 1
system/perms.txt

@@ -264,6 +264,7 @@ perm.addToGroup(4, "warn");
 perm.addToGroup(4, "kick");
 perm.addToGroup(4, "tempban");
 perm.addToGroup(4, "allsounds");
+perm.addToGroup(4, "color");
 perm.addToGroup(4, "perm");
 perm.addToGroup(4, "perm.toggle");
 perm.addToGroup(4, "skills.other");
@@ -369,7 +370,7 @@ perm.addToGroup(14, "perm.toggle");
 
 event.load("player_join");
 
-msg.text("dev", "§bPerms §rloaded.");
+msg.string("dev", "§bPerms §rloaded.");
 @wait
 wait();
 if(event == "player_join") {
@@ -398,6 +399,7 @@ function perm.addToGroup(group_id, perm) {
 
 function perm.addGroupToPlayer(group_id, player) {
 	list = perm.getGroupList(group_id);
+	iter = list.iterator(list);
 	while(hasNext(iter)) {
 		perm = next(iter);
 		perm.add(perm, player);

+ 7 - 3
system/player_data.txt

@@ -6,19 +6,23 @@ Configs sind dauerhaft geladen und werden z.B. in der ScriptVar "survival_data"
 playerdata.loadAll("survival_data");
 //playerdata.loadAll("games_data");
 //playerdata.loadAll("story_data");
-msg.text("dev", "§bPlayerdata §rloaded");
+msg.string("dev", "§bPlayerdata §rloaded");
 
 function playerdata.loadAll(name) {
 	player_data_map = map.new();
 	setScriptVar(name, player_data_map);
-	dir = file.new(concat("scripts/configs/player_data/", name));
+	dir = file.new(string.concat("scripts/configs/player_data/", name));
 	list = file.getList(dir);
 	iter = list.iterator(list);
 	while(hasNext(iter)) {
 		file = next(iter);
 		if(file.isFile(file)) {
 			file_name = file.getName(file);
-			player_id = text.convert(text.replace(file_name, ".snuvic", ""));
+			player_id = read.number(string.replace(file_name, ".snuvic", ""));
+			if(player_id == null) {
+				print(string.concat("player_id null found in config ", name));
+				continue;
+			}
 			playerdata.load(player_id, player_data_map, name);
 		}
 	}

+ 47 - 0
system/playtime.txt

@@ -0,0 +1,47 @@
+event.load("player_join");
+event.load("player_quit");
+
+databank.workerExecute(databank.prepare("
+	CREATE TABLE IF NOT EXISTS playtime (
+		id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
+		player_id INT NOT NULL, 
+		join_time BIGINT NOT NULL, 
+		leave_time BIGINT
+	);
+"));
+
+msg.string("dev", "§bPlaytime §rloaded.");
+@wait
+wait();
+player_id = player.getId(player);
+ignoreGoto(event);
+goto("wait");
+
+@player_join
+deleteDefectPlaytime(player_id);
+insertPlaytimeJoin(player_id);
+goto("wait");
+
+@player_quit
+insertPlaytimeLeave(player_id);
+goto("wait");
+
+function deleteDefectPlaytime(player_id) {
+	stmt = databank.prepare("DELETE FROM playtime WHERE player_id = ? AND leave_time IS NULL;", false);
+	databank.setInt(stmt, 1, player_id);
+	databank.workerExecute(stmt);
+}
+
+function insertPlaytimeJoin(player_id) {
+	stmt = databank.prepare("INSERT INTO playtime (player_id, join_time) VALUES (?, ?);", false);
+	databank.setInt(stmt, 1, player_id);
+	databank.setLong(stmt, 2, time.getMillis());
+	databank.workerExecute(stmt);
+}
+
+function insertPlaytimeLeave(player_id) {
+	stmt = databank.prepare("UPDATE playtime SET leave_time = ? WHERE player_id = ? AND leave_time IS NULL;", false);
+	databank.setLong(stmt, 1, time.getMillis());
+	databank.setInt(stmt, 2, player_id);
+	databank.workerExecute(stmt);
+}

+ 79 - 0
system/scheduler.txt

@@ -0,0 +1,79 @@
+list = list.new();
+setScriptVar("scheduler_list", list);
+
+msg("dev", "§bScheduler §rloaded.");
+@loop
+iter = list.iterator(list);
+while(hasNext(iter)) {
+	a = next(iter);
+	ticks = --a[1];
+	if(ticks <= 0) {
+		action = a[0];
+		
+		//Fly verändern
+		if(action == 0) {
+			player = a[2];
+			bool = a[3];
+			player.setFly(player, bool);
+		}
+		//Msg Prefix
+		if(action == 1) {
+			player = a[2];
+			prefix = a[3];
+			message = a[4];
+			msg.prefix(player, prefix, message);
+		}
+		//Msg
+		if(action == 2) {
+			player = a[2];
+			message = a[3];
+			msg(player, message);
+		}
+		//SetBlock
+		if(action == 3) {
+			location = a[2];
+			item_string = a[3];
+			block_update = a[4];
+			block.set(location, item_string, block_update);
+		}
+		//QuestFinish
+		if(action == 4) {
+			script = a[2];
+			player = a[3];
+			quest.finish(script, player);
+		}
+		//setBurning
+		if(action == 5) {
+			entity = a[2];
+			seconds = a[3];
+			entity.setBurning(entity, seconds);
+		}
+		//spawnEntity
+		if(action == 6) {
+			type = a[2];
+			location = a[3];
+			entity.spawn(type, location);
+		}
+		//removeEntity
+		if(action == 7) {
+			entity = a[2];
+			entity.remove(entity);
+		}
+		//giveItem
+		if(action == 8) {
+			player = a[2];
+			item = a[3];
+			player.safeGiveItem(player, item);
+		}
+		//giveSingleItem
+		if(action == 9) {
+			player = a[2];
+			item = a[3];
+			boolean = a[4];
+			player.giveSingleItem(player, item, boolean);
+		}
+		remove(iter);
+	}
+}
+sgoto(2, "loop");
+wait();

+ 54 - 0
system/sitting.txt

@@ -0,0 +1,54 @@
+event.load("entity_mount");
+event.load("block_click");
+
+sitting = map.new();
+stairs_tag = block.getTag("minecraft:stairs");
+half_property = block.getProperty("half");
+
+msg("dev", "§bSitting §rloaded.");
+@wait
+wait();
+ignoreGoto(event);
+goto("wait");
+
+@entity_mount
+if(isPlayer(rider)) {
+	player = rider;
+	if(map.contains(sitting, player)) {
+		entity.remove(map.get(sitting, player));
+		map.remove(sitting, player);
+	}
+}
+goto("wait");
+
+@block_click
+if(hand == "OFF_HAND") {
+	goto("wait");
+}
+if(block.hasTag(stairs_tag, block)) {
+	if(action == "left") {
+		goto("wait");
+	}
+	if(block.property.getValue(block_loc, half_property) != "bottom") {
+		goto("wait");
+	}
+	if(item.getType(living.getEquip(player, "hand")) != "minecraft:air") {
+		goto("wait");
+	}
+	if(!loc.isAir(loc.mod(block_loc, 0, 1, 0))) {
+		goto("wait");
+	}
+	if(map.contains(sitting, player)) {
+		goto("wait");
+	}
+	if(player.hasMinigame(player)) {
+		goto("wait");
+	}
+	if(!player.hasSittingActivated(player)) {
+		goto("wait");
+	}
+	entity = entity.spawn("km:nobody", loc.mod(block_loc, 0.5, 0, 0.5), "{NoGravity:true}");
+	map.add(sitting, player, entity);
+	entity.mount(player, entity);
+}
+goto("wait");

+ 0 - 36
system/svars.txt

@@ -1,36 +0,0 @@
-//---------- ScriptVars ----------
-
-config = config.new("scripts/configs", "server");
-if(config.exists(config)) {
-	config.load(config);
-}
-setScriptVar("server_config", config);
-
-setScriptVar("script_players", map.new());
-setScriptVar("nicknames", map.new());
-setScriptVar("rmInventories", map.new());
-setScriptVar("quest_ids", map.new());
-setScriptVar("lobbylastpos", map.new());
-
-
-//---------- Tables ----------
-
-table.setsize("f", 5);
-table.setsize("k", 5);
-table.setsize("I", 4);
-table.setsize("t", 4);
-table.setsize(" ", 4);
-table.setsize("[", 4);
-table.setsize("]", 4);
-table.setsize("{", 4);
-table.setsize("}", 4);
-table.setsize("(", 4);
-table.setsize(")", 4);
-table.setsize("l", 3);
-table.setsize(";", 2);
-table.setsize(",", 2);
-table.setsize(".", 2);
-table.setsize("i", 2);
-table.setsize(":", 2);
-
-term();

+ 542 - 0
system/tickets.txt

@@ -0,0 +1,542 @@
+event.load("custom_command");
+event.load("player_logout");
+prefix = "§2Ticket";
+pling_sound = sound.get("BLOCK_NOTE_BLOCK_PLING");
+sound_category_ambient = sound.getCategory("AMBIENT");
+
+tickets = list.new(); //List with ticket-arrays: ticket[ticketid][helpneeder][message][supporter]
+ticketcounter = 0;
+
+msg.string("dev", "§bTickets §rloaded.");
+@wait
+wait();
+ignoreGoto(event);
+goto("wait");
+
+@custom_command
+if(!isPlayer(sender)) {
+	goto("wait");
+}
+player = sender;
+if(command == "ticket") {
+	size = list.getSize(args);
+	if(size == 0) {
+		@tickethelp
+		msg.prefix(player, prefix, "/ticket...");
+		msg.string(player, "§2 - new <message> §rCreate a ticket");
+		msg.string(player, "§2 - stop [id] §rCancel your ticket");
+		if(isSupporter(player)) {
+			msg.string(player, "§2 - list §rShows all tickets");
+			msg.string(player, "§2 - get [id] §rTake care of a ticket");
+			msg.string(player, "§2 - finish [id] §rFinish a ticket");
+			msg.string(player, "§2 - release [id] §rRelease a ticket for the next supporter");
+			msg.string(player, "§2 - report [id] §rReport a ticket to marvinius");
+		}
+		goto("wait");
+	}
+	arg0 = string.toLowerCase(list.getIndex(args, 0));
+	if(arg0 == "list") {
+		if(size != 1) {
+			msg.prefix(player, prefix, "/ticket list");
+			goto("wait");
+		}
+		if(!isSupporter(player)) {
+			msg.prefix(player, prefix, "You are not a supporter.");
+			goto("wait");
+		}
+		amount = list.getSize(tickets);
+		if(amount == 0) {
+			msg.prefix(player, prefix, "There are no tickets.");
+			goto("wait");
+		}
+		if(ticket.getProcessingAmount() == 0) {
+			msg.prefix(player, prefix, "There are no processing tickets.");
+		} else {
+			msg.prefix(player, prefix, "Processing tickets:");
+			msg.string(player, "§2--------------------------");
+			list = ticket.getProcessing();
+			iter = list.iterator(list);
+			while(hasNext(iter)) {
+				ticket = next(iter);
+				msg.string(player, string.concat("§2 - §rID: §a", string.number(ticket.getId(ticket))));
+				msg.string(player, string.concat("§2 - §rPlayer: §a", player.getNameFromId(ticket.getHelpNeeder(ticket))));
+				msg.string(player, string.concat("§2 - §rSupporter: §a", player.getNameFromId(ticket.getSupporter(ticket))));
+				msg.string(player, string.concat("§2 - §rMessage: §a", ticket.getMessage(ticket)));
+				msg.string(player, "§2--------------------------");
+			}
+		}
+		if(ticket.getOutstandingAmount() == 0) {
+			msg.prefix(player, prefix, "There are no outstanding tickets.");
+		} else {
+			msg.prefix(player, prefix, "Outstanding tickets:");
+			msg.string(player, "§2--------------------------");
+			list = ticket.getOutstanding();
+			iter = list.iterator(list);
+			while(hasNext(iter)) {
+				ticket = next(iter);
+				msg.string(player, string.concat("§2 - §rID: §a", string.number(ticket.getId(ticket))));
+				msg.string(player, string.concat("§2 - §rPlayer: §a", player.getNameFromId(ticket.getHelpNeeder(ticket))));
+				msg.string(player, string.concat("§2 - §rMessage: §a", ticket.getMessage(ticket)));
+				msg.string(player, "§2--------------------------");
+			}
+		}
+		goto("wait");
+	}
+	if(arg0 == "get") {
+		if(size < 1 || size > 2) {
+			msg.prefix(player, prefix, "/ticket get [id]");
+			goto("wait");
+		}
+		if(!isSupporter(player)) {
+			msg.prefix(player, prefix, "You are not a supporter.");
+			goto("wait");
+		}
+		if(size == 1) {
+			if(ticket.getOutstandingAmount() == 0) {
+				msg.prefix(player, prefix, "There are no outstanding tickets.");
+				goto("wait");
+			}
+			ticket = ticket.getNextOutstanding();
+		} else {
+			ticket_id = list.getIndex(args, 1);
+			if(!isDouble(ticket_id)) {
+				msg.prefix(player, prefix, "Number expected.");
+				goto("wait");
+			}
+			ticket = ticket.getFromID(ticket_id);
+			if(ticket == null) {
+				msg.prefix(player, prefix, "Not an existing ticket.");
+				goto("wait");
+			}
+			supporter_id = ticket.getSupporter(ticket);
+			if(supporter_id != null) {
+				msg.prefix(player, prefix, "Another supporter supports this ticket.");
+				goto("wait");
+			}
+		}
+		message = ticket.getMessage(ticket);
+		ticket.setSupporter(ticket, player);
+		p_name = player.getNameFromId(ticket.getHelpNeeder(ticket));
+		p = read.player(p_name);
+		msg.prefix(p, prefix, "Your ticket is in process:");
+		msg.string(p, string.concat("§2 - §rSupporter: §a", player.getName(player)));
+		msg.string(p, string.concat("§2 - §rYour message: §a", message));
+		msg.prefix(player, prefix, "You take care of the ticket:");
+		msg.string(player, string.concat("§2 - §rID: §a", string.number(ticket.getId(ticket))));
+		msg.string(player, string.concat("§2 - §rPlayer: §a", p_name));
+		msg.string(player, string.concat("§2 - §rMessage: §a", message));
+		goto("wait");
+	}
+	if(arg0 == "finish") {
+		if(size < 1 || size > 2) {
+			msg.prefix(player, prefix, "/ticket finish [id]");
+			goto("wait");
+		}
+		if(!isSupporter(player)) {
+			msg.prefix(player, prefix, "You are not a supporter.");
+			goto("wait");
+		}
+		if(size == 1) {
+			if(ticket.getAmountFromSupporter(player) > 1) {
+				msg.prefix(player, prefix, "You support more than one ticket.");
+				goto("wait");
+			}
+			ticket = ticket.getFromSupporter(player);
+			if(ticket == null) {
+				msg.prefix(player, prefix, "You support no tickets.");
+				goto("wait");
+			}
+		} else {
+			ticketid = list.getIndex(args, 1);
+			if(!isDouble(ticketid)) {
+				msg.prefix(player, prefix, "Number expected.");
+				goto("wait");
+			}
+			ticket = ticket.getFromID(ticketid);
+			if(ticket == null) {
+				msg.prefix(player, prefix, "Not an existing ticket.");
+				goto("wait");
+			}
+		}
+		if(!ticket.isSupporter(ticket, player)) {
+			msg.prefix(player, prefix, "Another supporter supports this ticket.");
+			goto("wait");
+		}
+		ticket.stop(ticket);
+		name = player.getNameFromId(ticket.getHelpNeeder(ticket));
+		msg.send(null, name, prefix, "Your ticket was finished.", false);
+		msg.prefix(player, prefix, "You finished the ticket.");
+		goto("wait");
+	}
+	if(arg0 == "release") {
+		if(size < 1 || size > 2) {
+			msg.prefix(player, prefix, "/ticket release [id]");
+			goto("wait");
+		}
+		if(!isSupporter(player)) {
+			msg.prefix(player, prefix, "You are not a supporter.");
+			goto("wait");
+		}
+		if(size == 1) {
+			if(ticket.getAmountFromSupporter(player) > 1) {
+				msg.prefix(player, prefix, "You support more than one ticket.");
+				goto("wait");
+			}
+			ticket = ticket.getFromSupporter(player);
+			if(ticket == null) {
+				msg.prefix(player, prefix, "You support no tickets.");
+				goto("wait");
+			}
+		} else {
+			ticketid = list.getIndex(args, 1);
+			if(!isDouble(ticketid)) {
+				msg.prefix(player, prefix, "Number expected.");
+				goto("wait");
+			}
+			ticket = ticket.getFromID(ticketid);
+			if(ticket == null) {
+				msg.prefix(player, prefix, "Not an existing ticket.");
+				goto("wait");
+			}
+		}
+		if(!ticket.isSupporter(ticket, player)) {
+			msg.prefix(player, prefix, "Another supporter supports this ticket.");
+			goto("wait");
+		}
+		ticket.release(ticket, player);
+		goto("wait");
+	}
+	if(arg0 == "report") {
+		if(size < 1 || size > 2) {
+			msg.prefix(player, prefix, "/ticket report [id]");
+			goto("wait");
+		}
+		if(!isSupporter(player)) {
+			msg.prefix(player, prefix, "You are not a supporter.");
+			goto("wait");
+		}
+		if(size == 1) {
+			if(ticket.getAmountFromSupporter(player) > 1) {
+				msg.prefix(player, prefix, "You support more than one ticket.");
+				goto("wait");
+			}
+			ticket = ticket.getFromSupporter(player);
+			if(ticket == null) {
+				msg.prefix(player, prefix, "You support no tickets.");
+				goto("wait");
+			}
+		} else {
+			ticketid = list.getIndex(args, 1);
+			if(!isDouble(ticketid)) {
+				msg.prefix(player, prefix, "Number expected.");
+				goto("wait");
+			}
+			ticket = ticket.getFromID(ticketid);
+			if(ticket == null) {
+				msg.prefix(player, prefix, "Not an existing ticket.");
+				goto("wait");
+			}
+		}
+		if(!ticket.isSupporter(ticket, player)) {
+			msg.prefix(player, prefix, "Another supporter supports this ticket.");
+			goto("wait");
+		}
+		ticket.report(ticket, player);
+		name = player.getNameFromId(ticket.getHelpNeeder(ticket));
+		msg.send(null, name, prefix, "Your ticket got reported.", false);
+		msg.prefix(player, prefix, "You reported the ticket.");
+		goto("wait");
+	}
+	if(arg0 == "stop") {
+		if(size < 1 || size > 2) {
+			msg.prefix(player, prefix, "/ticket stop [id]");
+			goto("wait");
+		}
+		if(size == 1) {
+			if(ticket.getAmountFromHelpNeeder(player) > 1) {
+				msg.prefix(player, prefix, "You have more than one ticket.");
+				goto("wait");
+			}
+			ticket = ticket.getFromHelpNeeder(player);
+			if(ticket == null) {
+				msg.prefix(player, prefix, "You have no tickets.");
+				goto("wait");
+			}
+		} else {
+			ticketid = list.getIndex(args, 1);
+			if(!isDouble(ticketid)) {
+				msg.prefix(player, prefix, "Number expected.");
+				goto("wait");
+			}
+			ticket = ticket.getFromID(ticketid);
+			if(ticket == null) {
+				msg.prefix(player, prefix, "Not an existing ticket.");
+				goto("wait");
+			}
+			if(!hasTicketCreated(player, ticket)) {
+				msg.prefix(player, prefix, "Not your ticket.");
+				goto("wait");
+			}
+		}
+		if(ticket.stop(ticket)) {
+			msg.prefix(player, prefix, "Stopped your ticket.");
+			supporter_id = ticket.getSupporter(ticket);
+			if(supporter_id != null) {
+				msg.send(null, player.getNameFromId(supporter_id), prefix, string.concat("The ticket from ", player.getName(player), " was stopped."), false);
+			}
+		}
+		goto("wait");
+	}
+	if(arg0 == "new") {
+		if(size < 2) {
+			msg.prefix(player, prefix, "/ticket new <message>");
+			goto("wait");
+		}
+		
+		supporters = getAvailableSupporters();
+		if(list.getSize(supporters) == 0) {
+			msg.prefix(player, prefix, "There is no supporter available.");
+			goto("wait");
+		}
+		message = string.concatList(args, " ", 1, size - 1);
+		ticket = ticket.create(player, message);
+		msg.prefix(player, prefix, string.concat("Ticket created (ID: ", string.number(ticket.getId(ticket)), ")."));
+		informSuppsAboutNew(ticket);
+		goto("wait");
+	}
+	goto("tickethelp");
+}
+goto("wait");
+
+@player_logout
+player_id = player.getId(player);
+if(isSupporter(player)) {
+	iter = list.iterator(tickets);
+	while(hasNext(iter)) {
+		ticket = next(iter);
+		if(ticket.isSupporter(ticket, player)) {
+			ticket.release(ticket, player);
+		}
+	}
+}
+for(i = 0; i < list.getSize(tickets); i++) {
+	ticket = list.getIndex(tickets, i);
+	if(ticket.isHelpNeeder(ticket, player)) {
+		ticket.stop(ticket);
+	}
+}
+goto("wait");
+
+function ticket.getProcessing() {
+	list = list.new();
+	iter = list.iterator($tickets);
+	while(hasNext(iter)) {
+		ticket = next(iter);
+		if(ticket.getSupporter(ticket) != null) {
+			list.add(list, ticket);
+		}
+	}
+	return list;
+}
+
+function ticket.getProcessingAmount() {
+	return list.getSize(ticket.getProcessing());
+}
+
+function ticket.getOutstanding() {
+	list = list.new();
+	iter = list.iterator($tickets);
+	while(hasNext(iter)) {
+		ticket = next(iter);
+		if(ticket.getSupporter(ticket) == null) {
+			list.add(list, ticket);
+		}
+	}
+	return list;
+}
+
+function ticket.getOutstandingAmount() {
+	return list.getSize(ticket.getOutstanding());
+}
+
+function ticket.getNextOutstanding() {
+	iter = list.iterator($tickets);
+	while(hasNext(iter)) {
+		t = next(iter);
+		if(ticket.getSupporter(t) == null) {
+			return t;
+		}
+	}
+	return null;
+}
+
+function ticket.isSupporter(ticket, player) {
+	return ticket.getSupporter(ticket) == player.getId(player);
+}
+
+function ticket.isHelpNeeder(ticket, player) {
+	return ticket.getHelpNeeder(ticket) == player.getId(player);
+}
+
+function isSupporter(player) {
+	return perm.has("isSupporter", player);
+}
+
+function getAvailableSupporters() {
+	online = players.toList();
+	supporters = list.new();
+	for(i = 0; i < list.getSize(online); i++) {
+		p = list.getIndex(online, i);
+		if(isSupporter(p)) {
+			list.add(supporters, p);
+		}
+	}
+	return supporters;
+}
+
+function ticket.create(player, message) {
+	$ticketcounter++;
+	ticket = array.new(4);
+	ticket[0] = player.getId(player);
+	ticket[1] = message;
+	ticket[3] = $ticketcounter;
+	list.add($tickets, ticket);
+	return ticket;
+}
+
+function ticket.release(ticket, supporter) {
+	player_id = ticket.getHelpNeeder(ticket);
+	name = player.getNameFromId(player_id);
+	msg.send(null, name, $prefix, "Your ticket got released, so another supporter can take care of.", false);
+	msg.prefix(supporter, $prefix, "You released the ticket for another supporter.");
+	ticket.setSupporter(ticket, null);
+	informSuppsAboutRelease(ticket, supporter);
+}
+
+function informSuppsAboutNew(ticket) {
+	supporters = getAvailableSupporters();
+	iter = list.iterator(supporters);
+	while(hasNext(iter)) {
+		p = next(iter);
+		msg.prefix(p, $prefix, "New ticket:");
+		msg.string(p, string.concat("§2 - §rID: §a", string.number(ticket.getId(ticket))));
+		msg.string(p, string.concat("§2 - §rPlayer: §a", player.getNameFromId(ticket.getHelpNeeder(ticket))));
+		msg.string(p, string.concat("§2 - §rMessage: §a", ticket.getMessage(ticket)));
+		sound.spawnForPlayer(p, $pling_sound, $sound_category_ambient);
+	}
+}
+
+function informSuppsAboutRelease(ticket, supporter) {
+	supporters = getAvailableSupporters();
+	iter = list.iterator(supporters);
+	while(hasNext(iter)) {
+		p = next(iter);
+		msg.prefix(p, $prefix, "Ticket released:");
+		msg.string(p, string.concat("§2 - §rID: §a", string.number(ticket.getId(ticket))));
+		msg.string(p, string.concat("§2 - §rPlayer: §a", player.getNameFromId(ticket.getHelpNeeder(ticket))));
+		msg.string(p, string.concat("§2 - §rEx-Supporter: §a", player.getName(supporter)));
+		msg.string(p, string.concat("§2 - §rMessage: §a", ticket.getMessage(ticket)));
+		sound.spawnForPlayer(p, $pling_sound, $sound_category_ambient);
+	}
+}
+
+function ticket.report(ticket, supporter) {
+	name = player.getNameFromId(ticket.getHelpNeeder(ticket));
+	message = ticket.getMessage(ticket);
+	supporter_name = player.getName(supporter);
+	mail.send(supporter_name, "marvinius", string.concat("Ticket Report: ", name, " / ", message));
+	ticket.stop(ticket);
+}
+
+function ticket.stop(ticket) {
+	if(!list.contains($tickets, ticket)) {
+		return false;
+	}
+	list.remove($tickets, ticket);
+	return true;
+}
+
+function ticket.getHelpNeeder(ticket) {
+	return ticket[0];
+}
+
+function ticket.getMessage(ticket) {
+	return ticket[1];
+}
+
+function ticket.getSupporter(ticket) {
+	return ticket[2];
+}
+
+function ticket.getId(ticket) {
+	return ticket[3];
+}
+
+function ticket.setSupporter(ticket, player) {
+	if(player == null) {
+		ticket[2] = null;
+	} else {
+		ticket[2] = player.getId(player);
+	}
+}
+
+function hasTicketCreated(player, ticket) {
+	return player.getId(player) == ticket.getHelpNeeder(ticket);
+}
+
+function ticket.getFromID(ticket_id) {
+	iter = list.iterator($tickets);
+	while(hasNext(iter)) {
+		t = next(iter);
+		if(ticket.getId(t) == ticket_id) {
+			return t;
+		}
+	}
+	return null;
+}
+
+function ticket.getAmountFromSupporter(player) {
+	c = 0;
+	iter = list.iterator($tickets);
+	while(hasNext(iter)) {
+		t = next(iter);
+		if(ticket.isSupporter(t, player)) {
+			c++;
+		}
+	}
+	return c;
+}
+
+function ticket.getFromSupporter(player) {
+	iter = list.iterator($tickets);
+	while(hasNext(iter)) {
+		t = next(iter);
+		if(ticket.isSupporter(t, player)) {
+			return t;
+		}
+	}
+	return null;
+}
+
+function ticket.getAmountFromHelpNeeder(player) {
+	c = 0;
+	iter = list.iterator($tickets);
+	while(hasNext(iter)) {
+		t = next(iter);
+		if(ticket.isHelpNeeder(t, player)) {
+			c++;
+		}
+	}
+	return c;
+}
+
+function ticket.getFromHelpNeeder(player) {
+	iter = list.iterator($tickets);
+	while(hasNext(iter)) {
+		t = next(iter);
+		if(ticket.isHelpNeeder(t, player)) {
+			return t;
+		}
+	}
+	return null;
+}

+ 53 - 0
system/tiploop.txt

@@ -0,0 +1,53 @@
+prefix_tips = "§eTips";
+index = 0;
+sgoto(100, "tip_loop");
+
+msg.string("dev", "§bTipLoop §rloaded.");
+@wait
+wait();
+goto("wait");
+
+@tip_loop
+//get next tip
+list = getLoopTipps();
+size = list.getSize(list);
+if(size == 0) {
+	goto("wait");
+}
+index++;
+if(index >= size) {
+	index = 0;
+}
+a = list.getIndex(list, index);
+tipp_value = a[1];
+if(string.contains(tipp_value, "https://")) {
+	tipp_value = string.getTextWithLink(tipp_value);
+} else {
+	tipp_value = text.new(tipp_value);
+}
+//loop online players
+online_list = players.toList();
+iter = iterator(online_list);
+while(hasNext(iter)) {
+	p = next(iter);
+	if(player.getTipLoop(p)) {
+		msg(p, text.merge(text.new(string.concat(string.getPrefix(prefix_tips), " ")), tipp_value));
+	}
+}
+sgoto(12000, "tip_loop");
+goto("wait");
+
+function getLoopTipps() {
+	list = list.new();
+	stmt = databank.prepare("SELECT tipp_key, tipp_value FROM tipps WHERE tipp_loop = TRUE");
+	result = databank.execute(stmt);
+	while(databank.next(result)) {
+		a = array.new(2);
+		a[0] = databank.getString(result, 1);
+		a[1] = databank.getString(result, 2);
+		list.add(list, a);
+	}
+	databank.close(result);
+	databank.close(stmt);
+	return list;
+}

+ 17 - 0
test2.txt

@@ -0,0 +1,17 @@
+test(read.player("marvinius"));
+test(read.player("kajetanjohannes"));
+
+function test(player) {
+	a = item.custom.getAll();
+	iter = iterator(a);
+	while(hasNext(iter)) {
+		player.safeGiveItem(player, item.custom.new(next(iter)));
+	}
+}
+
+function player.safeGiveItem(player, item) {
+	rest_item = player.giveItem(player, item);
+	if(item.getAmount(rest_item) > 0) {
+		item.drop(entity.getLocation(player), rest_item);
+	}
+}

+ 0 - 0
test3.txt


File diff suppressed because it is too large
+ 258 - 239
utils/u_general.txt


Some files were not shown because too many files changed in this diff