瀏覽代碼

Added redistribution of wealth

Lennart 4 年之前
父節點
當前提交
ab23ec65be

+ 15 - 8
config.yml

@@ -1,4 +1,4 @@
-# Abba Caving Plugin by lennartVH01
+# Abba Caving Plugin by VonTum (https://github.com/VonTum)
 
 # Game duration in seconds
 Duration: 1800
@@ -6,16 +6,23 @@ Duration: 1800
 # Max players per game, users with permission AbbaCaving.joinFull can still join
 PlayerCap: 10
 
-#Example Game with 10 players
-# All: 1
-# Top: 
-# - 7
-# - 2
-# If FixPlayerWeight == true then the first player would receive 70% of winnings, second would receive 20% and the remaining 10% is divided among the 8 remaining players
-# If FixPlayerWeight == false then the first player would receive 7/(7+2+8*1)=7/17 of total winnings, second would receive 2/17 and every remaining player will get 1/17
+# Denotes the redistribution of ores after the game by score. 
+Redistribution:
+  Enabled: true
+  # Weight of ores to be allotted to the leaderboard players
+  Top:
+  - 7
+  - 2
+  # Share of the ores to be allotted to the other players
+  Other: 1
+  OthersShare: false
+# Example for 10 players
+# If OthersShare == true then the first player would receive 70% of winnings, second would receive 20% and the remaining 10% is divided among the 8 remaining players
+# If OthersShare == false then the first player would receive 7/(7+2+8*1)=7/17 of total winnings, second would receive 2/17 and every remaining player will get 1/17
 
 
 # Points awarded for each item at the end of an Abba Match
+# BlockData value can be added in () at the end of the type name
 ItemValues:
 - IRON_ORE=1
 - REDSTONE_ORE=2

+ 5 - 1
lang.yml

@@ -7,6 +7,9 @@ msg:
     gamePause: "&aThe game has been paused!"
     gameEnd: "&aThe game has ended!\nTotal Items Collected:"
     
+    pickupCollected: "&6You have uncollected items left.\nUse &a/abba collect &6to collect your items."
+    allItemsCollected: "All items collected."
+    
 error:
     noGames: "&cNo Games found!"
     noPermission: "&cYou don't have permission to use this command!"
@@ -22,7 +25,7 @@ error:
     blacklisted: "&cYou are blacklisted for this game!"
     contraband: "&cYou cannot join the game with the following items: "
     breakClaimedChest: "&cYou cannot break an occupied chest!"
-    
+    noItemsToCollect: "&cYou have no items to collect!"
 help:
     abba: "&aabba <%s>"
     
@@ -31,6 +34,7 @@ help:
     info: "&aabba info [game]&f: Displays info about an Abba Match"
     list: "&aabba list&f: Lists all Abba Matches"
     calc: "&aabba calc&f: Calculates the score of your current inventory"
+    collect: "&aabba collect&f: Collects the won items"
     
     create: "&aabba create [game]&f: Creates an Abba Game"
     remove: "&aabba remove <game>&f: Removes an Abba Game"

+ 93 - 0
src/me/lennartVH01/CollectionHandler.java

