Implement caminus vault API

This commit is contained in:
Trever Fischer 2012-11-09 12:02:05 -05:00
parent d60c52ed04
commit 6309a32a3e
8 changed files with 342 additions and 1 deletions

View File

@ -19,8 +19,11 @@ package us.camin;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.logging.Level;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Villager;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent;
@ -28,12 +31,20 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerChatEvent; import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.weather.WeatherChangeEvent; import org.bukkit.event.weather.WeatherChangeEvent;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.entity.Arrow;
import org.bukkit.permissions.PermissionAttachment; import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import us.camin.api.ValidationResponse; import us.camin.api.ValidationResponse;
import us.camin.api.ClientEvent; import us.camin.api.ClientEvent;
@ -101,6 +112,7 @@ public class JoinListener implements Listener {
event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, resp.errorMessage); event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, resp.errorMessage);
return; return;
} }
m_plugin.forgetVaultInventory(event.getPlayer());
} }
static public final String SESSION_METADATA_KEY = "caminus-session-id"; static public final String SESSION_METADATA_KEY = "caminus-session-id";
@ -147,4 +159,62 @@ public class JoinListener implements Listener {
m_plugin.sendEvent(evt); m_plugin.sendEvent(evt);
} }
} }
@EventHandler
public void onVaultmasterInteract(PlayerInteractEntityEvent event) {
System.out.println("Interacted with someone!");
ArrayList<Villager> vaultmasters = m_plugin.vaultmasters();
Villager vaultmaster = null;
boolean found = false;
for(Villager v : vaultmasters) {
if (event.getRightClicked() == v) {
System.out.println("It was one of ours!");
event.setCancelled(true);
found = true;
vaultmaster = v;
break;
}
}
if (!found)
return;
Inventory inv;
try {
inv = m_plugin.vaultInventory(event.getPlayer());
} catch (IOException e) {
log.log(Level.SEVERE, "Couldn't fetch user's vault!", e);
event.getPlayer().sendMessage("Couldn't fetch your vault! api.camin.us might be down.");
return;
}
event.getPlayer().openInventory(inv);
}
@EventHandler
public void onVaultmasterInventoryChange(InventoryCloseEvent event) {
Player p = (Player)event.getPlayer();
try {
m_plugin.saveVault(p, m_plugin.vaultInventory(p));
} catch (IOException e) {
log.log(Level.SEVERE, "Couldn't save user's vault!", e);
p.sendMessage("Your vault couldn't be saved to the server!");
p.sendMessage("Your items are still held by the vaultmaster, but might vanish.");
}
}
@EventHandler
public void onVaultmasterAttacked(EntityDamageEvent event) {
Entity target = event.getEntity();
if (target instanceof Villager) {
Villager v = (Villager)target;
if (m_plugin.vaultmasters().contains(target)) {
if (event instanceof EntityDamageByEntityEvent) {
EntityDamageByEntityEvent e = (EntityDamageByEntityEvent)event;
if (e.getDamager() instanceof LivingEntity) {
v.setTarget((LivingEntity)e.getDamager());
//Projectile weapon = v.launchProjectile(Arrow.class);
}
}
v.setHealth(v.getMaxHealth());
}
}
}
} }

View File

