This site requires JavaScript, please enable it in your browser!
Greenfoot back
Honza
Honza wrote ...

2021/1/18

Save world to file

Honza Honza

2021/1/18

#
Hello, I have a minor problem that I need to help with. I have a world which I am saving to file, but when I try to load (deserialize) it then there's this exception "Caused by: java.io.InvalidClassException: greenfoot.SaboterWorld; no valid constructor". I have no idea what to do with it, I tried to create no-arg constructor in SaboterWorld with super inside of it, but it doesn't work for me. I tried to make every class Serializable. I put this "private static final long serialVersionUID = 1L;" to every class, but still nothing. I would appreciate any kind of help or advice. Thank you in advance. :)
danpost danpost

2021/1/19

#
Remove everything you tried and show entire SaboterWorld class codes (copy/paste). Also, if it does not extend the World class directly, show what it extends as well.
Honza Honza

2021/1/19

#
Here it is. public class SaboterWorld extends World implements Serializable { private static final long serialVersionUID = 1L; RoundManager rm = new RoundManager(); Actor nextTurnActor; /** * UX feature, slow UI generate when printed for the first time */ public boolean firstTime = false; private Actor activeCard = new WayActor("what"); public Actor getActiveCard() { return activeCard; } public void setActiveCard(Actor activeCard) { this.activeCard = activeCard; } Actor deckActor, trashActor; LabelActor labelActor; LabelActor labelManual; Package deck = new Package(); Color transparent = new Color(1f, 1f, 1f, 0f); public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } int index; Boolean trashed = false; Boolean useCard = false; Boolean seeEndingCard = false; List<Player> playersList; int numberOfPlayers; int maxRounds = 3; static int roundCounter = 1; int round; public SaboterWorld(){ super(11, 7, 85); } public SaboterWorld(int numberOfPlayers, List<Player> players) { super(11, 7, 85); setBackground("bcg.png"); SaboteurGame saboteurGame = new SaboteurGame(); playersList = players; this.round += roundCounter(); rm.setPlayers(playersList); rm.setActivePlayer(playersList.get(0)); this.numberOfPlayers = numberOfPlayers; rm.getTable().generateStartingEndingCards(); rm.dealCards(deck, playersList); /* GENERATE BASIC BLANK MAP */ generateBlankMap(); generateStartingCard(); generateEndingCards(); generateUI(); labelManual = new ManualActor(getSaboterWorld()); addObject(labelManual, this.getWidth() - 1, 0); addObject(new SaveButton(this), this.getWidth() - 2, 0); deckActor = new DeckActor("Card"); trashActor = new DeckActor("kos"); labelActor = new LabelActor(Integer.toString(deck.getDrawDeck().size()), 50, 20, 60, Color.white, transparent); addObject(deckActor, 10, 5); addObject(labelActor, 10, 5); addObject(trashActor, 10, 6); printInventory(); //cards in hand } private void nextTurn() { removeObjects(getObjectsAt(9, 5, null)); System.out.println("next turn pressed"); rm.addTurn(); removeObjects(getObjectsAt(this.getWidth() - 2, 1, null)); removeObjects(getObjectsAt(this.getWidth() - 2, 2, null)); removeObjects(getObjectsAt(this.getWidth() - 1, 3, null)); removeObjects(getObjectsAt(this.getWidth() - 2, 3, null)); removeObjects(getObjectsAt(this.getWidth() - 1, 4, null)); removeObjects(getObjectsAt(this.getWidth() - 2, 4, null)); setSeeEndingCard(false); firstTime = true; printInventory(); firstTime = false; generateUI(); trashed = false; } public static synchronized int roundCounter(){ return roundCounter++; } public void removeUI(){ removeObjects(getObjectsAt(this.getWidth() - 2, 2, null)); removeObjects(getObjectsAt(this.getWidth() - 1, 3, null)); removeObjects(getObjectsAt(this.getWidth() - 2, 3, null)); removeObjects(getObjectsAt(this.getWidth() - 1, 4, null)); removeObjects(getObjectsAt(this.getWidth() - 2, 1, null)); removeObjects(getObjectsAt(this.getWidth() - 2, 4, null)); } public SaboterWorld getSaboterWorld() { return this; } @Override public void act() { if (rm.getActivePlayer().getHand().size() >= 9) { if (getObjectsAt(9, 5, null).size() == 0) { var tooMuchCards = new LabelActor("Too many\ncards in\nhand", 18, 100, 100, Color.black, transparent); addObject(tooMuchCards, 9, 5); } } if (mouseClicked(deckActor) || mouseClicked(labelActor)) { removeObject(labelActor); if (rm.getActivePlayer().getHand().size() >= 9) { System.out.println("Too much cards in hand"); //var tooMuchCards = new LabelActor("Too much\ncards", 18, 20, 60, Color.black, transparent); //addObject(tooMuchCards, 9, 5); //delay(150); } else { rm.getActivePlayer().addToHand(deck.drawCard(), deck); } labelActor = new LabelActor(Integer.toString(deck.getDrawDeck().size()), 50, 20, 60, Color.white, transparent); addObject(labelActor, 10, 5); printInventory(); //todo naxt turn label se vymaze //todo delay delay(100); if (getUseCard()) { setUseCard(false); } nextTurn(); } if (mouseClicked(trashActor)) { if (!trashed && getIndex() != -1) { System.out.println(index); rm.getActivePlayer().throwOutHand(index); printInventory(); setIndex(-1); } trashed = true; } } public int getRound() { return round; } public Boolean getUseCard() { return useCard; } public void setUseCard(Boolean useCard) { this.useCard = useCard; } /** * Generates Starting card * * @author xderynk * @version etapa 4 */ private void generateStartingCard() { BasicCard starting = new BasicCard("Starting"); addObject(starting, rm.getTable().getStartingCards().get(0).getxCoordinate(), rm.getTable().getStartingCards().get(0).getyCoordinate()); } private void generateBlankMap() { // minus 2 bc last 2 rows and cols are reserved for UI for (int i = 0; i < this.getWidth() - 2; i++) { for (int j = 0; j < this.getHeight() - 2; j++) { MapActor actor = new MapActor(this); addObject(actor, i, j); } } } /** * @author xnguyen4 * @version etapa 4 */ public void generateUI() { addObject(new LabelActor(rm.getActivePlayer().getId()), this.getWidth() - 2, 1); // zatim pouzity pevny string, jelikoz hrace to jeste negeneruje, takze active player je nullptr addObject(new LabelActor("Body: " + Integer.toString(rm.getActivePlayer().getPoints())), this.getWidth() - 2, 2); //vsecko zatim napevno addObject(new LabelActor("Role:"), this.getWidth() - 2, 3); addObject(new LabelActor(rm.getActivePlayer().getPlayerClass()), this.getWidth() - 1, 3); addObject(new LabelActor("Hrat: "), this.getWidth() - 2, 4); addObject(new LabelActor(Boolean.toString(rm.getActivePlayer().isCanPlay())), this.getWidth() - 1, 4); } public class DeckActor extends Actor implements Serializable{ public DeckActor(String cardTexture) { setImage("images/" + cardTexture + ".png"); } @Override public void act() { if (mouseClicked(this)) { } } } /** * Generates ending cards, for now, cards are visible for testing * * @author xderynk * @version etapa 4 */ private void generateEndingCards() { EndingCardsActor end1 = new EndingCardsActor(rm.getTable().getEndingCards().get(0).getType()); EndingCardsActor end2 = new EndingCardsActor(rm.getTable().getEndingCards().get(1).getType()); EndingCardsActor end3 = new EndingCardsActor(rm.getTable().getEndingCards().get(2).getType()); addObject(end1, rm.getTable().getEndingCards().get(0).getxCoordinate(), rm.getTable().getEndingCards().get(0).getyCoordinate()); addObject(end2, rm.getTable().getEndingCards().get(1).getxCoordinate(), rm.getTable().getEndingCards().get(1).getyCoordinate()); addObject(end3, rm.getTable().getEndingCards().get(2).getxCoordinate(), rm.getTable().getEndingCards().get(2).getyCoordinate()); } public static class BasicCard extends Actor { public BasicCard(String cardTexture) { setImage("images/" + cardTexture + ".png"); } } /** * @author xnguyen4 * @version etapa 5 */ public class WayActor extends Actor implements Serializable{ //wayActor lives in hand String cardTexture; public WayActor(String cardTexture) { this.cardTexture = cardTexture; if (cardTexture.isEmpty()) { setImage("images/what.png"); } else { setImage("images/" + cardTexture + ".png"); } } @Override public void act() { if (!getActiveCard().equals(this) && getIndex() != this.getX()) { setImage("images/" + cardTexture + ".png"); } if (mouseClicked(this)) { setActiveCard(this); setIndex(this.getX()); try { setImage("images/active/" + cardTexture + ".png"); } catch (Exception e) { setImage("images/" + cardTexture + ".png"); } //rm.setActive(rm.getActivePlayer().getHand().get(index)); } } } /** * @author xnguyen4 * @version etapa 5 */ public class ActionActor extends Actor implements Serializable{ int count = 0; String cardTexture; public ActionActor(String cardTexture) { setImage("images/" + cardTexture + ".png"); this.cardTexture = cardTexture; } @Override public void act() { if (!getActiveCard().equals(this) && getIndex() != this.getX()) { setImage("images/" + cardTexture + ".png"); } if (mouseClicked(this)) { setActiveCard(this); try { setImage("images/active/" + cardTexture + ".png"); } catch (Exception e) { setImage("images/" + cardTexture + ".png"); } } if (mouseClicked(this) && !getUseCard()) { if (getIndex() != this.getX()) { count = 0; } setIndex(this.getX()); count++; if (count == 2) { setWorld(new ChoosePlayerWorld(getSaboterWorld(), playersList)); setUseCard(true); count = 0; } } else if (mouseClicked(this) && getUseCard()) { setIndex(this.getX()); } } } /** * @author xnguyen4 * @version etapa 5 */ public class MapCheckActor extends Actor implements Serializable{ int count = 0; String cardTexture; public MapCheckActor(String cardTexture) { setImage("images/" + cardTexture + ".png"); this.cardTexture = cardTexture; } @Override public void act() { if (!getActiveCard().equals(this) && getIndex() != this.getX()) { setImage("images/" + cardTexture + ".png"); } if (mouseClicked(this)) { setActiveCard(this); try { setImage("images/active/" + cardTexture + ".png"); } catch (Exception e) { setImage("images/" + cardTexture + ".png"); } } if (mouseClicked(this) && !getUseCard()) { if (getIndex() != this.getX()) { count = 0; } setIndex(this.getX()); count++; if (count == 2) { setUseCard(true); setSeeEndingCard(true); rm.getActivePlayer().getHand().remove(getIndex()); printInventory(); count = 0; } } else if (mouseClicked(this) && getUseCard()) { setIndex(this.getX()); } } } /* public void resetEndingCard(){ EndingCardsActor removeObjects(getObjectsAt(this.getWidth() - 2, 2, null)); addObject(, this.getWidth() - 2, 2); }*/ public Boolean getSeeEndingCard() { return seeEndingCard; } public void setSeeEndingCard(Boolean seeEndingCard) { this.seeEndingCard = seeEndingCard; } /** * @author xderynk * @version etapa 4 */ void printInventory() { for (int row = 0; row < getWidth() - 1; row++) { removeObjects(getObjectsAt(row, getHeight() - 2, null)); } for (int row = 0; row < getWidth() - 1; row++) { removeObjects(getObjectsAt(row, getHeight() - 1, null)); } int x = 0; for (int j = 0, i = 0; j < rm.getActivePlayer().getHand().size(); j++, i++) { if (i >= getWidth() - 2) { WayActor way = new WayActor(rm.getActivePlayer().getHand().get(j).getType()); addObject(way, x, 5); x++; if (firstTime) { delay(4); } } else { if (rm.getActivePlayer().getHand().get(j).isTool()) { ActionActor action = new ActionActor(rm.getActivePlayer().getHand().get(j).getType()); addObject(action, i, getHeight()); if (firstTime) { delay(4); } } else if (rm.getActivePlayer().getHand().get(j).isMap()) { MapCheckActor map = new MapCheckActor(rm.getActivePlayer().getHand().get(j).getType()); addObject(map, i, getHeight()); if (firstTime) { delay(4); } } else { WayActor way = new WayActor(rm.getActivePlayer().getHand().get(j).getType()); addObject(way, i, getHeight()); if (firstTime) { delay(4); } } } } } public class EndingCardsActor extends Actor implements Serializable{ String cardTexture; EndingCard end; boolean reachedEnd = false; int x, y; Gold nugget; boolean reachedEndingCard = false; public EndingCardsActor(String cardTexture) { this.cardTexture = cardTexture; } public boolean isReachedEndingCard() { return reachedEndingCard; } public void setReachedEndingCard(boolean reachedEndingCard) { this.reachedEndingCard = reachedEndingCard; } @Override public void act() { for(int i = 0; i < rm.getTable().getEndingCards().size(); i++) { end = (EndingCard) rm.getTable().getEndingCards().get(i); if(rm.getTable().getEndingCards().isEmpty()){ break; }else { if (end.isReached()) { reachedEnd = true; y = end.getyCoordinate(); x = i; } } } if(mouseClicked(this) && reachedEnd) { if(this.getY() == y) { setImage("images/" + cardTexture + ".png"); this.setReachedEndingCard(true); if(rm.getTable().getEndingCards().get(x).isGoldCard()){ nugget = (Gold) rm.getTable().getEndingCards().get(x); rm.getActivePlayer().setPoints(nugget.getNugget()); removeUI(); generateUI(); delay(100); if(getRound() != maxRounds) { for(int i = 0; i < playersList.size(); i++){ for(int j = 1; j < playersList.get(i).getHand().size(); j++){ playersList.get(i).removeHand(); } } setWorld(new SaboterWorld(new SaboteurGame(), numberOfPlayers, playersList)); }else { System.out.println("END"); // fixme zde bude kod na leaderboard } } rm.getTable().getEndingCards().remove(x); } }else if(!reachedEnd) { setImage("images/Card.png"); setReachedEndingCard(false); } if (mouseClicked(this) && getSeeEndingCard() && !isReachedEndingCard()) { setImage("images/" + cardTexture + ".png"); delay(100); setImage("images/Card.png"); setSeeEndingCard(false); } } } }
Honza Honza

2021/1/19

#
There is " setWorld(new SaboterWorld(new SaboteurGame(), numberOfPlayers, playersList));" in EndingCard Actor, I forgot to erase SaboteurGame because it is not required in constructor. So look at it as if it's not there.
danpost danpost

2021/1/19

#
The 3rd line in act uses var, which is javascript -- not Java.
Honza Honza

2021/1/19

#
I got this error now after changing every var to certain type. "java.io.InvalidClassException: cz.mendelu.greenfoot.SaboterWorld; no valid constructor at java.base/java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:170) at java.base/java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:917) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2203) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1712) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:519) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:477) at cz.mendelu.pjj.SaboteurGame.load(SaboteurGame.java:55) at cz.mendelu.greenfoot.LoadButton.onClick(LoadButton.java:24) at cz.mendelu.greenfoot.ButtonActor.act(ButtonActor.java:23) at greenfoot.core.Simulation.actActor(Simulation.java:604) at greenfoot.core.Simulation.runOneLoop(Simulation.java:562) at greenfoot.core.Simulation.runContent(Simulation.java:221) at greenfoot.core.Simulation.run(Simulation.java:211) java.lang.IllegalArgumentException: Load game failed. at cz.mendelu.pjj.SaboteurGame.load(SaboteurGame.java:62) at cz.mendelu.greenfoot.LoadButton.onClick(LoadButton.java:24) at cz.mendelu.greenfoot.ButtonActor.act(ButtonActor.java:23) at greenfoot.core.Simulation.actActor(Simulation.java:604) at greenfoot.core.Simulation.runOneLoop(Simulation.java:562) at greenfoot.core.Simulation.runContent(Simulation.java:221) at greenfoot.core.Simulation.run(Simulation.java:211) Caused by: java.io.InvalidClassException: cz.mendelu.greenfoot.SaboterWorld; no valid constructor at java.base/java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.java:170) at java.base/java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:917) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2203) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1712) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:519) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:477) at cz.mendelu.pjj.SaboteurGame.load(SaboteurGame.java:55) ... 6 more" As for load buttong it looks like this: public class LoadButton extends ButtonActor implements Serializable { private static final long serialVersionUID = 1L; public LoadButton() { super(" "); setImage("images/Load.png"); } @Override protected void onClick() { String name = Greenfoot.ask("Name of game: "); SaboterWorld world = SaboteurGame.load(name); Greenfoot.setWorld(world); } }
Honza Honza

2021/1/19

#
this is my load method: public static SaboterWorld load(String name){ try { FileInputStream fileIn = new FileInputStream(file(name)); ObjectInputStream objectIn = new ObjectInputStream(fileIn); System.out.println("Save file was successfully loaded"); return (SaboterWorld) objectIn.readObject(); } catch (FileNotFoundException e) { e.printStackTrace(); throw new IllegalArgumentException("Load game failed.", e); } catch (IOException e) { e.printStackTrace(); throw new IllegalArgumentException("Load game failed.", e); } catch (ClassNotFoundException e) { e.printStackTrace(); throw new IllegalArgumentException("Load game failed.", e); } } This "System.out.println("Save file was successfully loaded");" appeared unlike before.
danpost danpost

2021/1/19

#
I have no experience with using Serializable with regards to saving/reading Object types. It may be (and this is just a guess) that Object references within your SaboterWorld class need to be Serializable as well -- and you seem to have quite a few Object reference fields. Better might be to read/write a text file the defines the game and describes its current state. You might make use of the Object.toString method to help organize the data.
Honza Honza

2021/1/19

#
Okay, I will try to look at it this way. Thank you for help. :)
danpost danpost

2021/1/19

#
Honza wrote...
Okay, I will try to look at it this way. Thank you for help. :)
Yeah. You won't need Serializable or serialVersionUID.
You need to login to post a reply.