@@ -0,0 +1,93 @@
+package me.lennartVH01;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+import me.lennartVH01.game.CollectionInfo;
+import me.lennartVH01.util.ChatUtil;
+
+public class CollectionHandler {
+	private static Map<Player, List<CollectionInfo>> itemsLeftToBeCollected = new HashMap<Player, List<CollectionInfo>>();
+	
+	private static void addItemToList(List<CollectionInfo> curList, CollectionInfo newItem){
+		for(CollectionInfo cur : curList){
+			if(cur.item.equals(newItem.item)){
+				cur.count += newItem.count;
+				return;
+			}
+		}
+		curList.add(newItem);
+	}
+	
+	public static void pushItemsForCollection(Player player, List<CollectionInfo> newItemsForCollection){
+		if(itemsLeftToBeCollected.containsKey(player)){
+			List<CollectionInfo> items = itemsLeftToBeCollected.get(player);
+			for(CollectionInfo currentlyAdding : newItemsForCollection){
+				addItemToList(items, currentlyAdding);
+			}
+		}else{
+			itemsLeftToBeCollected.put(player, newItemsForCollection);
+		}
+		printCollectableItems(player);
+	}
+	
+	// returns true if all items could be given
+	private static void give(Player player, CollectionInfo item){
+		while(item.count > 0){
+			int numberToGive = Math.min(item.count, item.item.getMaxStackSize());
+			ItemStack newItemStack = item.item.clone();
+			newItemStack.setAmount(numberToGive);
+			HashMap<Integer, ItemStack> couldntStore = player.getInventory().addItem(newItemStack);
+			
+			if(!couldntStore.isEmpty()){
+				int leftOver = couldntStore.get(0).getAmount();
+				int given = numberToGive - leftOver;
+				item.count -= given;
+			}else{
+				item.count -= numberToGive;
+			}
+		}
+	}
+	
+	public static boolean collect(Player player){
+		if(itemsLeftToBeCollected.containsKey(player)){
+			List<CollectionInfo> items = itemsLeftToBeCollected.get(player);
+			
+			
+			for(int i = 0; i < items.size();){
+				give(player, items.get(i));
+				if(items.get(i).count == 0){
+					items.remove(i);
+				}else{
+					i++;
+				}
+			}
+			if(items.isEmpty()){
+				itemsLeftToBeCollected.remove(player);
+				player.sendMessage(Messages.allItemsCollected);
+			}else{
+				printCollectableItems(player);
+			}
+			
+			return true;
+		}else{
+			return false;
+		}
+	}
+	
+	private static void printCollectableItems(Player player){
+		if(itemsLeftToBeCollected.containsKey(player)){
+			List<CollectionInfo> items = itemsLeftToBeCollected.get(player);
+			player.sendMessage(Messages.pickupCollected);
+			
+			for(CollectionInfo i : items){
+				ChatUtil.sendItemStack(player, i.item, "- " + i.count + "x ");
+			}
+		}
+	}
+}

+ 20 - 0
src/me/lennartVH01/CommandHandler.java

@@ -41,6 +41,7 @@ public class CommandHandler implements CommandExecutor, TabCompleter{
 		commands.put("info", infoCmd);
 		commands.put("list", listCmd);
 		commands.put("confirm", confirmCmd);
+		commands.put("collect", collectCmd);
 		
 		commands.put("create", createCmd);
 		commands.put("remove", removeCmd);
@@ -173,6 +174,25 @@ public class CommandHandler implements CommandExecutor, TabCompleter{
 		}
 	};
 	