@ -28,15 +28,21 @@ import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.ServicePriority; import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.ServicesManager; import org.bukkit.plugin.ServicesManager;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.entity.Villager;
import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.Economy;
import java.util.HashMap; import java.util.HashMap;
import java.util.ArrayList;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.logging.Level; import java.util.logging.Level;
import java.io.IOException; import java.io.IOException;
import java.util.ListIterator;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import us.camin.api.Server; import us.camin.api.Server;
@ -44,6 +50,8 @@ import us.camin.api.ServerEvent;
import us.camin.api.BroadcastEvent; import us.camin.api.BroadcastEvent;
import us.camin.api.PlayerMessageEvent; import us.camin.api.PlayerMessageEvent;
import us.camin.api.ClientEvent; import us.camin.api.ClientEvent;
import us.camin.api.VaultModifyEvent;
import us.camin.api.PlayerVaultSlot;
import org.json.JSONException; import org.json.JSONException;
public class Plugin extends JavaPlugin { public class Plugin extends JavaPlugin {
@ -53,7 +61,9 @@ public class Plugin extends JavaPlugin {
private JoinListener m_listener; private JoinListener m_listener;
private MOTDCommand m_motdCommand; private MOTDCommand m_motdCommand;
private VomitCommand m_vomitCommand; private VomitCommand m_vomitCommand;
private VaultCommand m_vaultCommand;
private ServerEventPoller m_eventPoll; private ServerEventPoller m_eventPoll;
private ArrayList<Villager> m_vaultmasters;
public Server api() { public Server api() {
return m_api; return m_api;
@ -63,6 +73,9 @@ public class Plugin extends JavaPlugin {
log.info("[Caminus] Plugin disabled"); log.info("[Caminus] Plugin disabled");
m_eventPoll.stop(); m_eventPoll.stop();
m_api = null; m_api = null;
for (Villager v : m_vaultmasters) {
v.remove();
}
} }
public void handleEvent(ServerEvent e) { public void handleEvent(ServerEvent e) {
@ -82,6 +95,26 @@ public class Plugin extends JavaPlugin {
return null; return null;
} }
}); });
} else if (e instanceof VaultModifyEvent) {
final VaultModifyEvent evt = (VaultModifyEvent)(e);
getServer().getScheduler().callSyncMethod(this, new Callable<Void>() {
public Void call() {
Inventory inv;
try {
inv = vaultInventory(getServer().getPlayer(evt.player));
} catch (IOException e) {
return null;
}
for (PlayerVaultSlot s : evt.contents) {
if (s.quantity == -1) {
inv.clear(s.position);
} else {
inv.setItem(s.position, new ItemStack(s.item, s.quantity, s.damage, s.data));
}
}
return null;
}
});
} }
try { try {
m_api.notifyEventHandled(e); m_api.notifyEventHandled(e);
@ -102,7 +135,17 @@ public class Plugin extends JavaPlugin {
} }
} }
public void addVaultmaster(Villager v) {
m_vaultmasters.add(v);
}
public ArrayList<Villager> vaultmasters() {
return m_vaultmasters;
}
public void onEnable() { public void onEnable() {
m_vaultmasters = new ArrayList<Villager>();
m_vaultInventories = new HashMap<String, Inventory>();
PluginManager pm = this.getServer().getPluginManager(); PluginManager pm = this.getServer().getPluginManager();
m_listener = new JoinListener(this); m_listener = new JoinListener(this);
Configuration conf = getConfig(); Configuration conf = getConfig();
@ -127,6 +170,9 @@ public class Plugin extends JavaPlugin {
m_vomitCommand = new VomitCommand(this); m_vomitCommand = new VomitCommand(this);
getCommand("vomit").setExecutor(m_vomitCommand); getCommand("vomit").setExecutor(m_vomitCommand);
m_vaultCommand = new VaultCommand(this);
getCommand("vaultmaster").setExecutor(m_vaultCommand);
CommandExecutor economyCommand = new EconomyCommand(this); CommandExecutor economyCommand = new EconomyCommand(this);
getCommand("balance").setExecutor(economyCommand); getCommand("balance").setExecutor(economyCommand);
@ -160,4 +206,50 @@ public class Plugin extends JavaPlugin {
} }
} }
} }
private HashMap<String, Inventory> m_vaultInventories;
public void saveVault(Player p, Inventory inv) throws IOException {
ListIterator<ItemStack> items = inv.iterator();
PlayerVaultSlot[] vault = new PlayerVaultSlot[inv.getSize()];
int i = 0;
while(items.hasNext()) {
ItemStack item = items.next();
PlayerVaultSlot slot = new PlayerVaultSlot();
slot.position = i;
slot.quantity = -1;
if (item != null) {
slot.item = item.getTypeId();
slot.quantity = item.getAmount();
slot.damage = item.getDurability();
slot.data = item.getData().getData();
}
vault[i] = slot;
i++;
}
log.info("Saving "+vault.length+" items to vault for "+p.getName());
try {
m_api.saveVault(p.getName(), vault);
} catch (JSONException e) {
throw new IOException(e);
}
}
public void forgetVaultInventory(Player p) {
if (m_vaultInventories.containsKey(p.getName())) {
m_vaultInventories.remove(p.getName());
}
}
public Inventory vaultInventory(Player p) throws IOException {
if (!m_vaultInventories.containsKey(p.getName())) {
Inventory inv = p.getServer().createInventory(p, InventoryType.CHEST);
m_vaultInventories.put(p.getName(), inv);
PlayerVaultSlot[] vault = m_api.loadVault(p.getName());
for(int i = 0;i<vault.length;i++) {
inv.setItem(vault[i].position, new ItemStack(vault[i].item, vault[i].quantity, vault[i].damage, vault[i].data));
}
}
return m_vaultInventories.get(p.getName());
}
} }

View File

@ -0,0 +1,46 @@
package us.camin;
/*
This file is part of Caminus
Caminus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caminus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Caminus. If not, see <http://www.gnu.org/licenses/>.
*/
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Villager;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.Location;
public class VaultCommand implements CommandExecutor {
private Plugin m_plugin;
public VaultCommand(Plugin p) {
m_plugin = p;
}
public boolean onCommand(CommandSender sender, Command command, String label, String[] split) {
if (sender.hasPermission("caminus.vaultmaster")) {
if (sender instanceof Player) {
Player p = (Player)sender;
Location loc = p.getLocation();
Villager vaultmaster = (Villager)p.getWorld().spawnCreature(loc, EntityType.VILLAGER);
m_plugin.addVaultmaster(vaultmaster);
}
}
return true;
}
}

