game engine, tests and other fixes:

tests: fixed wrong permanent structure for battlefield cards (addCard command);
tests: added docs and additional runtime checks;
game: Modal double-faced cards - improved support, no more other side effects on battlefield;
game: Copy abilities - improved stability and cards support;
game: Player under control - improved stability and related cards support (possible NPE errors, additional runtime checks);
server: fixed bloated logs with game timer;
AI: fixed wrong timer in computer games;
This commit is contained in:
Oleg Agafonov 2024-02-17 19:35:44 +04:00
parent 824e4c6b7a
commit 229e8d3075
35 changed files with 303 additions and 151 deletions

View file

@ -288,6 +288,8 @@ public abstract class GameImpl implements Game {
public void loadCards(Set<Card> cards, UUID ownerId) {
for (Card card : cards) {
if (card instanceof PermanentCard) {
// TODO: impossible use case, can be deleted?
// trying to put permanent card to battlefield
card = ((PermanentCard) card).getCard();
}
@ -2019,11 +2021,10 @@ public abstract class GameImpl implements Game {
// save original copy link (handle copy of copies too)
newBluePrint.setCopy(true, (copyFromPermanent.getCopyFrom() != null ? copyFromPermanent.getCopyFrom() : copyFromPermanent));
CopyEffect newEffect = new CopyEffect(duration, newBluePrint, copyToPermanentId);
newEffect.newId();
newEffect.setApplier(applier);
CopyEffect newCopyEffect = new CopyEffect(duration, newBluePrint, copyToPermanentId);
newCopyEffect.setApplier(applier);
Ability newAbility = source.copy();
newEffect.init(newAbility, this);
newCopyEffect.init(newAbility, this);
// If there are already copy effects with duration = Custom to the same object, remove the existing effects because they no longer have any effect
if (duration == Duration.Custom) {
@ -2037,7 +2038,7 @@ public abstract class GameImpl implements Game {
}
}
}
state.addEffect(newEffect, newAbility);
state.addEffect(newCopyEffect, newAbility);
return newBluePrint;
}
@ -3567,20 +3568,27 @@ public abstract class GameImpl implements Game {
}
@Override
public void cheat(UUID ownerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command, List<Card> exiled) {
public void cheat(UUID ownerId, List<Card> library, List<Card> hand, List<PutToBattlefieldInfo> battlefield, List<Card> graveyard, List<Card> command, List<Card> exiled) {
// fake test ability for triggers and events
Ability fakeSourceAbilityTemplate = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("adding testing cards"));
fakeSourceAbilityTemplate.setControllerId(ownerId);
Player player = getPlayer(ownerId);
if (player != null) {
// init cards
loadCards(ownerId, library);
loadCards(ownerId, hand);
loadCards(ownerId, battlefield);
loadCards(ownerId, battlefield
.stream()
.map(PutToBattlefieldInfo::getCard)
.collect(Collectors.toList())
);
loadCards(ownerId, graveyard);
loadCards(ownerId, command);
loadCards(ownerId, exiled);
// move cards to zones
for (Card card : library) {
player.getLibrary().putOnTop(card, this);
}
@ -3610,10 +3618,10 @@ public abstract class GameImpl implements Game {
getExile().add(card);
}
for (PermanentCard permanentCard : battlefield) {
for (PutToBattlefieldInfo info : battlefield) {
Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy();
fakeSourceAbility.setSourceId(permanentCard.getId());
CardUtil.putCardOntoBattlefieldWithEffects(fakeSourceAbility, this, permanentCard, player);
fakeSourceAbility.setSourceId(info.getCard().getId());
CardUtil.putCardOntoBattlefieldWithEffects(fakeSourceAbility, this, info.getCard(), player, info.isTapped());
}
applyEffects();