+	private CommandFunc collectCmd = new CommandFunc(){
+		@Override public boolean hasPermission(CommandSender sender){return Permission.BASIC.has(sender);}
+		@Override public boolean run(CommandSender sender, String[] args){
+			if(sender instanceof Player){
+				if(!CollectionHandler.collect((Player) sender)){
+					sender.sendMessage(Messages.errorNoItemsToCollect);
+					return false;
+				}
+				return true;
+			}else{
+				sender.sendMessage(Messages.errorMustBeInGame);
+				return false;
+			}
+		}
+		@Override public List<String> tabComplete(CommandSender sender, String[] args){
+			return Collections.emptyList();
+		}
+	};
+	
 	
 	private CommandFunc createCmd = new CommandFunc(){
 		@Override public boolean hasPermission(CommandSender sender){return Permission.ADMIN.has(sender);}

+ 15 - 0
src/me/lennartVH01/Config.java

@@ -5,6 +5,7 @@ import java.util.Map;
 
 import me.lennartVH01.game.StackTester;
 
+import org.bukkit.configuration.ConfigurationSection;
 import org.bukkit.configuration.InvalidConfigurationException;
 import org.bukkit.configuration.file.FileConfiguration;
 
@@ -14,6 +15,11 @@ public class Config{
 	public static StackTester[] itemValues;
 	public static StackTester[] contraband;
 	
+	public static boolean redistributionEnabled;
+	public static int[] topReturns;
+	public static int otherPlayersValue;
+	public static boolean otherPlayersShare;
+	
 	public static int defaultDuration;
 	public static int defaultPlayerCap;
 	
@@ -45,7 +51,16 @@ public class Config{
 			contraband[contrabandList.size() + i] = tester;
 		}
 		
+		ConfigurationSection redistribution = config.getConfigurationSection("Redistribution");
+		
+		redistributionEnabled = redistribution.getBoolean("Enabled");
+		@SuppressWarnings("unchecked")
+		List<Integer> topRets = (List<Integer>) redistribution.getList("Top");
+		topReturns = new int[topRets.size()];
+		for(int i = 0; i < topRets.size(); i++) topReturns[i] = topRets.get(i);
 		
+		otherPlayersValue = redistribution.getInt("Other");
+		otherPlayersShare = redistribution.getBoolean("OthersShare");
 	}
 	private static StackTester toStackTester(Object input){
 		try{

+ 9 - 0
src/me/lennartVH01/Messages.java

@@ -14,6 +14,8 @@ public class Messages{
 	public static String gameCountdown;
 	public static String gamePause;
 	public static String gameEnded;
+	public static String pickupCollected;
+	public static String allItemsCollected;
 	
 	public static String errorNoGames;
 	public static String errorNoPermission;
@@ -29,6 +31,7 @@ public class Messages{
 	public static String errorNotWhitelisted;
 	public static String errorBlacklisted;
 	public static String errorContraband;
+	public static String errorNoItemsToCollect;
 	
 	public static String errorBreakClaimedChest;
 	public static String chestCreateSuccess;
@@ -41,6 +44,7 @@ public class Messages{
 	public static String helpInfo;
 	public static String helpList;
 	public static String helpCalc;
+	public static String helpCollect;
 	
 	public static String helpCreate;
 	public static String helpRemove;
@@ -89,6 +93,9 @@ public class Messages{
 		gamePause = load("msg.gamePause");
 		gameEnded = load("msg.gameEnd");
 		
+		pickupCollected = load("msg.pickupCollected");
+		allItemsCollected = load("msg.allItemsCollected");
+		
 		errorNoGames = load("error.noGames");
 		errorNoPermission = load("error.noPermission");
 		errorNoPendingOperation = load("error.noPendingOperation");
@@ -102,6 +109,7 @@ public class Messages{
 		errorNotWhitelisted = load("error.notWhitelisted");
 		errorBlacklisted = load("error.blacklisted");
 		errorContraband = load("error.contraband");
+		errorNoItemsToCollect = load("error.noItemsToCollect");
 		
 		errorBreakClaimedChest = load("error.breakClaimedChest");
 		chestCreateSuccess = load("chest.create");
@@ -114,6 +122,7 @@ public class Messages{
 		helpInfo = load("help.info");
 		helpList = load("help.list");
 		helpCalc = load("help.calc");
+		helpCollect = load("help.collect");
 		
 		helpCreate = load("help.create");
 		helpRemove = load("help.remove");

+ 71 - 15
src/me/lennartVH01/game/BasicAbbaGame.java

@@ -3,12 +3,11 @@ package me.lennartVH01.game;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-
+import me.lennartVH01.CollectionHandler;
 import me.lennartVH01.Config;
 import me.lennartVH01.Messages;
 import me.lennartVH01.Permission;
 import me.lennartVH01.util.ChatUtil;
-import me.lennartVH01.util.Tuple2;
 import net.minecraft.server.v1_16_R2.ChatComponentText;
 import net.minecraft.server.v1_16_R2.IChatBaseComponent;
 
@@ -82,9 +81,9 @@ public class BasicAbbaGame implements AbbaGame{
 		}
 	}
 	private void clockTickRunning(){
-		if(timeLeft <= 0)
+		if(timeLeft <= 0){
 			endGame();
-		else{
+		}else{
 			timerScore.setScore(timeLeft);
 			timeLeft--;
 		}
@@ -121,19 +120,19 @@ public class BasicAbbaGame implements AbbaGame{
 				totalItems[i] += score.count[i];
 			}
 		}
-		ArrayList<Tuple2<ItemStack, Integer>> listCollected = new ArrayList<Tuple2<ItemStack, Integer>>();
+		ArrayList<CollectionInfo> listCollected = new ArrayList<CollectionInfo>();
 		
 		for(int i = 0; i < itemValues.length; i++){
 			if(totalItems[i] > 0){
-				listCollected.add(new Tuple2<ItemStack, Integer>(itemValues[i].asItemStack(), totalItems[i]));
+				listCollected.add(new CollectionInfo(itemValues[i].asItemStack(), totalItems[i]));
 			}
 		}
 		if(listCollected.size() > 0){
 			IChatBaseComponent message = new ChatComponentText("");
 			
 			for(int i = 0; i < listCollected.size(); i++){
-				message.getSiblings().add(ChatUtil.stackToChat(listCollected.get(i).arg1));
-				String countMsg = ": " + listCollected.get(i).arg2;
+				message.getSiblings().add(ChatUtil.stackToChat(listCollected.get(i).item));
+				String countMsg = ": " + listCollected.get(i).count;
 				if(i < listCollected.size() - 1){
 					countMsg += "\n";
 				}
@@ -150,9 +149,61 @@ public class BasicAbbaGame implements AbbaGame{
 			scoreboardScore.setScore(score.total);
 			
 		}
+		
+		if(Config.redistributionEnabled){
+			double[] distributionFractions = getRedistributionFractions(scores.size());
+			
+			int[] leftOverItems = new int[totalItems.length];
+			for(int i = 0; i < totalItems.length; i++){
+				leftOverItems[i] = totalItems[i];
+			}
+			
+			for(int curPlayer = 1; curPlayer < scores.size(); curPlayer++){
+				List<CollectionInfo> allottedItems = new ArrayList<CollectionInfo>();
+				
+				double allottedFraction = distributionFractions[curPlayer];
+				for(int i = 0; i < totalItems.length; i++){
+					int itemsForThisPlayer = (int) (allottedFraction * totalItems[i]);
+					if(itemsForThisPlayer > 0){
+						allottedItems.add(new CollectionInfo(itemValues[i].asItemStack(), itemsForThisPlayer));
+						leftOverItems[i] -= itemsForThisPlayer;
+					}
+				}
+				CollectionHandler.pushItemsForCollection(scores.get(curPlayer).player, allottedItems);
+			}
+			// give left over items to player #1, due to rounding this will be rounded up
+			List<CollectionInfo> allottedItems = new ArrayList<CollectionInfo>();
+			for(int i = 0; i < totalItems.length; i++){
+				int itemsForThisPlayer = leftOverItems[i];
+				if(itemsForThisPlayer > 0){
+					allottedItems.add(new CollectionInfo(itemValues[i].asItemStack(), itemsForThisPlayer));
+				}
+			}
+			CollectionHandler.pushItemsForCollection(scores.get(0).player, allottedItems);
+		}
 	}
 	
-	
+	static double[] getRedistributionFractions(int playerCount){
+		double[] distributionFractions = new double[playerCount];
+		int numberOfLeaderboardPlayers = Math.min(playerCount, Config.topReturns.length);
+		int numberOfNonLeaderboardPlayers = Math.max(playerCount - Config.topReturns.length, 0);
+		
+		int totalValue = Config.otherPlayersValue * (Config.otherPlayersShare ? 1 : numberOfNonLeaderboardPlayers);
+		
+		for(int i = 0; i < numberOfLeaderboardPlayers; i++) totalValue += Config.topReturns[i];
+		for(int i = 0; i < numberOfLeaderboardPlayers; i++){
+			distributionFractions[i] = ((double) Config.topReturns[i]) / totalValue;
+		}
+		if(numberOfNonLeaderboardPlayers >= 1){
+			double otherPlayerFraction = (Config.otherPlayersShare ? (double) Config.otherPlayersValue : ((double) Config.otherPlayersValue) / numberOfNonLeaderboardPlayers);
+			
+			for(int i = Config.topReturns.length; i < playerCount; i++){
+				distributionFractions[i] = otherPlayerFraction;
+			}
+		}
+		
+		return distributionFractions;
+	}
 	
 	@Override
 	public boolean join(final Player p){
@@ -169,12 +220,7 @@ public class BasicAbbaGame implements AbbaGame{
 			if(!illegalItems.isEmpty()){
 				p.sendMessage(Messages.errorContraband);
 				for(ItemStack stack:illegalItems){
-					IChatBaseComponent chatStack = ChatUtil.stackToChat(stack);
-					IChatBaseComponent chatText = new ChatComponentText("§c - ");
-					chatText.getSiblings().add(chatStack);
-					
-					ChatUtil.send(p, chatText);
-					
+					ChatUtil.sendItemStack(p, stack, "§c - ");
 				}
 				return false;
 			}
@@ -319,6 +365,16 @@ public class BasicAbbaGame implements AbbaGame{
 				score.total += itemValues[i].getValue() * score.count[i];
 				totalItems[i] += score.count[i];
 			}
+			
+			if(Config.redistributionEnabled){
+				for(StackTester tester : itemValues){
+					for(ItemStack invItem : p.getInventory().getContents()){
+						if(invItem != null && tester.isSimilar(invItem)){
+							p.getInventory().remove(invItem);
+						}
+					}
+				}
+			}
 		}
 		
 		scores.sort((s1, s2) -> {

+ 13 - 0
src/me/lennartVH01/game/CollectionInfo.java

@@ -0,0 +1,13 @@
+package me.lennartVH01.game;
+
+import org.bukkit.inventory.ItemStack;
+
+public class CollectionInfo {
+	public ItemStack item;
+	public int count;
+	
+	public CollectionInfo(ItemStack item, int count){
+		this.item = item;
+		this.count = count;
+	}
+}

+ 8 - 0
src/me/lennartVH01/util/ChatUtil.java

@@ -1,5 +1,6 @@
 package me.lennartVH01.util;
 
+import net.minecraft.server.v1_16_R2.ChatComponentText;
 import net.minecraft.server.v1_16_R2.ChatMessageType;
 import net.minecraft.server.v1_16_R2.IChatBaseComponent;
 import net.minecraft.server.v1_16_R2.PacketPlayOutChat;
@@ -25,4 +26,11 @@ public class ChatUtil {
 	public static String getName(org.bukkit.inventory.ItemStack stack){
 		return CraftItemStack.asNMSCopy(stack).getItem().getName() + ".name";
 	}
+	public static void sendItemStack(Player player, org.bukkit.inventory.ItemStack item, String prefix){
+		IChatBaseComponent chatStack = stackToChat(item);
+		IChatBaseComponent chatText = new ChatComponentText(prefix);
+		chatText.getSiblings().add(chatStack);
+		
+		send(player, chatText);
+	}
 }

+ 0 - 10
src/me/lennartVH01/util/Tuple2.java

@@ -1,10 +0,0 @@
-package me.lennartVH01.util;
-
-public class Tuple2<S,U>{
-	public S arg1;
-	public U arg2;
-	public Tuple2(S arg1, U arg2){
-		this.arg1 = arg1;
-		this.arg2 = arg2;
-	}
-}

+ 0 - 12
src/me/lennartVH01/util/Tuple3.java

@@ -1,12 +0,0 @@
-package me.lennartVH01.util;
-
-public class Tuple3<S, U, V>{
-	public S arg1;
-	public U arg2;
-	public V arg3;
-	public Tuple3(S arg1, U arg2, V arg3){
-		this.arg1 = arg1;
-		this.arg2 = arg2;
-		this.arg3 = arg3;
-	}
-}

+ 0 - 15
src/me/lennartVH01/util/ValuedObject.java

@@ -1,15 +0,0 @@
-package me.lennartVH01.util;
-
-public class ValuedObject<T> {
-	int value;
-	T object;
-	
-	public ValuedObject(int value, T object){
-		this.value = value;
-		this.object = object;
-	}
-	public void setValue(int value){this.value = value;}
-	public int getValue(){return value;}
-	public void setObject(T object){this.object = object;}
-	public T getObject(){return object;}
-}