View File

@ -0,0 +1,28 @@
package us.camin.api;
/*
This file is part of Caminus
Caminus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caminus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Caminus. If not, see <http://www.gnu.org/licenses/>.
*/
public class PlayerVaultSlot {
public int item;
public int quantity;
public int id;
public short damage;
public Byte data;
public int position;
}

View File

@ -301,4 +301,48 @@ public class Server {
} }
return resp; return resp;
} }
public PlayerVaultSlot[] loadVault(String player) throws IOException {
log.info("Opening vault for "+player);
PlayerVaultSlot[] vault;
JSONObject jsonObj = get("server/vault/"+player);
try {
JSONArray items = jsonObj.getJSONArray("items");
vault = new PlayerVaultSlot[items.length()];
for(int i = 0;i<items.length();i++) {
JSONObject slot = items.getJSONObject(i);
vault[i] = new PlayerVaultSlot();
vault[i].item = slot.optInt("item");
vault[i].quantity = slot.optInt("quantity");
vault[i].damage = (short)slot.optInt("damage");
vault[i].data = (byte)slot.optInt("data");
vault[i].position = slot.optInt("position");
}
} catch (JSONException e) {
throw new IOException("JSON parse error", e);
}
return vault;
}
public void saveVault(String player, PlayerVaultSlot[] vault) throws IOException, JSONException {
log.info("Saving vault for "+player);
JSONStringer out = new JSONStringer();
out.object();
out.key("items");
out.array();
for (PlayerVaultSlot item : vault) {
out.object();
out.key("item").value(item.item);
out.key("quantity").value(item.quantity);
out.key("damage").value(item.damage);
out.key("data").value(item.data);
out.key("position").value(item.position);
out.endObject();
}
out.endArray();
out.endObject();
HashMap<String, String> params = new HashMap<String, String>();
params.put("contents", out.toString());
put("server/vault/"+player, params);
}
} }

View File

@ -47,6 +47,8 @@ public class ServerEvent {
return BroadcastEvent.fromJSON(payload, id); return BroadcastEvent.fromJSON(payload, id);
} else if (type.equals("player-message")) { } else if (type.equals("player-message")) {
return PlayerMessageEvent.fromJSON(payload, id); return PlayerMessageEvent.fromJSON(payload, id);
} else if (type.equals("vault-contents")) {
return VaultModifyEvent.fromJSON(payload, id);
} else { } else {
log.log(Level.SEVERE, "Unhandled event type: "+type); log.log(Level.SEVERE, "Unhandled event type: "+type);
return null; return null;

View File

@ -0,0 +1,54 @@
package us.camin.api;
/*
This file is part of Caminus
Caminus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caminus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Caminus. If not, see <http://www.gnu.org/licenses/>.
*/
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;
public class VaultModifyEvent extends ServerEvent {
public PlayerVaultSlot[] contents;
public String player;
public static VaultModifyEvent fromJSON(JSONObject obj, int id) {
VaultModifyEvent ret = new VaultModifyEvent();
ret.player = obj.optString("player");
JSONArray items;
try {
items = obj.getJSONArray("items");
} catch (JSONException e) {
return null;
}
ret.contents = new PlayerVaultSlot[items.length()];
for(int i = 0;i<items.length();i++) {
JSONObject slot;
try {
slot = items.getJSONObject(i);
} catch (JSONException e) {
return null;
}
ret.contents[i] = new PlayerVaultSlot();
ret.contents[i].item = slot.optInt("item");
ret.contents[i].quantity = slot.optInt("quantity");
ret.contents[i].damage = (short)slot.optInt("damage");
ret.contents[i].data = (byte)slot.optInt("data");
ret.contents[i].position = slot.optInt("position");
}
return ret;
}
}

View File

@ -15,6 +15,8 @@ commands:
balance: balance:
description: Displays your balance description: Displays your balance
usage: /<command> usage: /<command>
vaultmaster:
description: Create a vaultmaster NPC at your current location.
permissions: permissions:
caminus.*: caminus.*:
default: op default: op
@ -23,6 +25,7 @@ permissions:
caminus.whitelisted: true caminus.whitelisted: true
caminus.freedoorday: true caminus.freedoorday: true
caminus.vomit: true caminus.vomit: true
caminus.vaultmaster: true
caminus.freedoorday: caminus.freedoorday:
default: false default: false
description: Enables free half door day description: Enables free half door day
@ -32,4 +35,6 @@ permissions:
caminus.whitelisted: caminus.whitelisted:
default: op default: op
description: Allows user to bypass caminus API whitelisting description: Allows user to bypass caminus API whitelisting
caminus.vaultmaster:
default: op
description: Allows creation of vaultmasters, interfaces to the vault system.