/*
* Copyright 2015 Demigods RPG
* Copyright 2015 Alexander Chauncey
* Copyright 2015 Alex Bennett
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.demigodsrpg.battle;
import com.demigodsrpg.DGData;
import com.demigodsrpg.family.Family;
import com.demigodsrpg.model.Participant;
import com.demigodsrpg.model.PlayerModel;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class Battle {
private final String id;
private ConcurrentMap<String, BattleMetaData> involved;
private Location startLocation;
private long startTimeMillis;
private long lastInteract;
private long endTimeMillis;
// -- CONSTRUCTORS -- //
public Battle() {
id = UUID.randomUUID().toString();
involved = new ConcurrentHashMap<>();
}
public Battle(Participant... participants) {
id = UUID.randomUUID().toString();
if (participants.length < 1) {
throw new IllegalArgumentException("A battle needs at least 1 participant to make sense.");
}
involved = new ConcurrentHashMap<>();
for (Participant participant : participants) {
involved.put(participant.getPersistentId(), new BattleMetaData());
}
startLocation = participants[0].getLocation();
startTimeMillis = System.currentTimeMillis();
lastInteract = System.currentTimeMillis();
DGData.BATTLE_R.register(this);
}
// -- GETTERS -- //
public String getId() {
return id;
}
public ConcurrentMap<String, BattleMetaData> getInvolved() {
return involved;
}
public Location getStartLocation() {
return startLocation;
}
public long getStartTimeMillis() {
return startTimeMillis;
}
public long getLastInteract() {
return lastInteract;
}
public long getEndTimeMillis() {
return endTimeMillis;
}
public boolean isInvolved(Participant participant) {
return involved.keySet().contains(participant.getPersistentId());
}
public boolean isInvolved(Player player) {
PlayerModel model = DGData.PLAYER_R.fromPlayer(player);
return isInvolved(model);
}
// -- MUTATORS -- //
public void setStartLocation(Location location) {
this.startLocation = location;
}
public void setStartTimeMillis(long startTimeMillis) {
this.startTimeMillis = startTimeMillis;
this.lastInteract = startTimeMillis;
}
public void setEndTimeMillis(long endTimeMillis) {
this.endTimeMillis = endTimeMillis;
}
public void hit(Participant attacking, Participant hit) {
putIfAbsent(attacking, hit);
if (okayToHit(attacking, hit)) {
involved.get(attacking.getPersistentId()).hits++;
}
lastInteract = System.currentTimeMillis();
DGData.BATTLE_R.register(this);
}
public void deny(Participant attacking, Participant target, Participant denier) {
putIfAbsent(attacking, target, denier);
if (!attacking.getFamily().equals(denier.getFamily()) && okayToHit(attacking, target)) {
involved.get(denier.getPersistentId()).denies++;
}
lastInteract = System.currentTimeMillis();
DGData.BATTLE_R.register(this);
}
public void assist(Participant attacking, Participant hit, Participant assistant) {
putIfAbsent(attacking, hit, assistant);
if (!attacking.getFamily().equals(assistant.getFamily()) && okayToHit(attacking, hit)) {
involved.get(assistant.getPersistentId()).assists++;
}
lastInteract = System.currentTimeMillis();
DGData.BATTLE_R.register(this);
}
public void kill(Participant attacking, Participant killed) {
putIfAbsent(attacking, killed);
if (attacking.getFamily().equals(killed.getFamily())) {
involved.get(attacking.getPersistentId()).teamKills++;
attacking.addTeamKill();
} else {
involved.get(attacking.getPersistentId()).kills++;
}
lastInteract = System.currentTimeMillis();
die(killed);
}
public void die(Participant dead) {
putIfAbsent(dead);
involved.get(dead.getPersistentId()).deaths++;
DGData.BATTLE_R.register(this);
}
public Report end() {
endTimeMillis = System.currentTimeMillis();
for (Map.Entry<String, BattleMetaData> entry : involved.entrySet()) {
Participant participant = DGData.PLAYER_R.fromId(entry.getKey()); // FIXME This restricts to players
participant.reward(entry.getValue());
}
DGData.BATTLE_R.unregister(this);
return new Report(this);
}
// -- PRIVATE HELPER METHODS -- //
private boolean okayToHit(Participant attacking, Participant defending) {
return Family.NEUTRAL.equals(attacking.getFamily()) ||
Family.NEUTRAL.equals(defending.getFamily()) ||
Family.EXCOMMUNICATED.equals(attacking.getFamily()) ||
Family.EXCOMMUNICATED.equals(defending.getFamily()) ||
!attacking.getFamily().equals(defending.getFamily());
}
private void putIfAbsent(Participant... toPut) {
for (Participant participant : toPut) {
involved.putIfAbsent(participant.getPersistentId(), new BattleMetaData());
}
}
}