Merge remote-tracking branch 'refs/remotes/origin/main'

main
Brett 2023-04-15 20:35:28 -04:00
commit 5ce406f376
4 changed files with 70 additions and 31 deletions

View File

@ -13,30 +13,24 @@ import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Random; import java.util.Random;
public class GameEngine implements Runnable { public class GameEngine {
public static final double GOLD_FACTOR = 5; public static final double GOLD_FACTOR = 5;
public static final double IRON_FACTOR = 1; public static final double IRON_FACTOR = 1;
public static final double WOOD_FACTOR = 0.1; public static final double WOOD_FACTOR = 0.1;
private Player player;
boolean running = true;
private float pillageFactor = 0.5f; private float pillageFactor = 0.5f;
private int currentTime; private int currentTime;
private final Random random = new Random(System.nanoTime()); private final Random random = new Random(System.nanoTime());
public Map map;
public GameDisplay view; public GameDisplay view;
public GameEngine() { public GameEngine() {
player = new Player();
map = generateInitialMap();
} }
public void attackVillage(Map map) { public void attackVillage(Map attacking, Map defending) {
// int defenseiveCounter = 1; // int defenseiveCounter = 1;
// int inhabCounter = 0; // int inhabCounter = 0;
// for (Building b : map.contains) // for (Building b : map.contains)
@ -53,31 +47,31 @@ public class GameEngine implements Runnable {
// this.map.getTownHall().addWood((int) (map.getTownHall().getCurrentWood() * pillageFactor)); // this.map.getTownHall().addWood((int) (map.getTownHall().getCurrentWood() * pillageFactor));
// this.map.getTownHall().addIron((int) (map.getTownHall().getCurrentIron() * pillageFactor)); // this.map.getTownHall().addIron((int) (map.getTownHall().getCurrentIron() * pillageFactor));
// this.map.getTownHall().addGold((int) (map.getTownHall().getCurrentGold() * pillageFactor)); // this.map.getTownHall().addGold((int) (map.getTownHall().getCurrentGold() * pillageFactor));
ChallengeAdapter adapter = new ChallengeAdapter(this.map); ChallengeAdapter adapter = new ChallengeAdapter(attacking);
adapter.attack(map); adapter.attack(defending);
} }
private Map generateInitialMap(){ public Map generateInitialMap(){
return new Map(new CasaDeNarino(1, VillageHallStages.villageStages[0]), 30); return new Map(new CasaDeNarino(1, VillageHallStages.villageStages[0]), 30);
} }
public Map generateMap() { public Map generateMap(Map map) {
Map initialMap = generateInitialMap(); Map initialMap = generateInitialMap();
CasaDeNarino hall = initialMap.getTownHall(); CasaDeNarino hall = initialMap.getTownHall();
// generate a similar town hall // generate a similar town hall
int levelChange = random.nextInt(2) - 1; int levelChange = random.nextInt(2) - 1;
int nextLevel = this.map.getTownHall().getLevel() + levelChange; int nextLevel = map.getTownHall().getLevel() + levelChange;
// only need to change if the new village level is higher than initial // only need to change if the new village level is higher than initial
if (nextLevel > 0) if (nextLevel > 0)
hall.upgrade(VillageHallStages.villageStages[nextLevel]); hall.upgrade(VillageHallStages.villageStages[nextLevel]);
hall.addWood(this.map.getTownHall().getCurrentWood() + random.nextInt(500) - 150); hall.addWood(map.getTownHall().getCurrentWood() + random.nextInt(500) - 150);
hall.addIron(this.map.getTownHall().getCurrentIron() + random.nextInt(500) - 150); hall.addIron(map.getTownHall().getCurrentIron() + random.nextInt(500) - 150);
hall.addGold(this.map.getTownHall().getCurrentGold() + random.nextInt(500) - 150); hall.addGold(map.getTownHall().getCurrentGold() + random.nextInt(500) - 150);
int buildingCount = this.map.contains.size(); int buildingCount = map.contains.size();
int saulGoodMines = 0; int saulGoodMines = 0;
int ironMines = 0; int ironMines = 0;
@ -86,7 +80,7 @@ public class GameEngine implements Runnable {
int cannons = 0; int cannons = 0;
// count buildings in our map // count buildings in our map
for (Building b : this.map.contains){ for (Building b : map.contains){
if (b instanceof SaulGoodMine) if (b instanceof SaulGoodMine)
saulGoodMines++; saulGoodMines++;
else if (b instanceof IronMine) else if (b instanceof IronMine)
@ -145,6 +139,35 @@ public class GameEngine implements Runnable {
return score; return score;
} }
public void updateMap(Map map) {
for (int i = 0; i < map.contains.size(); i++) {
if ((map.contains.get(i) instanceof ResourceBuilding)) {
((ResourceBuilding) map.contains.get(i)).update(map.getTownHall());
}
}
}
public boolean build (Map map, String buildingArg) {
BuildingFactory bfactory = new BuildingFactory();
Building type = bfactory.getBuilding(buildingArg);
return map.build(new Tile(), type);
}
public boolean train (Map map, String inhabitantArgs) {
InhabitantFactory ifactory = new InhabitantFactory();
Inhabitant type = ifactory.getInhabitant(inhabitantArgs);
return map.train(type);
}
public boolean upgradeBuilding (Map map, int buildingIndex) {
return map.upgradeBuilding(buildingIndex);
}
public boolean upgradeInhabitant (Map map, int inhabitantIndex) {
return map.upgradeInhabitant(inhabitantIndex);
}
/*
@Override @Override
public void run() { public void run() {
String in; String in;
@ -156,11 +179,6 @@ public class GameEngine implements Runnable {
Map exploringMap = null; Map exploringMap = null;
boolean deleteMyHeart = true; boolean deleteMyHeart = true;
while (running) { while (running) {
for (Building b : this.map.contains){
if ((b instanceof ResourceBuilding)) {
((ResourceBuilding) b).update(this.map.getTownHall());
}
}
try { try {
if ((in = view.nextInput()) != null) { if ((in = view.nextInput()) != null) {
String[] args = in.split(" "); String[] args = in.split(" ");
@ -249,8 +267,7 @@ public class GameEngine implements Runnable {
if (deleteMyHeart) if (deleteMyHeart)
exploringMap = null; exploringMap = null;
} }
save("test.xml", this.map); } */
}
public void save(String file, Map map){ public void save(String file, Map map){
try (XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(Files.newOutputStream(Paths.get(file))))) { try (XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(Files.newOutputStream(Paths.get(file))))) {

View File

@ -56,7 +56,7 @@ public class Map implements Serializable {
public boolean upgradeBuilding(int buildingIndex) { public boolean upgradeBuilding(int buildingIndex) {
if (buildingIndex >= contains.size()) return false; if (buildingIndex >= contains.size() || buildingIndex < 0) return false;
Building b = contains.get(buildingIndex); Building b = contains.get(buildingIndex);
@ -93,7 +93,7 @@ public class Map implements Serializable {
public boolean upgradeInhabitant(int inhabitantIndex) { public boolean upgradeInhabitant(int inhabitantIndex) {
if (inhabitantIndex >= inhabitants.size()) return false; if (inhabitantIndex >= inhabitants.size() || inhabitantIndex < 0) return false;
Inhabitant i = inhabitants.get(inhabitantIndex); Inhabitant i = inhabitants.get(inhabitantIndex);

View File

@ -16,5 +16,7 @@ public class PacketTable {
public static final byte ACK = 0x3; public static final byte ACK = 0x3;
// messageHeader, UTF8 String with length information (use DOS.writeUTF/DIS.readUTF) // messageHeader, UTF8 String with length information (use DOS.writeUTF/DIS.readUTF)
public static final byte MESSAGE = 0x4; public static final byte MESSAGE = 0x4;
// messageHeader, serial packets with map info
public static final byte MAP_DATA = 0x5;
} }

View File

@ -1,11 +1,16 @@
package ca.cosc3p91.a4.util.network; package ca.cosc3p91.a4.util.network;
import ca.cosc3p91.a4.game.GameEngine; import ca.cosc3p91.a4.game.GameEngine;
import ca.cosc3p91.a4.game.Map;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.rmi.ServerException; import java.rmi.ServerException;
import java.util.*;
import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
public class Server implements Runnable { public class Server implements Runnable {
@ -49,7 +54,7 @@ public class Server implements Runnable {
// the server must handle connection requests while the client's processing thread will handle all other messages // the server must handle connection requests while the client's processing thread will handle all other messages
if (packetID == PacketTable.CONNECT){ if (packetID == PacketTable.CONNECT){
clients.put(++clientAssignmentID, new ConnectedClient(socket, clientID, messageID, receivePacket.getAddress(), receivePacket.getPort())); clients.put(++clientAssignmentID, new ConnectedClient(socket, mainEngine, clientID, messageID, receivePacket.getAddress(), receivePacket.getPort()));
} else if (packetID == PacketTable.DISCONNECT) { } else if (packetID == PacketTable.DISCONNECT) {
if (client == null) if (client == null)
throw new ServerException("Client disconnected with invalid client id! (" + clientID + ")"); throw new ServerException("Client disconnected with invalid client id! (" + clientID + ")");
@ -80,19 +85,32 @@ public class Server implements Runnable {
private final int port; private final int port;
private final Queue<Message.Received> pendingRequests = new PriorityQueue<>(); private final Queue<Message.Received> pendingRequests = new PriorityQueue<>();
private final ReentrantLock requestLock = new ReentrantLock(); private final ReentrantLock requestLock = new ReentrantLock();
private final AtomicBoolean allowUpdate;
private final HashMap<Long, Message.Sent> sentMessages = new HashMap<>(); private final HashMap<Long, Message.Sent> sentMessages = new HashMap<>();
private final DatagramSocket serverSocket; private final DatagramSocket serverSocket;
private final long clientID; private final long clientID;
private volatile boolean running = true; private volatile boolean running = true;
private final Thread processingThread; private final Thread processingThread;
private final Thread gameEngineThread;
private final Map clientMap;
public ConnectedClient(DatagramSocket serverSocket, long clientID, long messageID, InetAddress address, int port){ public ConnectedClient(DatagramSocket serverSocket, GameEngine engine, long clientID, long messageID, InetAddress address, int port){
this.serverSocket = serverSocket; this.serverSocket = serverSocket;
this.address = address; this.address = address;
this.port = port; this.port = port;
this.clientID = clientID; this.clientID = clientID;
this.clientMap = engine.generateInitialMap();
this.allowUpdate = new AtomicBoolean(true);
processingThread = new Thread(this); processingThread = new Thread(this);
processingThread.start(); processingThread.start();
gameEngineThread = new Thread(() -> {
while (true) {
if (this.allowUpdate.get()) {
engine.updateMap(clientMap);
}
}
});
gameEngineThread.start();
sendMessage(new Message.Sent(PacketTable.ACK, clientID, messageID)); sendMessage(new Message.Sent(PacketTable.ACK, clientID, messageID));
} }
@ -129,11 +147,13 @@ public class Server implements Runnable {
requestLock.lock(); requestLock.lock();
if (!pendingRequests.isEmpty()) { if (!pendingRequests.isEmpty()) {
Message.Received request = pendingRequests.remove(); Message.Received request = pendingRequests.remove();
allowUpdate.set(false);
processRequest(request); processRequest(request);
allowUpdate.set(true);
} }
requestLock.unlock(); requestLock.unlock();
for (Map.Entry<Long, Message.Sent> message : sentMessages.entrySet()){ for (HashMap.Entry<Long, Message.Sent> message : sentMessages.entrySet()){
if (message.getValue().getTimeSinceSent().get() > MAX_PACKET_ACK_TIME_SECONDS) { if (message.getValue().getTimeSinceSent().get() > MAX_PACKET_ACK_TIME_SECONDS) {
System.out.println("The server did not process our message, did they receive it?"); System.out.println("The server did not process our message, did they receive it?");
sendMessage(message.getValue()); sendMessage(message.getValue());