kalenpw
kalenpw

Reputation: 695

Java serialzing file not writing with Bukkit

So what I'm trying to do is use bukkit and a hashmap to save a player's name and their home location to be able to teleport to later. Currently the User._PlayerHomes hashmap will work, but once the server is shutdown and reloaded there is no file named User.ser and if you try to teleport to a home you previously set there is a lengthy error message I will post here.

[13:20:05 INFO]: Kalenpw issued server command: /khome
[13:20:05 ERROR]: null
org.bukkit.command.CommandException: Unhandled exception executing command 'khome' in plugin TestPlugin v1.0
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) ~[spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at org.bukkit.craftbukkit.v1_9_R1.CraftServer.dispatchCommand(CraftServer.java:645) ~[spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at net.minecraft.server.v1_9_R1.PlayerConnection.handleCommand(PlayerConnection.java:1350) [spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at net.minecraft.server.v1_9_R1.PlayerConnection.a(PlayerConnection.java:1185) [spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at net.minecraft.server.v1_9_R1.PacketPlayInChat.a(PacketPlayInChat.java:45) [spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at net.minecraft.server.v1_9_R1.PacketPlayInChat.a(PacketPlayInChat.java:1) [spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at net.minecraft.server.v1_9_R1.PlayerConnectionUtils$1.run(SourceFile:13) [spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [?:1.7.0_85]
    at java.util.concurrent.FutureTask.run(FutureTask.java:262) [?:1.7.0_85]
    at net.minecraft.server.v1_9_R1.SystemUtils.a(SourceFile:45) [spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at net.minecraft.server.v1_9_R1.MinecraftServer.D(MinecraftServer.java:721) [spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at net.minecraft.server.v1_9_R1.DedicatedServer.D(DedicatedServer.java:400) [spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at net.minecraft.server.v1_9_R1.MinecraftServer.C(MinecraftServer.java:660) [spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at net.minecraft.server.v1_9_R1.MinecraftServer.run(MinecraftServer.java:559) [spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at java.lang.Thread.run(Thread.java:745) [?:1.7.0_85]
Caused by: java.lang.NullPointerException
    at org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer.teleport(CraftPlayer.java:457) ~[spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at org.bukkit.craftbukkit.v1_9_R1.entity.CraftEntity.teleport(CraftEntity.java:225) ~[spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    at com.Khalidor.testplugin.TestPluginCommandExecutor.onCommand(TestPluginCommandExecutor.java:161) ~[?:?]
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[spigot-1.9.2.jar:git-Spigot-5a40365-b70058a]
    ... 15 more

Here is all my relevant code I left out the User.java class and plugin.yml because that doesn't seem to be the issue because it works until the server gets restarted but if that would help let me know and I'll add it:

TestPlugin.java:

//@kalenpw


package com.Khalidor.testplugin;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;

public final class TestPlugin extends JavaPlugin implements Listener {
    MyConfigManager manager;
    MyConfig homesConfig;

    @Override
    public void onEnable() {
        // TODO insert logic for when plugin is enabled
        getLogger().info("onEable has been invoked!");
        getServer().getPluginManager().registerEvents(this, this);

        this.getCommand("KHome").setExecutor(new TestPluginCommandExecutor(this));
        this.getCommand("KSetHome").setExecutor(new TestPluginCommandExecutor(this));
        manager = new MyConfigManager(this);
        homesConfig = manager.getNewConfig("Homes.yml");

        //Deserialize
        try{
            FileInputStream fileIn = new FileInputStream("User.ser");
            ObjectInputStream in = new ObjectInputStream(fileIn);
            User._PlayerHomes = (HashMap<String, Location>) in.readObject();
            in.close();
            fileIn.close();
        }
        catch(IOException i){
            i.printStackTrace();
            return;
        }
        catch(ClassNotFoundException c){
            System.out.print("User class not found");
            c.printStackTrace();
            return;
        }

    }

    @Override
    public void onDisable() {
        // when plugin is disabled
        getLogger().info("onDisable has been invoked");
        //Serialize object
        try{
            FileOutputStream fileOut = new FileOutputStream("User.ser");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(User._PlayerHomes);
            out.close();
            fileOut.close();
            System.out.println("Serialized data has been saved");

        }
        catch(IOException i){
            i.printStackTrace();
        }


    }


}

TestPluginCommandExecutor.java

//@kalenpw
package com.Khalidor.testplugin;

import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;

import com.google.common.io.Files;

public class TestPluginCommandExecutor implements CommandExecutor {
    private final TestPlugin plugin;
    // All commands

    private final String _KHome = "KHome";
    private final String _KSetHome = "KSetHome";

    ArrayList<String> _AllCommands = new ArrayList<String>();

    // Error Messages
    private final String _InvalidArguments = ChatColor.RED + "Error(00): Invalid argument!";
    private final String _InvalidExecutor = ChatColor.RED + "Error(01): Can't execute command";

    //public static HashMap<String, Location> playerHomes = new HashMap<String, Location>();



    public TestPluginCommandExecutor(TestPlugin plugin) {
        this.plugin = plugin;// store info

    }

    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {


        if (cmd.getName().equalsIgnoreCase(_KHome)) {
            if (sender instanceof Player) {
                Player player = (Player) sender;
                //Location homeLocation = playerHomes.get(player.getName());
                Location homeLocation = User._PlayerHomes.get(player.getName());
                player.teleport(homeLocation);
                player.sendMessage("You were teleported home!");
                return true;
            }
        }

        if (cmd.getName().equalsIgnoreCase(_KSetHome)) {
            if (sender instanceof Player) {
                Player player = (Player) sender;
                //playerHomes.put(player.getName(), player.getLocation());
                //homesConfig.
                player.sendMessage("Set your home!");

                User._PlayerHomes.put(player.getName(), player.getLocation());
//              //Save home to file
//              Path playerHomesFile = Paths.get("PlayerHomes.txt");
//              String playerName = player.getName();
//              String playerX = String.valueOf(player.getLocation().getX());
//              String playerY = String.valueOf(player.getLocation().getY());
//              String playerZ = String.valueOf(player.getLocation().getZ());
//
//              
//              //List<String> playerInfo = Arrays.asList(playerName, playerX, playerY, playerZ);
//              ArrayList<String> playerInfo = new ArrayList<String>();
//              playerInfo.add(playerName);
//              
//              
//              //Files.write(playerHomesFile, playerInfo, Charset.forName("UTF-8"));
//              //Files.write(playerHomesFile, playerInfo, Charset.forName("UTF-8"), StandardOpenOption.APPEND);

                return true;


            }
        }

        sender.sendMessage(_InvalidExecutor);
        return false;
    }


}

Thanks for the help! I think I included all the relevant details but if anything is missing or you need clarification let me know and I'll edit.

Edit: The exception when trying to serilize locations:

[14:13:20 WARN]:    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183)
[14:13:20 WARN]:    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
[14:13:20 WARN]:    at java.util.HashMap.writeObject(HashMap.java:1129)
[14:13:20 WARN]:    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[14:13:20 WARN]:    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
[14:13:20 WARN]:    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[14:13:20 WARN]:    at java.lang.reflect.Method.invoke(Method.java:606)
[14:13:20 WARN]:    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1030)
[14:13:20 WARN]:    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495)
[14:13:20 WARN]:    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
[14:13:20 WARN]:    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
[14:13:20 WARN]:    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
[14:13:20 WARN]:    at com.Khalidor.testplugin.TestPlugin.onDisable(TestPlugin.java:90)
[14:13:20 WARN]:    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:294)
[14:13:20 WARN]:    at org.bukkit.plugin.java.JavaPluginLoader.disablePlugin(JavaPluginLoader.java:364)
[14:13:20 WARN]:    at org.bukkit.plugin.SimplePluginManager.disablePlugin(SimplePluginManager.java:424)
[14:13:20 WARN]:    at org.bukkit.plugin.SimplePluginManager.disablePlugins(SimplePluginManager.java:417)
[14:13:20 WARN]:    at org.bukkit.craftbukkit.v1_9_R1.CraftServer.disablePlugins(CraftServer.java:340)
[14:13:20 WARN]:    at net.minecraft.server.v1_9_R1.MinecraftServer.stop(MinecraftServer.java:454)
[14:13:20 WARN]:    at net.minecraft.server.v1_9_R1.MinecraftServer.run(MinecraftServer.java:595)
[14:13:20 WARN]:    at java.lang.Thread.run(Thread.java:745)

Upvotes: 1

Views: 398

Answers (1)

radai
radai

Reputation: 24192

class Location, which you were trying to serialize, is not Serializable, and so you cannot simply dump it to file (as you yourself have found out here)

Your options are either to make Location serializable (if you can and it makes sense. i dont know this API), or serialize something else that is serializable in its place and then upon reading that something else convert that information to a Location.

Upvotes: 1

Related Questions