mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
Normalize line endings
This commit is contained in:
0
forge-gui/src/main/config/create-dmg
Executable file → Normal file
0
forge-gui/src/main/config/create-dmg
Executable file → Normal file
0
forge-gui/src/main/config/forge.command
Executable file → Normal file
0
forge-gui/src/main/config/forge.command
Executable file → Normal file
0
forge-gui/src/main/config/forge.sh
Executable file → Normal file
0
forge-gui/src/main/config/forge.sh
Executable file → Normal file
0
forge-gui/src/main/config/support/dmg-license.py
Executable file → Normal file
0
forge-gui/src/main/config/support/dmg-license.py
Executable file → Normal file
@@ -1,100 +1,100 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Tail-based by Web Sockets</title>
|
||||
|
||||
|
||||
<link href="css/core.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<script type="text/javascript" src="js/jquery/jquery-1.9.1.min.js"></script>
|
||||
<script type="text/javascript" src="js/observable.js"></script>
|
||||
<script type="text/javascript" src="js/socket.js"></script>
|
||||
<script type='text/javascript' src="js/main.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="title">
|
||||
<span>Your server: <b>ws://</b></span>
|
||||
<input id="ws_uri" type="text" value="localhost:81/" name="uri"/>
|
||||
<button id="connect" name="connect" class="cn">Connect</button>
|
||||
<button id="disconn" name="disconn" class="dc" disabled="disabled">Disconnect</button>
|
||||
</div>
|
||||
<ul class="messages" id='messages'></ul>
|
||||
<div class="packets" id='input'>
|
||||
<span>Raw text to send:</span>
|
||||
<input type="text" name="packet" value="" />
|
||||
<button id="send" class="send">Send</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
if (!window.WebSocket)
|
||||
alert("WebSocket not supported by this browser");
|
||||
|
||||
var server = Socket();
|
||||
var listener = {
|
||||
onOpen : function() {
|
||||
$('#input').slideDown();
|
||||
},
|
||||
|
||||
onMessage : function(m) {
|
||||
if (m.data) {
|
||||
addLi("incoming", m.data);
|
||||
}
|
||||
},
|
||||
|
||||
onClose : function(m) {
|
||||
addLi("error", "Connection was closed (" + m.code + "): " + m.reason);
|
||||
onDisconnectClicked();
|
||||
$('#input').fadeOut();
|
||||
}
|
||||
};
|
||||
server.addObserver(listener);
|
||||
|
||||
function addLi(className, text) {
|
||||
var spanText = document.createElement('li');
|
||||
spanText.className = className;
|
||||
spanText.innerHTML = text;
|
||||
var messageBox = $('#messages')[0];
|
||||
messageBox.appendChild(spanText);
|
||||
messageBox.scrollTop = messageBox.scrollHeight - messageBox.clientHeight;
|
||||
}
|
||||
|
||||
function onConnectClicked() {
|
||||
var uri = $("#ws_uri").val()
|
||||
addLi("connecting", "Connecting to ws://" + uri + " ..." )
|
||||
server.connect(uri);
|
||||
$('#connect').attr("disabled", "disabled")
|
||||
$('#disconn').removeAttr("disabled")
|
||||
|
||||
}
|
||||
|
||||
function onDisconnectClicked() {
|
||||
server.close();
|
||||
$('#disconn').attr("disabled", "disabled")
|
||||
$('#connect').removeAttr("disabled")
|
||||
|
||||
}
|
||||
|
||||
function onSendClicked() {
|
||||
var toSend = $("#input input").val();
|
||||
$("#input input").val("");
|
||||
addLi("outcoming", toSend);
|
||||
server.send(toSend)
|
||||
}
|
||||
|
||||
function onInputKey(event) {
|
||||
if( event.keyCode == 13 )
|
||||
onSendClicked();
|
||||
}
|
||||
|
||||
function onReady() {
|
||||
$('#connect').on("click", onConnectClicked);
|
||||
$('#disconn').on("click", onDisconnectClicked);
|
||||
$('#send').on("click", onSendClicked);
|
||||
$("#input input").on("keypress", onInputKey);
|
||||
}
|
||||
|
||||
$(onReady)
|
||||
</script>
|
||||
|
||||
</body>
|
||||
<html>
|
||||
<head>
|
||||
<title>Tail-based by Web Sockets</title>
|
||||
|
||||
|
||||
<link href="css/core.css" media="all" rel="stylesheet" type="text/css" />
|
||||
<script type="text/javascript" src="js/jquery/jquery-1.9.1.min.js"></script>
|
||||
<script type="text/javascript" src="js/observable.js"></script>
|
||||
<script type="text/javascript" src="js/socket.js"></script>
|
||||
<script type='text/javascript' src="js/main.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="title">
|
||||
<span>Your server: <b>ws://</b></span>
|
||||
<input id="ws_uri" type="text" value="localhost:81/" name="uri"/>
|
||||
<button id="connect" name="connect" class="cn">Connect</button>
|
||||
<button id="disconn" name="disconn" class="dc" disabled="disabled">Disconnect</button>
|
||||
</div>
|
||||
<ul class="messages" id='messages'></ul>
|
||||
<div class="packets" id='input'>
|
||||
<span>Raw text to send:</span>
|
||||
<input type="text" name="packet" value="" />
|
||||
<button id="send" class="send">Send</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
if (!window.WebSocket)
|
||||
alert("WebSocket not supported by this browser");
|
||||
|
||||
var server = Socket();
|
||||
var listener = {
|
||||
onOpen : function() {
|
||||
$('#input').slideDown();
|
||||
},
|
||||
|
||||
onMessage : function(m) {
|
||||
if (m.data) {
|
||||
addLi("incoming", m.data);
|
||||
}
|
||||
},
|
||||
|
||||
onClose : function(m) {
|
||||
addLi("error", "Connection was closed (" + m.code + "): " + m.reason);
|
||||
onDisconnectClicked();
|
||||
$('#input').fadeOut();
|
||||
}
|
||||
};
|
||||
server.addObserver(listener);
|
||||
|
||||
function addLi(className, text) {
|
||||
var spanText = document.createElement('li');
|
||||
spanText.className = className;
|
||||
spanText.innerHTML = text;
|
||||
var messageBox = $('#messages')[0];
|
||||
messageBox.appendChild(spanText);
|
||||
messageBox.scrollTop = messageBox.scrollHeight - messageBox.clientHeight;
|
||||
}
|
||||
|
||||
function onConnectClicked() {
|
||||
var uri = $("#ws_uri").val()
|
||||
addLi("connecting", "Connecting to ws://" + uri + " ..." )
|
||||
server.connect(uri);
|
||||
$('#connect').attr("disabled", "disabled")
|
||||
$('#disconn').removeAttr("disabled")
|
||||
|
||||
}
|
||||
|
||||
function onDisconnectClicked() {
|
||||
server.close();
|
||||
$('#disconn').attr("disabled", "disabled")
|
||||
$('#connect').removeAttr("disabled")
|
||||
|
||||
}
|
||||
|
||||
function onSendClicked() {
|
||||
var toSend = $("#input input").val();
|
||||
$("#input input").val("");
|
||||
addLi("outcoming", toSend);
|
||||
server.send(toSend)
|
||||
}
|
||||
|
||||
function onInputKey(event) {
|
||||
if( event.keyCode == 13 )
|
||||
onSendClicked();
|
||||
}
|
||||
|
||||
function onReady() {
|
||||
$('#connect').on("click", onConnectClicked);
|
||||
$('#disconn').on("click", onDisconnectClicked);
|
||||
$('#send').on("click", onSendClicked);
|
||||
$("#input input").on("keypress", onInputKey);
|
||||
}
|
||||
|
||||
$(onReady)
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,23 +1,23 @@
|
||||
ul, ol { margin: 0; }
|
||||
|
||||
div { border: 0px solid black; }
|
||||
div.wrap { width: 640px; margin: 100px auto;}
|
||||
|
||||
.title { height: 24px; background-color: #ddd; padding: 4px; border: 1px solid black; border-bottom: 0px }
|
||||
.title input {width: 300px; }
|
||||
.title span { display: inline-block; width: 120px; text-align: right; }
|
||||
|
||||
.messages { height: 30ex; overflow: auto; background-color: #fff; padding: 4px; border: 1px solid black; list-style: none; }
|
||||
.messages .incoming { color: #006; }
|
||||
.messages .incoming:before { content: "<< "}
|
||||
.messages .outcoming { color: #060; }
|
||||
.messages .outcoming:before { content: ">> "}
|
||||
.messages .error { color: #600; }
|
||||
.messages li:nth-child(2n) { background-color: #f7f7f7; }
|
||||
|
||||
.packets { padding: 4px; background-color: #ddd; border: 1px solid black; border-top: 0px; display: none; }
|
||||
.packets span { display: inline-block; width: 120px; text-align: right; }
|
||||
.packets input {width: 400px; }
|
||||
.packets button { width: 100px; }
|
||||
|
||||
ul, ol { margin: 0; }
|
||||
|
||||
div { border: 0px solid black; }
|
||||
div.wrap { width: 640px; margin: 100px auto;}
|
||||
|
||||
.title { height: 24px; background-color: #ddd; padding: 4px; border: 1px solid black; border-bottom: 0px }
|
||||
.title input {width: 300px; }
|
||||
.title span { display: inline-block; width: 120px; text-align: right; }
|
||||
|
||||
.messages { height: 30ex; overflow: auto; background-color: #fff; padding: 4px; border: 1px solid black; list-style: none; }
|
||||
.messages .incoming { color: #006; }
|
||||
.messages .incoming:before { content: "<< "}
|
||||
.messages .outcoming { color: #060; }
|
||||
.messages .outcoming:before { content: ">> "}
|
||||
.messages .error { color: #600; }
|
||||
.messages li:nth-child(2n) { background-color: #f7f7f7; }
|
||||
|
||||
.packets { padding: 4px; background-color: #ddd; border: 1px solid black; border-top: 0px; display: none; }
|
||||
.packets span { display: inline-block; width: 120px; text-align: right; }
|
||||
.packets input {width: 400px; }
|
||||
.packets button { width: 100px; }
|
||||
|
||||
span.alert { font-style: italic; }
|
||||
@@ -1,23 +1,23 @@
|
||||
var Observable = function(eventNames) {
|
||||
var _t = {};
|
||||
var observers = {};
|
||||
|
||||
_t.addObserver = function(obj) {
|
||||
for(var i = 0; i < eventNames.length; i++) {
|
||||
var evName = eventNames[i]
|
||||
var method = obj["on" + evName];
|
||||
if( typeof(method) === 'function') {
|
||||
var handlers = observers[evName]
|
||||
if( 'undefined' === typeof(handler))
|
||||
handlers = observers[evName] = [];
|
||||
handlers.push(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_t.fireEvent = function() { // usually invoked as .apply(EventName, args)
|
||||
var q = observers[this]
|
||||
if ( q ) for( var i = 0; i < q.length; i++ ) q[i]['on'+ this].apply(q[i], arguments);
|
||||
}
|
||||
return _t;
|
||||
var Observable = function(eventNames) {
|
||||
var _t = {};
|
||||
var observers = {};
|
||||
|
||||
_t.addObserver = function(obj) {
|
||||
for(var i = 0; i < eventNames.length; i++) {
|
||||
var evName = eventNames[i]
|
||||
var method = obj["on" + evName];
|
||||
if( typeof(method) === 'function') {
|
||||
var handlers = observers[evName]
|
||||
if( 'undefined' === typeof(handler))
|
||||
handlers = observers[evName] = [];
|
||||
handlers.push(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_t.fireEvent = function() { // usually invoked as .apply(EventName, args)
|
||||
var q = observers[this]
|
||||
if ( q ) for( var i = 0; i < q.length; i++ ) q[i]['on'+ this].apply(q[i], arguments);
|
||||
}
|
||||
return _t;
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
|
||||
// There should be some kind of fallback to Flash-powered sockets (IE 9-, Opera with sockets switched off)
|
||||
var Socket = function() {
|
||||
var _t = Observable(["Open", "Message", "Close", "Error"]);
|
||||
|
||||
function onOpen() { _t.fireEvent.apply("Open", arguments); }
|
||||
function onClose() { _t.fireEvent.apply("Close", arguments); }
|
||||
function onError() { _t.fireEvent.apply("Error", arguments); }
|
||||
function onMessage() { _t.fireEvent.apply("Message", arguments); }
|
||||
|
||||
var ws;
|
||||
_t.connect = function(location) {
|
||||
ws = new WebSocket("ws://" + location);
|
||||
ws.onopen = onOpen;
|
||||
ws.onmessage = onMessage;
|
||||
ws.onclose = onClose;
|
||||
ws.onerror = onError;
|
||||
}
|
||||
|
||||
// _t.getWs = function() { return ws; }
|
||||
_t.isOpen = function() { return ws && ws.readyState == ws.OPEN; }
|
||||
_t.close = function() { ws && ws.close(); }
|
||||
_t.send = function(text) { text != null && text.length > 0 && ws && ws.send(text); };
|
||||
|
||||
return _t;
|
||||
};
|
||||
|
||||
|
||||
// There should be some kind of fallback to Flash-powered sockets (IE 9-, Opera with sockets switched off)
|
||||
var Socket = function() {
|
||||
var _t = Observable(["Open", "Message", "Close", "Error"]);
|
||||
|
||||
function onOpen() { _t.fireEvent.apply("Open", arguments); }
|
||||
function onClose() { _t.fireEvent.apply("Close", arguments); }
|
||||
function onError() { _t.fireEvent.apply("Error", arguments); }
|
||||
function onMessage() { _t.fireEvent.apply("Message", arguments); }
|
||||
|
||||
var ws;
|
||||
_t.connect = function(location) {
|
||||
ws = new WebSocket("ws://" + location);
|
||||
ws.onopen = onOpen;
|
||||
ws.onmessage = onMessage;
|
||||
ws.onclose = onClose;
|
||||
ws.onerror = onError;
|
||||
}
|
||||
|
||||
// _t.getWs = function() { return ws; }
|
||||
_t.isOpen = function() { return ws && ws.readyState == ws.OPEN; }
|
||||
_t.close = function() { ws && ws.close(); }
|
||||
_t.send = function(text) { text != null && text.length > 0 && ws && ws.send(text); };
|
||||
|
||||
return _t;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
package forge;
|
||||
|
||||
import forge.util.ThreadUtil;
|
||||
|
||||
public class FThreads {
|
||||
private FThreads() { } // no instances supposed
|
||||
|
||||
/** Checks if calling method uses event dispatch thread.
|
||||
* Exception thrown if method is on "wrong" thread.
|
||||
* A boolean is passed to indicate if the method must be EDT or not.
|
||||
*
|
||||
* @param methodName   String, part of the custom exception message.
|
||||
* @param mustBeEDT   boolean: true = exception if not EDT, false = exception if EDT
|
||||
*/
|
||||
public static void assertExecutedByEdt(final boolean mustBeEDT) {
|
||||
if (isGuiThread() != mustBeEDT) {
|
||||
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
||||
final String methodName = trace[2].getClassName() + "." + trace[2].getMethodName();
|
||||
final String modalOperator = mustBeEDT ? " must be" : " may not be";
|
||||
throw new IllegalStateException(methodName + modalOperator + " accessed from the event dispatch thread.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void invokeInEdtLater(final Runnable proc) {
|
||||
GuiBase.getInterface().invokeInEdtLater(proc);
|
||||
}
|
||||
|
||||
public static void invokeInEdtNowOrLater(final Runnable proc) {
|
||||
if (isGuiThread()) {
|
||||
GuiBase.getInterface().invokeInEdtNow(proc);
|
||||
}
|
||||
else {
|
||||
GuiBase.getInterface().invokeInEdtLater(proc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the given Runnable in an Event Dispatch Thread and wait for it to
|
||||
* finish; but <B>try to use SwingUtilities.invokeLater instead whenever
|
||||
* feasible.</B>
|
||||
*
|
||||
* Exceptions generated by SwingUtilities.invokeAndWait (if used), are
|
||||
* rethrown as RuntimeExceptions.
|
||||
*
|
||||
* @param proc
|
||||
* the Runnable to run
|
||||
* @see fgd.SwingUtilities#invokeLater(Runnable)
|
||||
*/
|
||||
public static void invokeInEdtAndWait(final Runnable proc) {
|
||||
GuiBase.getInterface().invokeInEdtAndWait(proc);
|
||||
}
|
||||
|
||||
private static int backgroundThreadCount;
|
||||
public static void invokeInBackgroundThread(final Runnable proc) {
|
||||
//start thread name with "Game" so isGuiThread() returns false on GuiMobile
|
||||
new Thread(proc, "Game BT" + backgroundThreadCount).start();
|
||||
backgroundThreadCount++;
|
||||
}
|
||||
|
||||
public static boolean isGuiThread() {
|
||||
return GuiBase.getInterface().isGuiThread();
|
||||
}
|
||||
|
||||
public static void delayInEDT(final int milliseconds, final Runnable inputUpdater) {
|
||||
final Runnable runInEdt = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FThreads.invokeInEdtNowOrLater(inputUpdater);
|
||||
}
|
||||
};
|
||||
ThreadUtil.delay(milliseconds, runInEdt);
|
||||
}
|
||||
|
||||
public static String debugGetCurrThreadId() {
|
||||
return isGuiThread() ? "EDT" : Thread.currentThread().getName();
|
||||
}
|
||||
|
||||
public static String debugGetStackTraceItem(final int depth, final boolean shorter) {
|
||||
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
||||
String lastItem = trace[depth].toString();
|
||||
if (shorter) {
|
||||
int lastPeriod = lastItem.lastIndexOf('.');
|
||||
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
|
||||
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
|
||||
lastItem = lastItem.substring(lastPeriod+1);
|
||||
return String.format("%s > from %s", debugGetCurrThreadId(), lastItem);
|
||||
}
|
||||
return String.format("%s > %s called from %s", debugGetCurrThreadId(),
|
||||
trace[2].getClassName() + "." + trace[2].getMethodName(), lastItem);
|
||||
}
|
||||
|
||||
public static String debugGetStackTraceItem(final int depth) {
|
||||
return debugGetStackTraceItem(depth, false);
|
||||
}
|
||||
}
|
||||
package forge;
|
||||
|
||||
import forge.util.ThreadUtil;
|
||||
|
||||
public class FThreads {
|
||||
private FThreads() { } // no instances supposed
|
||||
|
||||
/** Checks if calling method uses event dispatch thread.
|
||||
* Exception thrown if method is on "wrong" thread.
|
||||
* A boolean is passed to indicate if the method must be EDT or not.
|
||||
*
|
||||
* @param methodName   String, part of the custom exception message.
|
||||
* @param mustBeEDT   boolean: true = exception if not EDT, false = exception if EDT
|
||||
*/
|
||||
public static void assertExecutedByEdt(final boolean mustBeEDT) {
|
||||
if (isGuiThread() != mustBeEDT) {
|
||||
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
||||
final String methodName = trace[2].getClassName() + "." + trace[2].getMethodName();
|
||||
final String modalOperator = mustBeEDT ? " must be" : " may not be";
|
||||
throw new IllegalStateException(methodName + modalOperator + " accessed from the event dispatch thread.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void invokeInEdtLater(final Runnable proc) {
|
||||
GuiBase.getInterface().invokeInEdtLater(proc);
|
||||
}
|
||||
|
||||
public static void invokeInEdtNowOrLater(final Runnable proc) {
|
||||
if (isGuiThread()) {
|
||||
GuiBase.getInterface().invokeInEdtNow(proc);
|
||||
}
|
||||
else {
|
||||
GuiBase.getInterface().invokeInEdtLater(proc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the given Runnable in an Event Dispatch Thread and wait for it to
|
||||
* finish; but <B>try to use SwingUtilities.invokeLater instead whenever
|
||||
* feasible.</B>
|
||||
*
|
||||
* Exceptions generated by SwingUtilities.invokeAndWait (if used), are
|
||||
* rethrown as RuntimeExceptions.
|
||||
*
|
||||
* @param proc
|
||||
* the Runnable to run
|
||||
* @see fgd.SwingUtilities#invokeLater(Runnable)
|
||||
*/
|
||||
public static void invokeInEdtAndWait(final Runnable proc) {
|
||||
GuiBase.getInterface().invokeInEdtAndWait(proc);
|
||||
}
|
||||
|
||||
private static int backgroundThreadCount;
|
||||
public static void invokeInBackgroundThread(final Runnable proc) {
|
||||
//start thread name with "Game" so isGuiThread() returns false on GuiMobile
|
||||
new Thread(proc, "Game BT" + backgroundThreadCount).start();
|
||||
backgroundThreadCount++;
|
||||
}
|
||||
|
||||
public static boolean isGuiThread() {
|
||||
return GuiBase.getInterface().isGuiThread();
|
||||
}
|
||||
|
||||
public static void delayInEDT(final int milliseconds, final Runnable inputUpdater) {
|
||||
final Runnable runInEdt = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FThreads.invokeInEdtNowOrLater(inputUpdater);
|
||||
}
|
||||
};
|
||||
ThreadUtil.delay(milliseconds, runInEdt);
|
||||
}
|
||||
|
||||
public static String debugGetCurrThreadId() {
|
||||
return isGuiThread() ? "EDT" : Thread.currentThread().getName();
|
||||
}
|
||||
|
||||
public static String debugGetStackTraceItem(final int depth, final boolean shorter) {
|
||||
final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
|
||||
String lastItem = trace[depth].toString();
|
||||
if (shorter) {
|
||||
int lastPeriod = lastItem.lastIndexOf('.');
|
||||
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
|
||||
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
|
||||
lastItem = lastItem.substring(lastPeriod+1);
|
||||
return String.format("%s > from %s", debugGetCurrThreadId(), lastItem);
|
||||
}
|
||||
return String.format("%s > %s called from %s", debugGetCurrThreadId(),
|
||||
trace[2].getClassName() + "." + trace[2].getMethodName(), lastItem);
|
||||
}
|
||||
|
||||
public static String debugGetStackTraceItem(final int depth) {
|
||||
return debugGetStackTraceItem(depth, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package forge;
|
||||
|
||||
import forge.interfaces.IGuiBase;
|
||||
|
||||
public class GuiBase {
|
||||
private static IGuiBase guiInterface;
|
||||
|
||||
public static IGuiBase getInterface() {
|
||||
return guiInterface;
|
||||
}
|
||||
public static void setInterface(IGuiBase i0) {
|
||||
guiInterface = i0;
|
||||
}
|
||||
}
|
||||
package forge;
|
||||
|
||||
import forge.interfaces.IGuiBase;
|
||||
|
||||
public class GuiBase {
|
||||
private static IGuiBase guiInterface;
|
||||
|
||||
public static IGuiBase getInterface() {
|
||||
return guiInterface;
|
||||
}
|
||||
public static void setInterface(IGuiBase i0) {
|
||||
guiInterface = i0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,270 +1,270 @@
|
||||
package forge.achievement;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.assets.ISkinImage;
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.Lang;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
public abstract class Achievement {
|
||||
private final String key, displayName, sharedDesc, commonDesc, uncommonDesc, rareDesc, mythicDesc;
|
||||
private final int commonThreshold, uncommonThreshold, rareThreshold, mythicThreshold;
|
||||
private final boolean checkGreaterThan;
|
||||
protected final int defaultValue;
|
||||
private ISkinImage image;
|
||||
private long timestamp;
|
||||
private int best;
|
||||
|
||||
//use this constructor for special achievements without tiers
|
||||
protected Achievement(final String key0, final String displayName0, final String description0, final String flavorText0, final int defaultValue0) {
|
||||
this(key0, displayName0, description0, defaultValue0, null, 1, null, 1, null, 1, "(" + flavorText0 + ")", 1); //pass flavor text as mythic description so it appears below description faded out
|
||||
}
|
||||
//use this constructor for regular tiered achievements
|
||||
protected Achievement(final String key0, final String displayName0, final String sharedDesc0, final int defaultValue0,
|
||||
final String commonDesc0, final int commonThreshold0,
|
||||
final String uncommonDesc0, final int uncommonThreshold0,
|
||||
final String rareDesc0, final int rareThreshold0,
|
||||
final String mythicDesc0, final int mythicThreshold0) {
|
||||
key = key0;
|
||||
displayName = displayName0;
|
||||
sharedDesc = sharedDesc0;
|
||||
commonDesc = commonDesc0;
|
||||
commonThreshold = commonThreshold0;
|
||||
uncommonDesc = uncommonDesc0;
|
||||
uncommonThreshold = uncommonThreshold0;
|
||||
rareDesc = rareDesc0;
|
||||
rareThreshold = rareThreshold0;
|
||||
mythicDesc = mythicDesc0;
|
||||
mythicThreshold = mythicThreshold0;
|
||||
checkGreaterThan = rareThreshold0 >= uncommonThreshold0;
|
||||
best = defaultValue0;
|
||||
defaultValue = defaultValue0;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
public String getSharedDesc() {
|
||||
return sharedDesc;
|
||||
}
|
||||
public String getCommonDesc() {
|
||||
return commonDesc;
|
||||
}
|
||||
public String getUncommonDesc() {
|
||||
return uncommonDesc;
|
||||
}
|
||||
public String getRareDesc() {
|
||||
return rareDesc;
|
||||
}
|
||||
public String getMythicDesc() {
|
||||
return mythicDesc;
|
||||
}
|
||||
public ISkinImage getImage() {
|
||||
if (image == null) {
|
||||
updateTrophyImage();
|
||||
}
|
||||
return image;
|
||||
}
|
||||
public int getBest() {
|
||||
return best;
|
||||
}
|
||||
public boolean isSpecial() {
|
||||
return mythicThreshold == commonThreshold;
|
||||
}
|
||||
private boolean earnedSpecial() {
|
||||
return (isSpecial() && best > 0);
|
||||
}
|
||||
public boolean earnedMythic() {
|
||||
if (isSpecial()) { return false; }
|
||||
if (checkGreaterThan) {
|
||||
return best >= mythicThreshold;
|
||||
}
|
||||
return best <= mythicThreshold;
|
||||
}
|
||||
public boolean earnedRare() {
|
||||
if (isSpecial()) { return false; }
|
||||
if (checkGreaterThan) {
|
||||
return best >= rareThreshold;
|
||||
}
|
||||
return best <= rareThreshold;
|
||||
}
|
||||
public boolean earnedUncommon() {
|
||||
if (isSpecial()) { return false; }
|
||||
if (checkGreaterThan) {
|
||||
return best >= uncommonThreshold;
|
||||
}
|
||||
return best <= uncommonThreshold;
|
||||
}
|
||||
public boolean earnedCommon() {
|
||||
if (isSpecial()) { return false; }
|
||||
if (checkGreaterThan) {
|
||||
return best >= commonThreshold;
|
||||
}
|
||||
return best <= commonThreshold;
|
||||
}
|
||||
|
||||
//get card associated with this achievement if any
|
||||
public IPaperCard getPaperCard() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract int evaluate(Player player, Game game);
|
||||
|
||||
private void updateTrophyImage() {
|
||||
FSkinProp background;
|
||||
float opacity = 1;
|
||||
if (earnedSpecial()) {
|
||||
background = FSkinProp.IMG_SPECIAL_TROPHY;
|
||||
}
|
||||
else if (earnedMythic()) {
|
||||
background = FSkinProp.IMG_MYTHIC_TROPHY;
|
||||
}
|
||||
else if (earnedRare()) {
|
||||
background = FSkinProp.IMG_RARE_TROPHY;
|
||||
}
|
||||
else if (earnedUncommon()) {
|
||||
background = FSkinProp.IMG_UNCOMMON_TROPHY;
|
||||
}
|
||||
else if (earnedCommon()) {
|
||||
background = FSkinProp.IMG_COMMON_TROPHY;
|
||||
}
|
||||
else {
|
||||
opacity = 0.25f; //fade out if achievement hasn't been earned yet
|
||||
if (mythicThreshold == commonThreshold) {
|
||||
background = FSkinProp.IMG_SPECIAL_TROPHY;
|
||||
}
|
||||
else {
|
||||
background = FSkinProp.IMG_COMMON_TROPHY;
|
||||
}
|
||||
}
|
||||
image = GuiBase.getInterface().createLayeredImage(background, ForgeConstants.CACHE_ACHIEVEMENTS_DIR + "/" + key + ".png", opacity);
|
||||
}
|
||||
|
||||
public int update(final Player player) {
|
||||
final int value = evaluate(player, player.getGame());
|
||||
if (checkGreaterThan) {
|
||||
if (value <= best) { return value; }
|
||||
}
|
||||
else if (value >= best) { return value; }
|
||||
|
||||
final boolean hadEarnedSpecial = earnedSpecial();
|
||||
final boolean hadEarnedMythic = earnedMythic();
|
||||
final boolean hadEarnedRare = earnedRare();
|
||||
final boolean hadEarnedUncommon = earnedUncommon();
|
||||
final boolean hadEarnedCommon = earnedCommon();
|
||||
|
||||
best = value;
|
||||
timestamp = new Date().getTime();
|
||||
|
||||
if (earnedSpecial()) {
|
||||
if (!hadEarnedSpecial) {
|
||||
updateTrophyImage();
|
||||
GuiBase.getInterface().showImageDialog(image, displayName + "\n" + sharedDesc + "\n" + mythicDesc, "Achievement Earned");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
String type = null;
|
||||
String desc = null;
|
||||
if (earnedMythic()) {
|
||||
if (!hadEarnedMythic) {
|
||||
type = "Mythic";
|
||||
desc = mythicDesc;
|
||||
}
|
||||
}
|
||||
else if (earnedRare()) {
|
||||
if (!hadEarnedRare) {
|
||||
type = "Rare";
|
||||
desc = rareDesc;
|
||||
}
|
||||
}
|
||||
else if (earnedUncommon()) {
|
||||
if (!hadEarnedUncommon) {
|
||||
type = "Uncommon";
|
||||
desc = uncommonDesc;
|
||||
}
|
||||
}
|
||||
else if (earnedCommon()) {
|
||||
if (!hadEarnedCommon) {
|
||||
type = "Common";
|
||||
desc = commonDesc;
|
||||
}
|
||||
}
|
||||
if (type != null) {
|
||||
updateTrophyImage();
|
||||
if (sharedDesc != null) {
|
||||
desc = sharedDesc + " " + desc;
|
||||
}
|
||||
GuiBase.getInterface().showImageDialog(image, displayName + " (" + type + ")\n" + desc, "Achievement Earned");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public final boolean needSave() {
|
||||
return best != defaultValue;
|
||||
}
|
||||
|
||||
public void saveToXml(final Element el) {
|
||||
el.setAttribute("best", String.valueOf(best));
|
||||
el.setAttribute("time", String.valueOf(timestamp));
|
||||
}
|
||||
|
||||
public void loadFromXml(final Element el) {
|
||||
best = XmlUtil.getIntAttribute(el, "best");
|
||||
timestamp = XmlUtil.getLongAttribute(el, "time");
|
||||
best = performConversion(best, timestamp);
|
||||
}
|
||||
|
||||
//give derived classes a chance to perform a conversion if needed
|
||||
protected int performConversion(final int value, final long timestamp) {
|
||||
return value;
|
||||
}
|
||||
|
||||
protected abstract String getNoun();
|
||||
|
||||
protected boolean pluralizeNoun() {
|
||||
return best != 1;
|
||||
}
|
||||
protected boolean displayNounBefore() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected final String getFormattedTimestamp() {
|
||||
if (timestamp == 0) { return null; }
|
||||
|
||||
final DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault());
|
||||
return formatter.format(new Date(timestamp));
|
||||
}
|
||||
|
||||
public String getSubTitle(final boolean includeTimestamp) {
|
||||
if (best == defaultValue) { return null; }
|
||||
|
||||
String subTitle;
|
||||
if (displayNounBefore()) {
|
||||
subTitle = "Best: " + getNoun() + " " + best;
|
||||
}
|
||||
else {
|
||||
subTitle = "Best: " + best + " " + (pluralizeNoun() ? Lang.getPlural(getNoun()) : getNoun());
|
||||
}
|
||||
if (includeTimestamp) {
|
||||
final String formattedTimestamp = getFormattedTimestamp();
|
||||
if (formattedTimestamp != null) {
|
||||
subTitle += " (" + formattedTimestamp + ")";
|
||||
}
|
||||
}
|
||||
return subTitle;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.assets.ISkinImage;
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.Lang;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
public abstract class Achievement {
|
||||
private final String key, displayName, sharedDesc, commonDesc, uncommonDesc, rareDesc, mythicDesc;
|
||||
private final int commonThreshold, uncommonThreshold, rareThreshold, mythicThreshold;
|
||||
private final boolean checkGreaterThan;
|
||||
protected final int defaultValue;
|
||||
private ISkinImage image;
|
||||
private long timestamp;
|
||||
private int best;
|
||||
|
||||
//use this constructor for special achievements without tiers
|
||||
protected Achievement(final String key0, final String displayName0, final String description0, final String flavorText0, final int defaultValue0) {
|
||||
this(key0, displayName0, description0, defaultValue0, null, 1, null, 1, null, 1, "(" + flavorText0 + ")", 1); //pass flavor text as mythic description so it appears below description faded out
|
||||
}
|
||||
//use this constructor for regular tiered achievements
|
||||
protected Achievement(final String key0, final String displayName0, final String sharedDesc0, final int defaultValue0,
|
||||
final String commonDesc0, final int commonThreshold0,
|
||||
final String uncommonDesc0, final int uncommonThreshold0,
|
||||
final String rareDesc0, final int rareThreshold0,
|
||||
final String mythicDesc0, final int mythicThreshold0) {
|
||||
key = key0;
|
||||
displayName = displayName0;
|
||||
sharedDesc = sharedDesc0;
|
||||
commonDesc = commonDesc0;
|
||||
commonThreshold = commonThreshold0;
|
||||
uncommonDesc = uncommonDesc0;
|
||||
uncommonThreshold = uncommonThreshold0;
|
||||
rareDesc = rareDesc0;
|
||||
rareThreshold = rareThreshold0;
|
||||
mythicDesc = mythicDesc0;
|
||||
mythicThreshold = mythicThreshold0;
|
||||
checkGreaterThan = rareThreshold0 >= uncommonThreshold0;
|
||||
best = defaultValue0;
|
||||
defaultValue = defaultValue0;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
public String getSharedDesc() {
|
||||
return sharedDesc;
|
||||
}
|
||||
public String getCommonDesc() {
|
||||
return commonDesc;
|
||||
}
|
||||
public String getUncommonDesc() {
|
||||
return uncommonDesc;
|
||||
}
|
||||
public String getRareDesc() {
|
||||
return rareDesc;
|
||||
}
|
||||
public String getMythicDesc() {
|
||||
return mythicDesc;
|
||||
}
|
||||
public ISkinImage getImage() {
|
||||
if (image == null) {
|
||||
updateTrophyImage();
|
||||
}
|
||||
return image;
|
||||
}
|
||||
public int getBest() {
|
||||
return best;
|
||||
}
|
||||
public boolean isSpecial() {
|
||||
return mythicThreshold == commonThreshold;
|
||||
}
|
||||
private boolean earnedSpecial() {
|
||||
return (isSpecial() && best > 0);
|
||||
}
|
||||
public boolean earnedMythic() {
|
||||
if (isSpecial()) { return false; }
|
||||
if (checkGreaterThan) {
|
||||
return best >= mythicThreshold;
|
||||
}
|
||||
return best <= mythicThreshold;
|
||||
}
|
||||
public boolean earnedRare() {
|
||||
if (isSpecial()) { return false; }
|
||||
if (checkGreaterThan) {
|
||||
return best >= rareThreshold;
|
||||
}
|
||||
return best <= rareThreshold;
|
||||
}
|
||||
public boolean earnedUncommon() {
|
||||
if (isSpecial()) { return false; }
|
||||
if (checkGreaterThan) {
|
||||
return best >= uncommonThreshold;
|
||||
}
|
||||
return best <= uncommonThreshold;
|
||||
}
|
||||
public boolean earnedCommon() {
|
||||
if (isSpecial()) { return false; }
|
||||
if (checkGreaterThan) {
|
||||
return best >= commonThreshold;
|
||||
}
|
||||
return best <= commonThreshold;
|
||||
}
|
||||
|
||||
//get card associated with this achievement if any
|
||||
public IPaperCard getPaperCard() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract int evaluate(Player player, Game game);
|
||||
|
||||
private void updateTrophyImage() {
|
||||
FSkinProp background;
|
||||
float opacity = 1;
|
||||
if (earnedSpecial()) {
|
||||
background = FSkinProp.IMG_SPECIAL_TROPHY;
|
||||
}
|
||||
else if (earnedMythic()) {
|
||||
background = FSkinProp.IMG_MYTHIC_TROPHY;
|
||||
}
|
||||
else if (earnedRare()) {
|
||||
background = FSkinProp.IMG_RARE_TROPHY;
|
||||
}
|
||||
else if (earnedUncommon()) {
|
||||
background = FSkinProp.IMG_UNCOMMON_TROPHY;
|
||||
}
|
||||
else if (earnedCommon()) {
|
||||
background = FSkinProp.IMG_COMMON_TROPHY;
|
||||
}
|
||||
else {
|
||||
opacity = 0.25f; //fade out if achievement hasn't been earned yet
|
||||
if (mythicThreshold == commonThreshold) {
|
||||
background = FSkinProp.IMG_SPECIAL_TROPHY;
|
||||
}
|
||||
else {
|
||||
background = FSkinProp.IMG_COMMON_TROPHY;
|
||||
}
|
||||
}
|
||||
image = GuiBase.getInterface().createLayeredImage(background, ForgeConstants.CACHE_ACHIEVEMENTS_DIR + "/" + key + ".png", opacity);
|
||||
}
|
||||
|
||||
public int update(final Player player) {
|
||||
final int value = evaluate(player, player.getGame());
|
||||
if (checkGreaterThan) {
|
||||
if (value <= best) { return value; }
|
||||
}
|
||||
else if (value >= best) { return value; }
|
||||
|
||||
final boolean hadEarnedSpecial = earnedSpecial();
|
||||
final boolean hadEarnedMythic = earnedMythic();
|
||||
final boolean hadEarnedRare = earnedRare();
|
||||
final boolean hadEarnedUncommon = earnedUncommon();
|
||||
final boolean hadEarnedCommon = earnedCommon();
|
||||
|
||||
best = value;
|
||||
timestamp = new Date().getTime();
|
||||
|
||||
if (earnedSpecial()) {
|
||||
if (!hadEarnedSpecial) {
|
||||
updateTrophyImage();
|
||||
GuiBase.getInterface().showImageDialog(image, displayName + "\n" + sharedDesc + "\n" + mythicDesc, "Achievement Earned");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
String type = null;
|
||||
String desc = null;
|
||||
if (earnedMythic()) {
|
||||
if (!hadEarnedMythic) {
|
||||
type = "Mythic";
|
||||
desc = mythicDesc;
|
||||
}
|
||||
}
|
||||
else if (earnedRare()) {
|
||||
if (!hadEarnedRare) {
|
||||
type = "Rare";
|
||||
desc = rareDesc;
|
||||
}
|
||||
}
|
||||
else if (earnedUncommon()) {
|
||||
if (!hadEarnedUncommon) {
|
||||
type = "Uncommon";
|
||||
desc = uncommonDesc;
|
||||
}
|
||||
}
|
||||
else if (earnedCommon()) {
|
||||
if (!hadEarnedCommon) {
|
||||
type = "Common";
|
||||
desc = commonDesc;
|
||||
}
|
||||
}
|
||||
if (type != null) {
|
||||
updateTrophyImage();
|
||||
if (sharedDesc != null) {
|
||||
desc = sharedDesc + " " + desc;
|
||||
}
|
||||
GuiBase.getInterface().showImageDialog(image, displayName + " (" + type + ")\n" + desc, "Achievement Earned");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public final boolean needSave() {
|
||||
return best != defaultValue;
|
||||
}
|
||||
|
||||
public void saveToXml(final Element el) {
|
||||
el.setAttribute("best", String.valueOf(best));
|
||||
el.setAttribute("time", String.valueOf(timestamp));
|
||||
}
|
||||
|
||||
public void loadFromXml(final Element el) {
|
||||
best = XmlUtil.getIntAttribute(el, "best");
|
||||
timestamp = XmlUtil.getLongAttribute(el, "time");
|
||||
best = performConversion(best, timestamp);
|
||||
}
|
||||
|
||||
//give derived classes a chance to perform a conversion if needed
|
||||
protected int performConversion(final int value, final long timestamp) {
|
||||
return value;
|
||||
}
|
||||
|
||||
protected abstract String getNoun();
|
||||
|
||||
protected boolean pluralizeNoun() {
|
||||
return best != 1;
|
||||
}
|
||||
protected boolean displayNounBefore() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected final String getFormattedTimestamp() {
|
||||
if (timestamp == 0) { return null; }
|
||||
|
||||
final DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault());
|
||||
return formatter.format(new Date(timestamp));
|
||||
}
|
||||
|
||||
public String getSubTitle(final boolean includeTimestamp) {
|
||||
if (best == defaultValue) { return null; }
|
||||
|
||||
String subTitle;
|
||||
if (displayNounBefore()) {
|
||||
subTitle = "Best: " + getNoun() + " " + best;
|
||||
}
|
||||
else {
|
||||
subTitle = "Best: " + best + " " + (pluralizeNoun() ? Lang.getPlural(getNoun()) : getNoun());
|
||||
}
|
||||
if (includeTimestamp) {
|
||||
final String formattedTimestamp = getFormattedTimestamp();
|
||||
if (formattedTimestamp != null) {
|
||||
subTitle += " (" + formattedTimestamp + ")";
|
||||
}
|
||||
}
|
||||
return subTitle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,209 +1,209 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.GuiBase;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.Player;
|
||||
import forge.interfaces.IComboBox;
|
||||
import forge.model.FModel;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.ThreadUtil;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
public abstract class AchievementCollection implements Iterable<Achievement> {
|
||||
protected final Map<String, Achievement> achievements = Maps.newLinkedHashMap();
|
||||
protected final String name, filename, path;
|
||||
protected final boolean isLimitedFormat;
|
||||
|
||||
static {
|
||||
FileUtil.ensureDirectoryExists(ForgeConstants.ACHIEVEMENTS_DIR);
|
||||
}
|
||||
|
||||
public static void updateAll(final PlayerControllerHuman controller) {
|
||||
//don't update achievements if player cheated during game
|
||||
if (controller.hasCheated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Game game = controller.getGame();
|
||||
final Player player = controller.getPlayer();
|
||||
|
||||
//update all achievements for GUI player after game finished
|
||||
//(we are doing it in different threads in different game ports to prevent freezing when processing multiple achievements)
|
||||
if (GuiBase.getInterface().isLibgdxPort()) {
|
||||
ThreadUtil.invokeInGameThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doUpdateAllAchievements(game, player);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
doUpdateAllAchievements(game, player);
|
||||
}
|
||||
}
|
||||
|
||||
private static void doUpdateAllAchievements(final Game game, final Player player) {
|
||||
FModel.getAchievements(game.getRules().getGameType()).updateAll(player);
|
||||
AltWinAchievements.instance.updateAll(player);
|
||||
PlaneswalkerAchievements.instance.updateAll(player);
|
||||
ChallengeAchievements.instance.updateAll(player);
|
||||
}
|
||||
|
||||
public static void buildComboBox(IComboBox<AchievementCollection> cb) {
|
||||
cb.addItem(FModel.getAchievements(GameType.Constructed));
|
||||
cb.addItem(FModel.getAchievements(GameType.Draft));
|
||||
cb.addItem(FModel.getAchievements(GameType.Sealed));
|
||||
cb.addItem(FModel.getAchievements(GameType.Quest));
|
||||
cb.addItem(FModel.getAchievements(GameType.PlanarConquest));
|
||||
cb.addItem(FModel.getAchievements(GameType.Puzzle));
|
||||
cb.addItem(AltWinAchievements.instance);
|
||||
cb.addItem(PlaneswalkerAchievements.instance);
|
||||
cb.addItem(ChallengeAchievements.instance);
|
||||
}
|
||||
|
||||
protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0) {
|
||||
this(name0, filename0, isLimitedFormat0, (String) null);
|
||||
}
|
||||
|
||||
protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0, String path0) {
|
||||
name = name0;
|
||||
filename = filename0;
|
||||
isLimitedFormat = isLimitedFormat0;
|
||||
path = path0;
|
||||
addSharedAchivements();
|
||||
addAchievements();
|
||||
load();
|
||||
}
|
||||
|
||||
protected void addSharedAchivements() {
|
||||
add(new GameWinStreak(10, 25, 50, 100));
|
||||
add(new MatchWinStreak(10, 25, 50, 100));
|
||||
add(new TotalGameWins(250, 500, 1000, 2000));
|
||||
add(new TotalMatchWins(100, 250, 500, 1000));
|
||||
if (isLimitedFormat) { //make need for speed goal more realistic for limited formats
|
||||
add(new NeedForSpeed(8, 6, 4, 2));
|
||||
}
|
||||
else {
|
||||
add(new NeedForSpeed(5, 3, 1, 0));
|
||||
}
|
||||
add(new Overkill(-25, -50, -100, -200));
|
||||
add(new LifeToSpare(20, 40, 80, 160));
|
||||
add(new Hellbent());
|
||||
add(new ArcaneMaster());
|
||||
add(new StormChaser(5, 10, 20, 50));
|
||||
add(new ManaScrewed());
|
||||
if (isLimitedFormat) { //lower gold and mythic thresholds based on smaller decks
|
||||
add(new ManaFlooded(8, 11, 14, 17));
|
||||
}
|
||||
else {
|
||||
add(new ManaFlooded(8, 12, 18, 24));
|
||||
}
|
||||
add(new RagsToRiches());
|
||||
}
|
||||
|
||||
protected void addAchievements() {
|
||||
if (path != null) {
|
||||
final List<String> achievementListFile = FileUtil.readFile(path);
|
||||
for (final String s : achievementListFile) {
|
||||
if (!s.isEmpty()) {
|
||||
String k[] = StringUtils.split(s, "|");
|
||||
add(k[0],k[1],k[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void add(Achievement achievement) {
|
||||
achievements.put(achievement.getKey(), achievement);
|
||||
}
|
||||
protected void add(String name, String title, String desc) {
|
||||
// to overwrite
|
||||
}
|
||||
|
||||
public void updateAll(Player player) {
|
||||
for (Achievement achievement : achievements.values()) {
|
||||
achievement.update(player);
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final Document document = builder.parse(new File(filename));
|
||||
final NodeList nodes = document.getElementsByTagName("a");
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
final Element el = (Element)nodes.item(i);
|
||||
final Achievement achievement = achievements.get(el.getAttribute("name"));
|
||||
if (achievement != null) {
|
||||
achievement.loadFromXml(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
//ok if file not found
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected void save() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
Element root = document.createElement("achievements");
|
||||
document.appendChild(root);
|
||||
|
||||
for (Entry<String, Achievement> entry : achievements.entrySet()) {
|
||||
Achievement achievement = entry.getValue();
|
||||
if (achievement.needSave()) {
|
||||
Element el = document.createElement("a");
|
||||
el.setAttribute("name", entry.getKey());
|
||||
achievement.saveToXml(el);
|
||||
root.appendChild(el);
|
||||
}
|
||||
}
|
||||
XmlUtil.saveDocument(document, filename);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return achievements.size();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Iterable#iterator()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<Achievement> iterator() {
|
||||
return achievements.values().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.GuiBase;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.Player;
|
||||
import forge.interfaces.IComboBox;
|
||||
import forge.model.FModel;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.ThreadUtil;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
public abstract class AchievementCollection implements Iterable<Achievement> {
|
||||
protected final Map<String, Achievement> achievements = Maps.newLinkedHashMap();
|
||||
protected final String name, filename, path;
|
||||
protected final boolean isLimitedFormat;
|
||||
|
||||
static {
|
||||
FileUtil.ensureDirectoryExists(ForgeConstants.ACHIEVEMENTS_DIR);
|
||||
}
|
||||
|
||||
public static void updateAll(final PlayerControllerHuman controller) {
|
||||
//don't update achievements if player cheated during game
|
||||
if (controller.hasCheated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Game game = controller.getGame();
|
||||
final Player player = controller.getPlayer();
|
||||
|
||||
//update all achievements for GUI player after game finished
|
||||
//(we are doing it in different threads in different game ports to prevent freezing when processing multiple achievements)
|
||||
if (GuiBase.getInterface().isLibgdxPort()) {
|
||||
ThreadUtil.invokeInGameThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doUpdateAllAchievements(game, player);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
doUpdateAllAchievements(game, player);
|
||||
}
|
||||
}
|
||||
|
||||
private static void doUpdateAllAchievements(final Game game, final Player player) {
|
||||
FModel.getAchievements(game.getRules().getGameType()).updateAll(player);
|
||||
AltWinAchievements.instance.updateAll(player);
|
||||
PlaneswalkerAchievements.instance.updateAll(player);
|
||||
ChallengeAchievements.instance.updateAll(player);
|
||||
}
|
||||
|
||||
public static void buildComboBox(IComboBox<AchievementCollection> cb) {
|
||||
cb.addItem(FModel.getAchievements(GameType.Constructed));
|
||||
cb.addItem(FModel.getAchievements(GameType.Draft));
|
||||
cb.addItem(FModel.getAchievements(GameType.Sealed));
|
||||
cb.addItem(FModel.getAchievements(GameType.Quest));
|
||||
cb.addItem(FModel.getAchievements(GameType.PlanarConquest));
|
||||
cb.addItem(FModel.getAchievements(GameType.Puzzle));
|
||||
cb.addItem(AltWinAchievements.instance);
|
||||
cb.addItem(PlaneswalkerAchievements.instance);
|
||||
cb.addItem(ChallengeAchievements.instance);
|
||||
}
|
||||
|
||||
protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0) {
|
||||
this(name0, filename0, isLimitedFormat0, (String) null);
|
||||
}
|
||||
|
||||
protected AchievementCollection(String name0, String filename0, boolean isLimitedFormat0, String path0) {
|
||||
name = name0;
|
||||
filename = filename0;
|
||||
isLimitedFormat = isLimitedFormat0;
|
||||
path = path0;
|
||||
addSharedAchivements();
|
||||
addAchievements();
|
||||
load();
|
||||
}
|
||||
|
||||
protected void addSharedAchivements() {
|
||||
add(new GameWinStreak(10, 25, 50, 100));
|
||||
add(new MatchWinStreak(10, 25, 50, 100));
|
||||
add(new TotalGameWins(250, 500, 1000, 2000));
|
||||
add(new TotalMatchWins(100, 250, 500, 1000));
|
||||
if (isLimitedFormat) { //make need for speed goal more realistic for limited formats
|
||||
add(new NeedForSpeed(8, 6, 4, 2));
|
||||
}
|
||||
else {
|
||||
add(new NeedForSpeed(5, 3, 1, 0));
|
||||
}
|
||||
add(new Overkill(-25, -50, -100, -200));
|
||||
add(new LifeToSpare(20, 40, 80, 160));
|
||||
add(new Hellbent());
|
||||
add(new ArcaneMaster());
|
||||
add(new StormChaser(5, 10, 20, 50));
|
||||
add(new ManaScrewed());
|
||||
if (isLimitedFormat) { //lower gold and mythic thresholds based on smaller decks
|
||||
add(new ManaFlooded(8, 11, 14, 17));
|
||||
}
|
||||
else {
|
||||
add(new ManaFlooded(8, 12, 18, 24));
|
||||
}
|
||||
add(new RagsToRiches());
|
||||
}
|
||||
|
||||
protected void addAchievements() {
|
||||
if (path != null) {
|
||||
final List<String> achievementListFile = FileUtil.readFile(path);
|
||||
for (final String s : achievementListFile) {
|
||||
if (!s.isEmpty()) {
|
||||
String k[] = StringUtils.split(s, "|");
|
||||
add(k[0],k[1],k[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void add(Achievement achievement) {
|
||||
achievements.put(achievement.getKey(), achievement);
|
||||
}
|
||||
protected void add(String name, String title, String desc) {
|
||||
// to overwrite
|
||||
}
|
||||
|
||||
public void updateAll(Player player) {
|
||||
for (Achievement achievement : achievements.values()) {
|
||||
achievement.update(player);
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final Document document = builder.parse(new File(filename));
|
||||
final NodeList nodes = document.getElementsByTagName("a");
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
final Element el = (Element)nodes.item(i);
|
||||
final Achievement achievement = achievements.get(el.getAttribute("name"));
|
||||
if (achievement != null) {
|
||||
achievement.loadFromXml(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
//ok if file not found
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected void save() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
Element root = document.createElement("achievements");
|
||||
document.appendChild(root);
|
||||
|
||||
for (Entry<String, Achievement> entry : achievements.entrySet()) {
|
||||
Achievement achievement = entry.getValue();
|
||||
if (achievement.needSave()) {
|
||||
Element el = document.createElement("a");
|
||||
el.setAttribute("name", entry.getKey());
|
||||
achievement.saveToXml(el);
|
||||
root.appendChild(el);
|
||||
}
|
||||
}
|
||||
XmlUtil.saveDocument(document, filename);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return achievements.size();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Iterable#iterator()
|
||||
*/
|
||||
@Override
|
||||
public Iterator<Achievement> iterator() {
|
||||
return achievements.values().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
package forge.achievement;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class AltWinAchievements extends AchievementCollection {
|
||||
public static final AltWinAchievements instance = new AltWinAchievements();
|
||||
|
||||
private AltWinAchievements() {
|
||||
super("Alternate Win Conditions", ForgeConstants.ACHIEVEMENTS_DIR + "altwin.xml", false, ForgeConstants.ALTWIN_ACHIEVEMENT_LIST_FILE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSharedAchivements() {
|
||||
//prevent including shared achievements
|
||||
}
|
||||
|
||||
protected void add(String cardName0, String displayName0, String flavorText0) {
|
||||
add(new AltWinAchievement(cardName0, displayName0, flavorText0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAll(Player player) {
|
||||
//only call update achievement for alternate win condition (if any)
|
||||
if (player.getOutcome().hasWon()) {
|
||||
String altWinCondition = player.getOutcome().altWinSourceName;
|
||||
if (StringUtils.isEmpty(altWinCondition)) {
|
||||
Player opponent = player.getSingleOpponent();
|
||||
if (opponent == null) { return; }
|
||||
|
||||
altWinCondition = opponent.getOutcome().loseConditionSpell;
|
||||
if (StringUtils.isEmpty(altWinCondition)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Achievement achievement = achievements.get(altWinCondition);
|
||||
if (achievement != null) {
|
||||
achievement.update(player);
|
||||
save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AltWinAchievement extends ProgressiveAchievement {
|
||||
private AltWinAchievement(String cardName0, String displayName0, String flavorText0) {
|
||||
super(cardName0, displayName0, "Win a game with " + cardName0, flavorText0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
return true; //if this reaches this point, it can be presumed that alternate win condition achieved
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPaperCard getPaperCard() {
|
||||
return FModel.getMagicDb().getCommonCards().getCard(getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNoun() {
|
||||
return "Win";
|
||||
}
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class AltWinAchievements extends AchievementCollection {
|
||||
public static final AltWinAchievements instance = new AltWinAchievements();
|
||||
|
||||
private AltWinAchievements() {
|
||||
super("Alternate Win Conditions", ForgeConstants.ACHIEVEMENTS_DIR + "altwin.xml", false, ForgeConstants.ALTWIN_ACHIEVEMENT_LIST_FILE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSharedAchivements() {
|
||||
//prevent including shared achievements
|
||||
}
|
||||
|
||||
protected void add(String cardName0, String displayName0, String flavorText0) {
|
||||
add(new AltWinAchievement(cardName0, displayName0, flavorText0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAll(Player player) {
|
||||
//only call update achievement for alternate win condition (if any)
|
||||
if (player.getOutcome().hasWon()) {
|
||||
String altWinCondition = player.getOutcome().altWinSourceName;
|
||||
if (StringUtils.isEmpty(altWinCondition)) {
|
||||
Player opponent = player.getSingleOpponent();
|
||||
if (opponent == null) { return; }
|
||||
|
||||
altWinCondition = opponent.getOutcome().loseConditionSpell;
|
||||
if (StringUtils.isEmpty(altWinCondition)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Achievement achievement = achievements.get(altWinCondition);
|
||||
if (achievement != null) {
|
||||
achievement.update(player);
|
||||
save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AltWinAchievement extends ProgressiveAchievement {
|
||||
private AltWinAchievement(String cardName0, String displayName0, String flavorText0) {
|
||||
super(cardName0, displayName0, "Win a game with " + cardName0, flavorText0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
return true; //if this reaches this point, it can be presumed that alternate win condition achieved
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPaperCard getPaperCard() {
|
||||
return FModel.getMagicDb().getCommonCards().getCard(getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNoun() {
|
||||
return "Win";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class ArcaneMaster extends Achievement {
|
||||
public ArcaneMaster() {
|
||||
super("ArcaneMaster", "Arcane Master", "Win a game without casting", Integer.MAX_VALUE,
|
||||
"more than 3 spells", 3,
|
||||
"more than 2 spells", 2,
|
||||
"more than 1 spell", 1,
|
||||
"any spells", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
|
||||
return defaultValue; // Momir Basic is exempt from this achievement (custom rules do not require any spellcasting by default)
|
||||
}
|
||||
if (player.getOutcome().hasWon()) {
|
||||
return player.getAchievementTracker().spellsCast;
|
||||
}
|
||||
return defaultValue; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Spell";
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class ArcaneMaster extends Achievement {
|
||||
public ArcaneMaster() {
|
||||
super("ArcaneMaster", "Arcane Master", "Win a game without casting", Integer.MAX_VALUE,
|
||||
"more than 3 spells", 3,
|
||||
"more than 2 spells", 2,
|
||||
"more than 1 spell", 1,
|
||||
"any spells", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
|
||||
return defaultValue; // Momir Basic is exempt from this achievement (custom rules do not require any spellcasting by default)
|
||||
}
|
||||
if (player.getOutcome().hasWon()) {
|
||||
return player.getAchievementTracker().spellsCast;
|
||||
}
|
||||
return defaultValue; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Spell";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.GameLossReason;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class Blackjack extends Achievement {
|
||||
private static final int THRESHOLD = 21;
|
||||
|
||||
public Blackjack(int silver0, int gold0, int mythic0) {
|
||||
super("Blackjack", "Blackjack", "Win a game from your commander dealing", 0,
|
||||
String.format("%d combat damage", THRESHOLD), THRESHOLD,
|
||||
String.format("%d combat damage", silver0), silver0,
|
||||
String.format("%d combat damage", gold0), gold0,
|
||||
String.format("%d combat damage", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
for (Player p : game.getRegisteredPlayers()) {
|
||||
if (p.isOpponentOf(player) && p.getOutcome().lossState == GameLossReason.CommanderDamage) {
|
||||
int max = 0;
|
||||
for (Card c : player.getCommanders()) {
|
||||
Integer damage = p.getCommanderDamage(c);
|
||||
if (damage != null && damage >= THRESHOLD) {
|
||||
max = damage;
|
||||
return damage;
|
||||
}
|
||||
}
|
||||
if (max > 0) {
|
||||
return max;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNoun() {
|
||||
return "Damage";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean pluralizeNoun() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.GameLossReason;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class Blackjack extends Achievement {
|
||||
private static final int THRESHOLD = 21;
|
||||
|
||||
public Blackjack(int silver0, int gold0, int mythic0) {
|
||||
super("Blackjack", "Blackjack", "Win a game from your commander dealing", 0,
|
||||
String.format("%d combat damage", THRESHOLD), THRESHOLD,
|
||||
String.format("%d combat damage", silver0), silver0,
|
||||
String.format("%d combat damage", gold0), gold0,
|
||||
String.format("%d combat damage", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
for (Player p : game.getRegisteredPlayers()) {
|
||||
if (p.isOpponentOf(player) && p.getOutcome().lossState == GameLossReason.CommanderDamage) {
|
||||
int max = 0;
|
||||
for (Card c : player.getCommanders()) {
|
||||
Integer damage = p.getCommanderDamage(c);
|
||||
if (damage != null && damage >= THRESHOLD) {
|
||||
max = damage;
|
||||
return damage;
|
||||
}
|
||||
}
|
||||
if (max > 0) {
|
||||
return max;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNoun() {
|
||||
return "Damage";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean pluralizeNoun() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +1,82 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.deck.Deck;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.Player;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class ChallengeAchievements extends AchievementCollection {
|
||||
public static final ChallengeAchievements instance = new ChallengeAchievements();
|
||||
|
||||
private ChallengeAchievements() {
|
||||
super("Challenges", ForgeConstants.ACHIEVEMENTS_DIR + "challenges.xml", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSharedAchivements() {
|
||||
//prevent including shared achievements
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAchievements() {
|
||||
add(new NoCreatures());
|
||||
add(new NoSpells());
|
||||
add(new NoLands());
|
||||
add(new Domain());
|
||||
add("Chromatic", "Chromatic", "Win a game after casting a 5 color spell", "With great color requirements comes great power.");
|
||||
add("Epic", "Epic", "Win a game after resolving a spell with the Epic keyword", "When it's the last spell you ever cast, you better make it count!");
|
||||
}
|
||||
|
||||
private void add(String key0, String displayName0, String description0, String flavorText0) {
|
||||
add(new ChallengeAchievement(key0, displayName0, description0, flavorText0));
|
||||
}
|
||||
|
||||
public static class ChallengeAchievement extends ProgressiveAchievement {
|
||||
protected ChallengeAchievement(String key0, String displayName0, String description0, String flavorText0) {
|
||||
super(key0, displayName0, description0, flavorText0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final String getNoun() {
|
||||
return "Win";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
if (!ChallengeAchievements.checkValidGameMode(game)) {
|
||||
return false;
|
||||
}
|
||||
return player.getOutcome().hasWon() &&
|
||||
player.getAchievementTracker().challengesCompleted.contains(getKey());
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class DeckChallengeAchievement extends ChallengeAchievement {
|
||||
protected DeckChallengeAchievement(String key0, String displayName0, String condition0, String flavorText0) {
|
||||
super(key0, displayName0, "Win a game using a deck " + condition0, flavorText0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean eval(Player player, Game game) {
|
||||
if (!ChallengeAchievements.checkValidGameMode(game)) {
|
||||
return false;
|
||||
}
|
||||
if (player.getOutcome().hasWon()) {
|
||||
return eval(player.getRegisteredPlayer().getDeck());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract boolean eval(Deck deck);
|
||||
}
|
||||
|
||||
public static boolean checkValidGameMode(final Game game) {
|
||||
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)
|
||||
|| game.getRules().hasAppliedVariant(GameType.Puzzle)) {
|
||||
// these modes use a fixed pre-defined deck format, so challenge achievements don't apply in them
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.deck.Deck;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.Player;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class ChallengeAchievements extends AchievementCollection {
|
||||
public static final ChallengeAchievements instance = new ChallengeAchievements();
|
||||
|
||||
private ChallengeAchievements() {
|
||||
super("Challenges", ForgeConstants.ACHIEVEMENTS_DIR + "challenges.xml", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSharedAchivements() {
|
||||
//prevent including shared achievements
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAchievements() {
|
||||
add(new NoCreatures());
|
||||
add(new NoSpells());
|
||||
add(new NoLands());
|
||||
add(new Domain());
|
||||
add("Chromatic", "Chromatic", "Win a game after casting a 5 color spell", "With great color requirements comes great power.");
|
||||
add("Epic", "Epic", "Win a game after resolving a spell with the Epic keyword", "When it's the last spell you ever cast, you better make it count!");
|
||||
}
|
||||
|
||||
private void add(String key0, String displayName0, String description0, String flavorText0) {
|
||||
add(new ChallengeAchievement(key0, displayName0, description0, flavorText0));
|
||||
}
|
||||
|
||||
public static class ChallengeAchievement extends ProgressiveAchievement {
|
||||
protected ChallengeAchievement(String key0, String displayName0, String description0, String flavorText0) {
|
||||
super(key0, displayName0, description0, flavorText0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final String getNoun() {
|
||||
return "Win";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
if (!ChallengeAchievements.checkValidGameMode(game)) {
|
||||
return false;
|
||||
}
|
||||
return player.getOutcome().hasWon() &&
|
||||
player.getAchievementTracker().challengesCompleted.contains(getKey());
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class DeckChallengeAchievement extends ChallengeAchievement {
|
||||
protected DeckChallengeAchievement(String key0, String displayName0, String condition0, String flavorText0) {
|
||||
super(key0, displayName0, "Win a game using a deck " + condition0, flavorText0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean eval(Player player, Game game) {
|
||||
if (!ChallengeAchievements.checkValidGameMode(game)) {
|
||||
return false;
|
||||
}
|
||||
if (player.getOutcome().hasWon()) {
|
||||
return eval(player.getRegisteredPlayer().getDeck());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract boolean eval(Deck deck);
|
||||
}
|
||||
|
||||
public static boolean checkValidGameMode(final Game game) {
|
||||
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)
|
||||
|| game.getRules().hasAppliedVariant(GameType.Puzzle)) {
|
||||
// these modes use a fixed pre-defined deck format, so challenge achievements don't apply in them
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.GameType;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class ConstructedAchievements extends AchievementCollection {
|
||||
public ConstructedAchievements() {
|
||||
super("Constructed", ForgeConstants.ACHIEVEMENTS_DIR + "constructed.xml", false);
|
||||
}
|
||||
|
||||
//add achievements that should appear at the bottom below core achievements for each game mode
|
||||
@Override
|
||||
protected void addAchievements() {
|
||||
add(new VariantWins(GameType.Vanguard, 25, 50, 100));
|
||||
add(new VariantWins(GameType.MomirBasic, 25, 50, 100));
|
||||
add(new VariantWins(GameType.Commander, 25, 50, 100));
|
||||
add(new VariantWins(GameType.TinyLeaders, 25, 50, 100));
|
||||
add(new VariantWins(GameType.Planechase, 25, 50, 100));
|
||||
add(new VariantWins(GameType.Archenemy, 25, 50, 100));
|
||||
add(new Poisoned(15, 25, 40));
|
||||
add(new DeckedOut(8, 4, 2));
|
||||
add(new Blackjack(30, 50, 100));
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.GameType;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class ConstructedAchievements extends AchievementCollection {
|
||||
public ConstructedAchievements() {
|
||||
super("Constructed", ForgeConstants.ACHIEVEMENTS_DIR + "constructed.xml", false);
|
||||
}
|
||||
|
||||
//add achievements that should appear at the bottom below core achievements for each game mode
|
||||
@Override
|
||||
protected void addAchievements() {
|
||||
add(new VariantWins(GameType.Vanguard, 25, 50, 100));
|
||||
add(new VariantWins(GameType.MomirBasic, 25, 50, 100));
|
||||
add(new VariantWins(GameType.Commander, 25, 50, 100));
|
||||
add(new VariantWins(GameType.TinyLeaders, 25, 50, 100));
|
||||
add(new VariantWins(GameType.Planechase, 25, 50, 100));
|
||||
add(new VariantWins(GameType.Archenemy, 25, 50, 100));
|
||||
add(new Poisoned(15, 25, 40));
|
||||
add(new DeckedOut(8, 4, 2));
|
||||
add(new Blackjack(30, 50, 100));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.GameLossReason;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class DeckedOut extends Achievement {
|
||||
public DeckedOut(int silver0, int gold0, int mythic0) {
|
||||
super("DeckedOut", "Decked Out", "Win a game from opponent", Integer.MAX_VALUE,
|
||||
"drawing into an empty library", Integer.MAX_VALUE - 1,
|
||||
String.format("drawing into an empty library by turn %d", silver0), silver0,
|
||||
String.format("drawing into an empty library by turn %d", gold0), gold0,
|
||||
String.format("drawing into an empty library by turn %d", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
Player opponent = player.getSingleOpponent();
|
||||
if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Milled) {
|
||||
return player.getTurn();
|
||||
}
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Turn";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean displayNounBefore() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.GameLossReason;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class DeckedOut extends Achievement {
|
||||
public DeckedOut(int silver0, int gold0, int mythic0) {
|
||||
super("DeckedOut", "Decked Out", "Win a game from opponent", Integer.MAX_VALUE,
|
||||
"drawing into an empty library", Integer.MAX_VALUE - 1,
|
||||
String.format("drawing into an empty library by turn %d", silver0), silver0,
|
||||
String.format("drawing into an empty library by turn %d", gold0), gold0,
|
||||
String.format("drawing into an empty library by turn %d", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
Player opponent = player.getSingleOpponent();
|
||||
if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Milled) {
|
||||
return player.getTurn();
|
||||
}
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Turn";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean displayNounBefore() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
package forge.achievement;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class Domain extends ProgressiveAchievement {
|
||||
public Domain() {
|
||||
super("Domain", "Domain", "Win a game with one of each basic land on the battlefield", "It's nice being able to cast anything you want.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
|
||||
// Not an achievement in Momir Basic (easy to get due to predefined deck contents)
|
||||
return false;
|
||||
}
|
||||
if (player.getOutcome().hasWon()) {
|
||||
Set<String> basicLands = new HashSet<String>();
|
||||
for (Card c : player.getCardsIn(ZoneType.Battlefield)) {
|
||||
if (c.isBasicLand()) {
|
||||
basicLands.add(c.getName());
|
||||
}
|
||||
}
|
||||
return basicLands.size() == 5;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Win";
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class Domain extends ProgressiveAchievement {
|
||||
public Domain() {
|
||||
super("Domain", "Domain", "Win a game with one of each basic land on the battlefield", "It's nice being able to cast anything you want.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
|
||||
// Not an achievement in Momir Basic (easy to get due to predefined deck contents)
|
||||
return false;
|
||||
}
|
||||
if (player.getOutcome().hasWon()) {
|
||||
Set<String> basicLands = new HashSet<String>();
|
||||
for (Card c : player.getCardsIn(ZoneType.Battlefield)) {
|
||||
if (c.isBasicLand()) {
|
||||
basicLands.add(c.getName());
|
||||
}
|
||||
}
|
||||
return basicLands.size() == 5;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Win";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class DraftAchievements extends AchievementCollection {
|
||||
public DraftAchievements() {
|
||||
super("Booster Draft", ForgeConstants.ACHIEVEMENTS_DIR + "draft.xml", true);
|
||||
}
|
||||
|
||||
//add achievements that should appear at the bottom below core achievements for each game mode
|
||||
@Override
|
||||
protected void addAchievements() {
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class DraftAchievements extends AchievementCollection {
|
||||
public DraftAchievements() {
|
||||
super("Booster Draft", ForgeConstants.ACHIEVEMENTS_DIR + "draft.xml", true);
|
||||
}
|
||||
|
||||
//add achievements that should appear at the bottom below core achievements for each game mode
|
||||
@Override
|
||||
protected void addAchievements() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class GameWinStreak extends StreakAchievement {
|
||||
public GameWinStreak(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("GameWinStreak", "Game Win Streak", null,
|
||||
String.format("Win %d games in a row", bronze0), bronze0,
|
||||
String.format("Win %d games in a row", silver0), silver0,
|
||||
String.format("Win %d games in a row", gold0), gold0,
|
||||
String.format("Win %d games in a row", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean eval(Player player, Game game) {
|
||||
return player.getOutcome().hasWon();
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class GameWinStreak extends StreakAchievement {
|
||||
public GameWinStreak(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("GameWinStreak", "Game Win Streak", null,
|
||||
String.format("Win %d games in a row", bronze0), bronze0,
|
||||
String.format("Win %d games in a row", silver0), silver0,
|
||||
String.format("Win %d games in a row", gold0), gold0,
|
||||
String.format("Win %d games in a row", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean eval(Player player, Game game) {
|
||||
return player.getOutcome().hasWon();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class Hellbent extends Achievement {
|
||||
public Hellbent() {
|
||||
super("Hellbent", "Hellbent", "Win a game with no cards in your", 0,
|
||||
"hand", 1,
|
||||
"hand or library", 2,
|
||||
"hand, library, or graveyard", 3,
|
||||
"hand, library, graveyard, or battlefield", 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
if (player.getZone(ZoneType.Hand).size() == 0) {
|
||||
if (player.getZone(ZoneType.Library).size() == 0) {
|
||||
if (player.getZone(ZoneType.Graveyard).size() == 0) {
|
||||
if (player.getZone(ZoneType.Battlefield).size() == 0) {
|
||||
return 4;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubTitle(boolean includeTimestamp) {
|
||||
if (includeTimestamp) {
|
||||
String formattedTimestamp = getFormattedTimestamp();
|
||||
if (formattedTimestamp != null) {
|
||||
return "Earned " + formattedTimestamp;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class Hellbent extends Achievement {
|
||||
public Hellbent() {
|
||||
super("Hellbent", "Hellbent", "Win a game with no cards in your", 0,
|
||||
"hand", 1,
|
||||
"hand or library", 2,
|
||||
"hand, library, or graveyard", 3,
|
||||
"hand, library, graveyard, or battlefield", 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
if (player.getZone(ZoneType.Hand).size() == 0) {
|
||||
if (player.getZone(ZoneType.Library).size() == 0) {
|
||||
if (player.getZone(ZoneType.Graveyard).size() == 0) {
|
||||
if (player.getZone(ZoneType.Battlefield).size() == 0) {
|
||||
return 4;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubTitle(boolean includeTimestamp) {
|
||||
if (includeTimestamp) {
|
||||
String formattedTimestamp = getFormattedTimestamp();
|
||||
if (formattedTimestamp != null) {
|
||||
return "Earned " + formattedTimestamp;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class LifeToSpare extends Achievement {
|
||||
public LifeToSpare(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("LifeToSpare", "Life to Spare", "Win a game with", 0,
|
||||
String.format("%d life more than you started with", bronze0), bronze0,
|
||||
String.format("%d life more than you started with", silver0), silver0,
|
||||
String.format("%d life more than you started with", gold0), gold0,
|
||||
String.format("%d life more than you started with", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
int gainedLife = player.getLife() - player.getStartingLife();
|
||||
if (gainedLife > 0) {
|
||||
return gainedLife;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Life";
|
||||
}
|
||||
@Override
|
||||
protected boolean pluralizeNoun() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class LifeToSpare extends Achievement {
|
||||
public LifeToSpare(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("LifeToSpare", "Life to Spare", "Win a game with", 0,
|
||||
String.format("%d life more than you started with", bronze0), bronze0,
|
||||
String.format("%d life more than you started with", silver0), silver0,
|
||||
String.format("%d life more than you started with", gold0), gold0,
|
||||
String.format("%d life more than you started with", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
int gainedLife = player.getLife() - player.getStartingLife();
|
||||
if (gainedLife > 0) {
|
||||
return gainedLife;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Life";
|
||||
}
|
||||
@Override
|
||||
protected boolean pluralizeNoun() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class ManaFlooded extends Achievement {
|
||||
public ManaFlooded(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("ManaFlooded", "Mana Flooded", "Win a game with at least", 0,
|
||||
String.format("%d lands on the battlefield", bronze0), bronze0,
|
||||
String.format("%d lands on the battlefield", silver0), silver0,
|
||||
String.format("%d lands on the battlefield", gold0), gold0,
|
||||
String.format("%d lands on the battlefield", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
|
||||
return 0; // in Momir Basic, getting a lot of lands out is not an achievement:w
|
||||
}
|
||||
if (player.getOutcome().hasWon()) {
|
||||
int landCount = 0;
|
||||
for (Card c : player.getZone(ZoneType.Battlefield).getCards()) {
|
||||
if (c.isLand()) {
|
||||
landCount++;
|
||||
}
|
||||
}
|
||||
return landCount;
|
||||
}
|
||||
return 0; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Land";
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class ManaFlooded extends Achievement {
|
||||
public ManaFlooded(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("ManaFlooded", "Mana Flooded", "Win a game with at least", 0,
|
||||
String.format("%d lands on the battlefield", bronze0), bronze0,
|
||||
String.format("%d lands on the battlefield", silver0), silver0,
|
||||
String.format("%d lands on the battlefield", gold0), gold0,
|
||||
String.format("%d lands on the battlefield", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (game.getRules().hasAppliedVariant(GameType.MomirBasic)) {
|
||||
return 0; // in Momir Basic, getting a lot of lands out is not an achievement:w
|
||||
}
|
||||
if (player.getOutcome().hasWon()) {
|
||||
int landCount = 0;
|
||||
for (Card c : player.getZone(ZoneType.Battlefield).getCards()) {
|
||||
if (c.isLand()) {
|
||||
landCount++;
|
||||
}
|
||||
}
|
||||
return landCount;
|
||||
}
|
||||
return 0; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Land";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class ManaScrewed extends Achievement {
|
||||
public ManaScrewed() {
|
||||
super("ManaScrewed", "Mana Screwed", "Win a game despite playing only", Integer.MAX_VALUE,
|
||||
"3 lands", 3,
|
||||
"2 lands", 2,
|
||||
"1 land", 1,
|
||||
"0 lands", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
return player.getAchievementTracker().landsPlayed;
|
||||
}
|
||||
return defaultValue; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Land";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int performConversion(int value, long timestamp) {
|
||||
//throw out any ManaScrewed achievements earned before timestamp support added
|
||||
//since there was a bug where it was earned almost always
|
||||
if (timestamp == 0) {
|
||||
return defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class ManaScrewed extends Achievement {
|
||||
public ManaScrewed() {
|
||||
super("ManaScrewed", "Mana Screwed", "Win a game despite playing only", Integer.MAX_VALUE,
|
||||
"3 lands", 3,
|
||||
"2 lands", 2,
|
||||
"1 land", 1,
|
||||
"0 lands", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
return player.getAchievementTracker().landsPlayed;
|
||||
}
|
||||
return defaultValue; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Land";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int performConversion(int value, long timestamp) {
|
||||
//throw out any ManaScrewed achievements earned before timestamp support added
|
||||
//since there was a bug where it was earned almost always
|
||||
if (timestamp == 0) {
|
||||
return defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class MatchWinStreak extends StreakAchievement {
|
||||
public MatchWinStreak(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("MatchWinStreak", "Match Win Streak", null,
|
||||
String.format("Win %d matches in a row", bronze0), bronze0,
|
||||
String.format("Win %d matches in a row", silver0), silver0,
|
||||
String.format("Win %d matches in a row", gold0), gold0,
|
||||
String.format("Win %d matches in a row", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean eval(Player player, Game game) {
|
||||
if (game.getMatch().isMatchOver()) {
|
||||
if (game.getMatch().isWonBy(player.getLobbyPlayer())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class MatchWinStreak extends StreakAchievement {
|
||||
public MatchWinStreak(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("MatchWinStreak", "Match Win Streak", null,
|
||||
String.format("Win %d matches in a row", bronze0), bronze0,
|
||||
String.format("Win %d matches in a row", silver0), silver0,
|
||||
String.format("Win %d matches in a row", gold0), gold0,
|
||||
String.format("Win %d matches in a row", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean eval(Player player, Game game) {
|
||||
if (game.getMatch().isMatchOver()) {
|
||||
if (game.getMatch().isWonBy(player.getLobbyPlayer())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class NeedForSpeed extends Achievement {
|
||||
public NeedForSpeed(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("NeedForSpeed", "Need for Speed", null, Integer.MAX_VALUE,
|
||||
String.format("Win a game by turn %d", bronze0), bronze0,
|
||||
String.format("Win a game by turn %d", silver0), silver0,
|
||||
String.format("Win a game by turn %d", gold0), gold0,
|
||||
String.format("Win a game by turn %d", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
return player.getTurn();
|
||||
}
|
||||
return defaultValue; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Turn";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean displayNounBefore() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class NeedForSpeed extends Achievement {
|
||||
public NeedForSpeed(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("NeedForSpeed", "Need for Speed", null, Integer.MAX_VALUE,
|
||||
String.format("Win a game by turn %d", bronze0), bronze0,
|
||||
String.format("Win a game by turn %d", silver0), silver0,
|
||||
String.format("Win a game by turn %d", gold0), gold0,
|
||||
String.format("Win a game by turn %d", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
return player.getTurn();
|
||||
}
|
||||
return defaultValue; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Turn";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean displayNounBefore() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
package forge.achievement;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
|
||||
import forge.deck.Deck;
|
||||
import forge.item.PaperCard;
|
||||
|
||||
public class NoCreatures extends DeckChallengeAchievement {
|
||||
public NoCreatures() {
|
||||
super("NoCreatures", "No Creatures", "with no creatures", "I'm not really an animal person.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Deck deck) {
|
||||
for (Entry<PaperCard, Integer> card : deck.getMain()) {
|
||||
if (card.getKey().getRules().getType().isCreature()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
|
||||
import forge.deck.Deck;
|
||||
import forge.item.PaperCard;
|
||||
|
||||
public class NoCreatures extends DeckChallengeAchievement {
|
||||
public NoCreatures() {
|
||||
super("NoCreatures", "No Creatures", "with no creatures", "I'm not really an animal person.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Deck deck) {
|
||||
for (Entry<PaperCard, Integer> card : deck.getMain()) {
|
||||
if (card.getKey().getRules().getType().isCreature()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
package forge.achievement;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
|
||||
import forge.deck.Deck;
|
||||
import forge.item.PaperCard;
|
||||
|
||||
public class NoLands extends DeckChallengeAchievement {
|
||||
public NoLands() {
|
||||
super("NoLands", "No Lands", "with no lands", "I prefer mana from more artificial sources.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Deck deck) {
|
||||
for (Entry<PaperCard, Integer> card : deck.getMain()) {
|
||||
if (card.getKey().getRules().getType().isLand()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
|
||||
import forge.deck.Deck;
|
||||
import forge.item.PaperCard;
|
||||
|
||||
public class NoLands extends DeckChallengeAchievement {
|
||||
public NoLands() {
|
||||
super("NoLands", "No Lands", "with no lands", "I prefer mana from more artificial sources.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Deck deck) {
|
||||
for (Entry<PaperCard, Integer> card : deck.getMain()) {
|
||||
if (card.getKey().getRules().getType().isLand()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
package forge.achievement;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
|
||||
import forge.card.CardType;
|
||||
import forge.deck.Deck;
|
||||
import forge.item.PaperCard;
|
||||
|
||||
public class NoSpells extends DeckChallengeAchievement {
|
||||
public NoSpells() {
|
||||
super("NoSpells", "No Spells", "with only creatures and lands", "I let my army do the talking.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Deck deck) {
|
||||
for (Entry<PaperCard, Integer> card : deck.getMain()) {
|
||||
CardType type = card.getKey().getRules().getType();
|
||||
if (!type.isCreature() && !type.isLand()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.achievement.ChallengeAchievements.DeckChallengeAchievement;
|
||||
import forge.card.CardType;
|
||||
import forge.deck.Deck;
|
||||
import forge.item.PaperCard;
|
||||
|
||||
public class NoSpells extends DeckChallengeAchievement {
|
||||
public NoSpells() {
|
||||
super("NoSpells", "No Spells", "with only creatures and lands", "I let my army do the talking.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Deck deck) {
|
||||
for (Entry<PaperCard, Integer> card : deck.getMain()) {
|
||||
CardType type = card.getKey().getRules().getType();
|
||||
if (!type.isCreature() && !type.isLand()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class Overkill extends Achievement {
|
||||
public Overkill(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("Overkill", "Overkill", "Win a game with opponent at", 0,
|
||||
String.format("%d life", bronze0), bronze0,
|
||||
String.format("%d life", silver0), silver0,
|
||||
String.format("%d life", gold0), gold0,
|
||||
String.format("%d life", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
Player opponent = player.getSingleOpponent();
|
||||
if (opponent != null && opponent.getLife() < 0) {
|
||||
return opponent.getLife();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Life";
|
||||
}
|
||||
@Override
|
||||
protected boolean pluralizeNoun() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int performConversion(int value, long timestamp) {
|
||||
//perform conversion to handle data from old format before supporting negative thresholds
|
||||
if (value > 0) {
|
||||
value = -value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class Overkill extends Achievement {
|
||||
public Overkill(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("Overkill", "Overkill", "Win a game with opponent at", 0,
|
||||
String.format("%d life", bronze0), bronze0,
|
||||
String.format("%d life", silver0), silver0,
|
||||
String.format("%d life", gold0), gold0,
|
||||
String.format("%d life", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
Player opponent = player.getSingleOpponent();
|
||||
if (opponent != null && opponent.getLife() < 0) {
|
||||
return opponent.getLife();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Life";
|
||||
}
|
||||
@Override
|
||||
protected boolean pluralizeNoun() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int performConversion(int value, long timestamp) {
|
||||
//perform conversion to handle data from old format before supporting negative thresholds
|
||||
if (value > 0) {
|
||||
value = -value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.assets.ISkinImage;
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class PlaneswalkerAchievements extends AchievementCollection {
|
||||
public static final PlaneswalkerAchievements instance = new PlaneswalkerAchievements();
|
||||
|
||||
public static ISkinImage getTrophyImage(String planeswalkerName) {
|
||||
return GuiBase.getInterface().createLayeredImage(FSkinProp.IMG_SPECIAL_TROPHY, ForgeConstants.CACHE_ACHIEVEMENTS_DIR + "/" + planeswalkerName + ".png", 1);
|
||||
}
|
||||
|
||||
private PlaneswalkerAchievements() {
|
||||
super("Planeswalker Ultimates", ForgeConstants.ACHIEVEMENTS_DIR + "planeswalkers.xml", false, ForgeConstants.PLANESWALKER_ACHIEVEMENT_LIST_FILE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSharedAchivements() {
|
||||
//prevent including shared achievements
|
||||
}
|
||||
|
||||
protected void add(String cardName0, String displayName0, String flavorText0) {
|
||||
add(new PlaneswalkerUltimate(cardName0, displayName0, flavorText0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAll(Player player) {
|
||||
//only call update achievements for any ultimates activated during the game
|
||||
if (player.getOutcome().hasWon()) {
|
||||
boolean needSave = false;
|
||||
for (String ultimate : player.getAchievementTracker().activatedUltimates) {
|
||||
Achievement achievement = achievements.get(ultimate);
|
||||
if (achievement != null) {
|
||||
achievement.update(player);
|
||||
needSave = true;
|
||||
}
|
||||
}
|
||||
if (needSave) {
|
||||
save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PlaneswalkerUltimate extends ProgressiveAchievement {
|
||||
private PlaneswalkerUltimate(String cardName0, String displayName0, String flavorText0) {
|
||||
super(cardName0, displayName0, "Win a game after activating " + cardName0 + "'s ultimate", flavorText0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
return true; //if this reaches this point, it can be presumed that alternate win condition achieved
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPaperCard getPaperCard() {
|
||||
return FModel.getMagicDb().getCommonCards().getCard(getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Win";
|
||||
}
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.assets.ISkinImage;
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class PlaneswalkerAchievements extends AchievementCollection {
|
||||
public static final PlaneswalkerAchievements instance = new PlaneswalkerAchievements();
|
||||
|
||||
public static ISkinImage getTrophyImage(String planeswalkerName) {
|
||||
return GuiBase.getInterface().createLayeredImage(FSkinProp.IMG_SPECIAL_TROPHY, ForgeConstants.CACHE_ACHIEVEMENTS_DIR + "/" + planeswalkerName + ".png", 1);
|
||||
}
|
||||
|
||||
private PlaneswalkerAchievements() {
|
||||
super("Planeswalker Ultimates", ForgeConstants.ACHIEVEMENTS_DIR + "planeswalkers.xml", false, ForgeConstants.PLANESWALKER_ACHIEVEMENT_LIST_FILE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSharedAchivements() {
|
||||
//prevent including shared achievements
|
||||
}
|
||||
|
||||
protected void add(String cardName0, String displayName0, String flavorText0) {
|
||||
add(new PlaneswalkerUltimate(cardName0, displayName0, flavorText0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAll(Player player) {
|
||||
//only call update achievements for any ultimates activated during the game
|
||||
if (player.getOutcome().hasWon()) {
|
||||
boolean needSave = false;
|
||||
for (String ultimate : player.getAchievementTracker().activatedUltimates) {
|
||||
Achievement achievement = achievements.get(ultimate);
|
||||
if (achievement != null) {
|
||||
achievement.update(player);
|
||||
needSave = true;
|
||||
}
|
||||
}
|
||||
if (needSave) {
|
||||
save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PlaneswalkerUltimate extends ProgressiveAchievement {
|
||||
private PlaneswalkerUltimate(String cardName0, String displayName0, String flavorText0) {
|
||||
super(cardName0, displayName0, "Win a game after activating " + cardName0 + "'s ultimate", flavorText0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
return true; //if this reaches this point, it can be presumed that alternate win condition achieved
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPaperCard getPaperCard() {
|
||||
return FModel.getMagicDb().getCommonCards().getCard(getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Win";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.GameLossReason;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class Poisoned extends Achievement {
|
||||
private static final int THRESHOLD = 10;
|
||||
|
||||
public Poisoned(int silver0, int gold0, int mythic0) {
|
||||
super("Poisoned", "Poisoned", "Win a game by giving opponent", 0,
|
||||
String.format("%d poison counters", THRESHOLD), THRESHOLD,
|
||||
String.format("%d poison counters", silver0), silver0,
|
||||
String.format("%d poison counters", gold0), gold0,
|
||||
String.format("%d poison counters", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
Player opponent = player.getSingleOpponent();
|
||||
if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Poisoned) {
|
||||
return opponent.getPoisonCounters();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Counter";
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.GameLossReason;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class Poisoned extends Achievement {
|
||||
private static final int THRESHOLD = 10;
|
||||
|
||||
public Poisoned(int silver0, int gold0, int mythic0) {
|
||||
super("Poisoned", "Poisoned", "Win a game by giving opponent", 0,
|
||||
String.format("%d poison counters", THRESHOLD), THRESHOLD,
|
||||
String.format("%d poison counters", silver0), silver0,
|
||||
String.format("%d poison counters", gold0), gold0,
|
||||
String.format("%d poison counters", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
Player opponent = player.getSingleOpponent();
|
||||
if (opponent != null && opponent.getOutcome().lossState == GameLossReason.Poisoned) {
|
||||
return opponent.getPoisonCounters();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Counter";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.util.Lang;
|
||||
|
||||
public abstract class ProgressiveAchievement extends Achievement {
|
||||
protected ProgressiveAchievement(String key0, String displayName0, String description0, String flavorText0) {
|
||||
super(key0, displayName0, description0, flavorText0, 0);
|
||||
}
|
||||
//use this constructor for regular tiered achievements
|
||||
protected ProgressiveAchievement(String key0, String displayName0, String sharedDesc0,
|
||||
String commonDesc0, int commonThreshold0,
|
||||
String uncommonDesc0, int uncommonThreshold0,
|
||||
String rareDesc0, int rareThreshold0,
|
||||
String mythicDesc0, int mythicThreshold0) {
|
||||
super(key0, displayName0, sharedDesc0, 0, commonDesc0, commonThreshold0,
|
||||
uncommonDesc0, uncommonThreshold0, rareDesc0, rareThreshold0,
|
||||
mythicDesc0, mythicThreshold0);
|
||||
}
|
||||
|
||||
protected abstract boolean eval(Player player, Game game);
|
||||
|
||||
@Override
|
||||
protected final int evaluate(Player player, Game game) {
|
||||
if (eval(player, game)) {
|
||||
return getBest() + 1;
|
||||
}
|
||||
return getBest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getSubTitle(boolean includeTimestamp) {
|
||||
String subTitle = getBest() + " " + (getBest() != 1 ? Lang.getPlural(getNoun()) : getNoun());
|
||||
if (includeTimestamp) {
|
||||
String formattedTimestamp = getFormattedTimestamp();
|
||||
if (formattedTimestamp != null) {
|
||||
subTitle += " (" + formattedTimestamp + ")";
|
||||
}
|
||||
}
|
||||
return subTitle;
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.util.Lang;
|
||||
|
||||
public abstract class ProgressiveAchievement extends Achievement {
|
||||
protected ProgressiveAchievement(String key0, String displayName0, String description0, String flavorText0) {
|
||||
super(key0, displayName0, description0, flavorText0, 0);
|
||||
}
|
||||
//use this constructor for regular tiered achievements
|
||||
protected ProgressiveAchievement(String key0, String displayName0, String sharedDesc0,
|
||||
String commonDesc0, int commonThreshold0,
|
||||
String uncommonDesc0, int uncommonThreshold0,
|
||||
String rareDesc0, int rareThreshold0,
|
||||
String mythicDesc0, int mythicThreshold0) {
|
||||
super(key0, displayName0, sharedDesc0, 0, commonDesc0, commonThreshold0,
|
||||
uncommonDesc0, uncommonThreshold0, rareDesc0, rareThreshold0,
|
||||
mythicDesc0, mythicThreshold0);
|
||||
}
|
||||
|
||||
protected abstract boolean eval(Player player, Game game);
|
||||
|
||||
@Override
|
||||
protected final int evaluate(Player player, Game game) {
|
||||
if (eval(player, game)) {
|
||||
return getBest() + 1;
|
||||
}
|
||||
return getBest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getSubTitle(boolean includeTimestamp) {
|
||||
String subTitle = getBest() + " " + (getBest() != 1 ? Lang.getPlural(getNoun()) : getNoun());
|
||||
if (includeTimestamp) {
|
||||
String formattedTimestamp = getFormattedTimestamp();
|
||||
if (formattedTimestamp != null) {
|
||||
subTitle += " (" + formattedTimestamp + ")";
|
||||
}
|
||||
}
|
||||
return subTitle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class QuestAchievements extends AchievementCollection {
|
||||
public QuestAchievements() {
|
||||
super("Quest Mode", ForgeConstants.ACHIEVEMENTS_DIR + "quest.xml", false);
|
||||
}
|
||||
|
||||
//add achievements that should appear at the bottom below core achievements for each game mode
|
||||
@Override
|
||||
protected void addAchievements() {
|
||||
add(new Poisoned(15, 25, 40));
|
||||
add(new DeckedOut(8, 4, 2));
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class QuestAchievements extends AchievementCollection {
|
||||
public QuestAchievements() {
|
||||
super("Quest Mode", ForgeConstants.ACHIEVEMENTS_DIR + "quest.xml", false);
|
||||
}
|
||||
|
||||
//add achievements that should appear at the bottom below core achievements for each game mode
|
||||
@Override
|
||||
protected void addAchievements() {
|
||||
add(new Poisoned(15, 25, 40));
|
||||
add(new DeckedOut(8, 4, 2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class RagsToRiches extends Achievement {
|
||||
public RagsToRiches() {
|
||||
super("RagsToRiches", "Rags to Riches", "Win a game after mulliganing to", 7,
|
||||
"4 cards", 4,
|
||||
"3 cards", 3,
|
||||
"2 cards", 2,
|
||||
"1 card", 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon() && player.getAchievementTracker().mulliganTo < defaultValue) {
|
||||
return player.getAchievementTracker().mulliganTo;
|
||||
}
|
||||
return defaultValue; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Card";
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class RagsToRiches extends Achievement {
|
||||
public RagsToRiches() {
|
||||
super("RagsToRiches", "Rags to Riches", "Win a game after mulliganing to", 7,
|
||||
"4 cards", 4,
|
||||
"3 cards", 3,
|
||||
"2 cards", 2,
|
||||
"1 card", 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon() && player.getAchievementTracker().mulliganTo < defaultValue) {
|
||||
return player.getAchievementTracker().mulliganTo;
|
||||
}
|
||||
return defaultValue; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Card";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class SealedAchievements extends AchievementCollection {
|
||||
public SealedAchievements() {
|
||||
super("Sealed Deck", ForgeConstants.ACHIEVEMENTS_DIR + "sealed.xml", true);
|
||||
}
|
||||
|
||||
//add achievements that should appear at the bottom below core achievements for each game mode
|
||||
@Override
|
||||
protected void addAchievements() {
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class SealedAchievements extends AchievementCollection {
|
||||
public SealedAchievements() {
|
||||
super("Sealed Deck", ForgeConstants.ACHIEVEMENTS_DIR + "sealed.xml", true);
|
||||
}
|
||||
|
||||
//add achievements that should appear at the bottom below core achievements for each game mode
|
||||
@Override
|
||||
protected void addAchievements() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class StormChaser extends Achievement {
|
||||
public StormChaser(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("StormChaser", "Storm Chaser", "Win a game after casting", 0,
|
||||
String.format("%d spells in a single turn", bronze0), bronze0,
|
||||
String.format("%d spells in a single turn", silver0), silver0,
|
||||
String.format("%d spells in a single turn", gold0), gold0,
|
||||
String.format("%d spells in a single turn", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
return player.getAchievementTracker().maxStormCount;
|
||||
}
|
||||
return 0; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Spell";
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class StormChaser extends Achievement {
|
||||
public StormChaser(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("StormChaser", "Storm Chaser", "Win a game after casting", 0,
|
||||
String.format("%d spells in a single turn", bronze0), bronze0,
|
||||
String.format("%d spells in a single turn", silver0), silver0,
|
||||
String.format("%d spells in a single turn", gold0), gold0,
|
||||
String.format("%d spells in a single turn", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int evaluate(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
return player.getAchievementTracker().maxStormCount;
|
||||
}
|
||||
return 0; //indicate that player didn't win
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Spell";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
package forge.achievement;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
public abstract class StreakAchievement extends Achievement {
|
||||
private int current;
|
||||
|
||||
//use this constructor for regular tiered achievements
|
||||
protected StreakAchievement(final String key0, final String displayName0, final String sharedDesc0,
|
||||
final String commonDesc0, final int commonThreshold0,
|
||||
final String uncommonDesc0, final int uncommonThreshold0,
|
||||
final String rareDesc0, final int rareThreshold0,
|
||||
final String mythicDesc0, final int mythicThreshold0) {
|
||||
super(key0, displayName0, sharedDesc0, 0, commonDesc0, commonThreshold0,
|
||||
uncommonDesc0, uncommonThreshold0, rareDesc0, rareThreshold0,
|
||||
mythicDesc0, mythicThreshold0);
|
||||
}
|
||||
|
||||
protected abstract Boolean eval(Player player, Game game);
|
||||
|
||||
@Override
|
||||
protected final int evaluate(final Player player, final Game game) {
|
||||
final Boolean val = eval(player, game);
|
||||
if (val != null) { //null means don't increment or reset
|
||||
if (val) {
|
||||
current++;
|
||||
}
|
||||
else {
|
||||
current = 0;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Active: " + current; //override here so active streak appears after best
|
||||
}
|
||||
@Override
|
||||
protected boolean pluralizeNoun() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveToXml(final Element el) {
|
||||
super.saveToXml(el);
|
||||
el.setAttribute("current", String.valueOf(current));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFromXml(final Element el) {
|
||||
super.loadFromXml(el);
|
||||
current = XmlUtil.getIntAttribute(el, "current");
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
public abstract class StreakAchievement extends Achievement {
|
||||
private int current;
|
||||
|
||||
//use this constructor for regular tiered achievements
|
||||
protected StreakAchievement(final String key0, final String displayName0, final String sharedDesc0,
|
||||
final String commonDesc0, final int commonThreshold0,
|
||||
final String uncommonDesc0, final int uncommonThreshold0,
|
||||
final String rareDesc0, final int rareThreshold0,
|
||||
final String mythicDesc0, final int mythicThreshold0) {
|
||||
super(key0, displayName0, sharedDesc0, 0, commonDesc0, commonThreshold0,
|
||||
uncommonDesc0, uncommonThreshold0, rareDesc0, rareThreshold0,
|
||||
mythicDesc0, mythicThreshold0);
|
||||
}
|
||||
|
||||
protected abstract Boolean eval(Player player, Game game);
|
||||
|
||||
@Override
|
||||
protected final int evaluate(final Player player, final Game game) {
|
||||
final Boolean val = eval(player, game);
|
||||
if (val != null) { //null means don't increment or reset
|
||||
if (val) {
|
||||
current++;
|
||||
}
|
||||
else {
|
||||
current = 0;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Active: " + current; //override here so active streak appears after best
|
||||
}
|
||||
@Override
|
||||
protected boolean pluralizeNoun() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveToXml(final Element el) {
|
||||
super.saveToXml(el);
|
||||
el.setAttribute("current", String.valueOf(current));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFromXml(final Element el) {
|
||||
super.loadFromXml(el);
|
||||
current = XmlUtil.getIntAttribute(el, "current");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class TotalGameWins extends ProgressiveAchievement {
|
||||
public TotalGameWins(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("TotalGameWins", "Total Game Wins", null,
|
||||
String.format("Win %d games", bronze0), bronze0,
|
||||
String.format("Win %d games", silver0), silver0,
|
||||
String.format("Win %d games", gold0), gold0,
|
||||
String.format("Win %d games", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
return player.getOutcome().hasWon();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Game";
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class TotalGameWins extends ProgressiveAchievement {
|
||||
public TotalGameWins(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("TotalGameWins", "Total Game Wins", null,
|
||||
String.format("Win %d games", bronze0), bronze0,
|
||||
String.format("Win %d games", silver0), silver0,
|
||||
String.format("Win %d games", gold0), gold0,
|
||||
String.format("Win %d games", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
return player.getOutcome().hasWon();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Game";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class TotalMatchWins extends ProgressiveAchievement {
|
||||
public TotalMatchWins(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("TotalMatchWins", "Total Match Wins", null,
|
||||
String.format("Win %d matches", bronze0), bronze0,
|
||||
String.format("Win %d matches", silver0), silver0,
|
||||
String.format("Win %d matches", gold0), gold0,
|
||||
String.format("Win %d matches", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
return game.getMatch().isMatchOver() && game.getMatch().isWonBy(player.getLobbyPlayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Match";
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class TotalMatchWins extends ProgressiveAchievement {
|
||||
public TotalMatchWins(int bronze0, int silver0, int gold0, int mythic0) {
|
||||
super("TotalMatchWins", "Total Match Wins", null,
|
||||
String.format("Win %d matches", bronze0), bronze0,
|
||||
String.format("Win %d matches", silver0), silver0,
|
||||
String.format("Win %d matches", gold0), gold0,
|
||||
String.format("Win %d matches", mythic0), mythic0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
return game.getMatch().isMatchOver() && game.getMatch().isWonBy(player.getLobbyPlayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Match";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.Player;
|
||||
import forge.util.Lang;
|
||||
|
||||
public class VariantWins extends ProgressiveAchievement {
|
||||
private GameType variant;
|
||||
|
||||
public VariantWins(GameType variant0, int silver0, int gold0, int mythic0) {
|
||||
super(variant0.name(), variant0.toString(), null,
|
||||
"Win " + Lang.nounWithAmount(1, variant0.toString() + " game"), 1,
|
||||
"Win " + Lang.nounWithAmount(silver0, variant0.toString() + " game"), silver0,
|
||||
"Win " + Lang.nounWithAmount(gold0, variant0.toString() + " game"), gold0,
|
||||
"Win " + Lang.nounWithAmount(mythic0, variant0.toString() + " game"), mythic0);
|
||||
variant = variant0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
if (game.getRules().hasAppliedVariant(variant)) {
|
||||
return true;
|
||||
}
|
||||
if (variant == GameType.Archenemy && game.getRules().hasAppliedVariant(GameType.ArchenemyRumble)) {
|
||||
return true; //lump Archenemy Rumble into same achievement as Archenemy
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Win";
|
||||
}
|
||||
}
|
||||
package forge.achievement;
|
||||
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.Player;
|
||||
import forge.util.Lang;
|
||||
|
||||
public class VariantWins extends ProgressiveAchievement {
|
||||
private GameType variant;
|
||||
|
||||
public VariantWins(GameType variant0, int silver0, int gold0, int mythic0) {
|
||||
super(variant0.name(), variant0.toString(), null,
|
||||
"Win " + Lang.nounWithAmount(1, variant0.toString() + " game"), 1,
|
||||
"Win " + Lang.nounWithAmount(silver0, variant0.toString() + " game"), silver0,
|
||||
"Win " + Lang.nounWithAmount(gold0, variant0.toString() + " game"), gold0,
|
||||
"Win " + Lang.nounWithAmount(mythic0, variant0.toString() + " game"), mythic0);
|
||||
variant = variant0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean eval(Player player, Game game) {
|
||||
if (player.getOutcome().hasWon()) {
|
||||
if (game.getRules().hasAppliedVariant(variant)) {
|
||||
return true;
|
||||
}
|
||||
if (variant == GameType.Archenemy && game.getRules().hasAppliedVariant(GameType.ArchenemyRumble)) {
|
||||
return true; //lump Archenemy Rumble into same achievement as Archenemy
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getNoun() {
|
||||
return "Win";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package forge.assets;
|
||||
|
||||
public interface IHasSkinProp {
|
||||
FSkinProp getSkinProp();
|
||||
}
|
||||
package forge.assets;
|
||||
|
||||
public interface IHasSkinProp {
|
||||
FSkinProp getSkinProp();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package forge.assets;
|
||||
|
||||
public interface ISkinImage {
|
||||
|
||||
}
|
||||
package forge.assets;
|
||||
|
||||
public interface ISkinImage {
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,120 +1,120 @@
|
||||
package forge.card;
|
||||
|
||||
import forge.item.IPaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Preferences associated with individual cards
|
||||
*
|
||||
*/
|
||||
public class CardPreferences {
|
||||
private static Map<String, CardPreferences> allPrefs = new HashMap<String, CardPreferences>();
|
||||
|
||||
public static CardPreferences getPrefs(IPaperCard card) {
|
||||
String cardName = card.getName();
|
||||
CardPreferences prefs = allPrefs.get(cardName);
|
||||
if (prefs == null) {
|
||||
prefs = new CardPreferences(cardName);
|
||||
allPrefs.put(cardName, prefs);
|
||||
}
|
||||
return prefs;
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
allPrefs.clear();
|
||||
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final Document document = builder.parse(new File(ForgeConstants.CARD_PREFS_FILE));
|
||||
final NodeList cards = document.getElementsByTagName("card");
|
||||
for (int i = 0; i < cards.getLength(); i++) {
|
||||
final Element el = (Element)cards.item(i);
|
||||
final CardPreferences prefs = new CardPreferences(el.getAttribute("name"));
|
||||
allPrefs.put(prefs.cardName, prefs);
|
||||
prefs.setStarCount(XmlUtil.getIntAttribute(el, "stars"));
|
||||
prefs.setPreferredArt(XmlUtil.getStringAttribute(el, "art"));
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
//ok if file not found
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
Element root = document.createElement("preferences");
|
||||
root.setAttribute("type", "cards");
|
||||
document.appendChild(root);
|
||||
|
||||
for (Map.Entry<String, CardPreferences> entry : allPrefs.entrySet()) {
|
||||
CardPreferences prefs = entry.getValue();
|
||||
if (prefs.starCount > 0 || prefs.preferredArt != null) {
|
||||
Element card = document.createElement("card");
|
||||
card.setAttribute("name", entry.getKey());
|
||||
if (prefs.starCount > 0) {
|
||||
card.setAttribute("stars", String.valueOf(prefs.starCount));
|
||||
}
|
||||
if (prefs.preferredArt != null) {
|
||||
card.setAttribute("art", prefs.preferredArt);
|
||||
}
|
||||
root.appendChild(card);
|
||||
}
|
||||
}
|
||||
XmlUtil.saveDocument(document, ForgeConstants.CARD_PREFS_FILE);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private final String cardName;
|
||||
private int starCount;
|
||||
private String preferredArt;
|
||||
|
||||
private CardPreferences(String cardName0) {
|
||||
cardName = cardName0;
|
||||
}
|
||||
|
||||
public int getStarCount() {
|
||||
return starCount;
|
||||
}
|
||||
|
||||
public void setStarCount(int starCount0) {
|
||||
starCount = starCount0;
|
||||
}
|
||||
|
||||
public String getPreferredArt() {
|
||||
return preferredArt;
|
||||
}
|
||||
|
||||
public void setPreferredArt(String preferredArt0) {
|
||||
if (preferredArt0 == null) {
|
||||
preferredArt = null;
|
||||
return;
|
||||
}
|
||||
if (preferredArt0.equals(preferredArt)) { return; }
|
||||
|
||||
if (FModel.getMagicDb().getCommonCards().setPreferredArt(cardName, preferredArt0)) {
|
||||
preferredArt = preferredArt0;
|
||||
}
|
||||
}
|
||||
package forge.card;
|
||||
|
||||
import forge.item.IPaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Preferences associated with individual cards
|
||||
*
|
||||
*/
|
||||
public class CardPreferences {
|
||||
private static Map<String, CardPreferences> allPrefs = new HashMap<String, CardPreferences>();
|
||||
|
||||
public static CardPreferences getPrefs(IPaperCard card) {
|
||||
String cardName = card.getName();
|
||||
CardPreferences prefs = allPrefs.get(cardName);
|
||||
if (prefs == null) {
|
||||
prefs = new CardPreferences(cardName);
|
||||
allPrefs.put(cardName, prefs);
|
||||
}
|
||||
return prefs;
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
allPrefs.clear();
|
||||
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final Document document = builder.parse(new File(ForgeConstants.CARD_PREFS_FILE));
|
||||
final NodeList cards = document.getElementsByTagName("card");
|
||||
for (int i = 0; i < cards.getLength(); i++) {
|
||||
final Element el = (Element)cards.item(i);
|
||||
final CardPreferences prefs = new CardPreferences(el.getAttribute("name"));
|
||||
allPrefs.put(prefs.cardName, prefs);
|
||||
prefs.setStarCount(XmlUtil.getIntAttribute(el, "stars"));
|
||||
prefs.setPreferredArt(XmlUtil.getStringAttribute(el, "art"));
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
//ok if file not found
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
Element root = document.createElement("preferences");
|
||||
root.setAttribute("type", "cards");
|
||||
document.appendChild(root);
|
||||
|
||||
for (Map.Entry<String, CardPreferences> entry : allPrefs.entrySet()) {
|
||||
CardPreferences prefs = entry.getValue();
|
||||
if (prefs.starCount > 0 || prefs.preferredArt != null) {
|
||||
Element card = document.createElement("card");
|
||||
card.setAttribute("name", entry.getKey());
|
||||
if (prefs.starCount > 0) {
|
||||
card.setAttribute("stars", String.valueOf(prefs.starCount));
|
||||
}
|
||||
if (prefs.preferredArt != null) {
|
||||
card.setAttribute("art", prefs.preferredArt);
|
||||
}
|
||||
root.appendChild(card);
|
||||
}
|
||||
}
|
||||
XmlUtil.saveDocument(document, ForgeConstants.CARD_PREFS_FILE);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private final String cardName;
|
||||
private int starCount;
|
||||
private String preferredArt;
|
||||
|
||||
private CardPreferences(String cardName0) {
|
||||
cardName = cardName0;
|
||||
}
|
||||
|
||||
public int getStarCount() {
|
||||
return starCount;
|
||||
}
|
||||
|
||||
public void setStarCount(int starCount0) {
|
||||
starCount = starCount0;
|
||||
}
|
||||
|
||||
public String getPreferredArt() {
|
||||
return preferredArt;
|
||||
}
|
||||
|
||||
public void setPreferredArt(String preferredArt0) {
|
||||
if (preferredArt0 == null) {
|
||||
preferredArt = null;
|
||||
return;
|
||||
}
|
||||
if (preferredArt0.equals(preferredArt)) { return; }
|
||||
|
||||
if (FModel.getMagicDb().getCommonCards().setPreferredArt(cardName, preferredArt0)) {
|
||||
preferredArt = preferredArt0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,194 +1,194 @@
|
||||
package forge.card;
|
||||
|
||||
import forge.CardStorageReader;
|
||||
import forge.card.CardRules;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class CardReaderExperiments {
|
||||
|
||||
//utility functions to parse all cards and perform certain actions on each card
|
||||
public static void parseAllCards(String[] args) {
|
||||
if (args.length < 2) { return; }
|
||||
|
||||
int totalParsedCount = 0;
|
||||
final List<List<String>> output = new ArrayList<List<String>>();
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
output.add(new ArrayList<String>());
|
||||
}
|
||||
|
||||
final List<File> allFiles = CardStorageReader.collectCardFiles(new ArrayList<File>(), new File(ForgeConstants.CARD_DATA_DIR));
|
||||
Charset charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME);
|
||||
final CardRules.Reader rulesReader = new CardRules.Reader();
|
||||
for (File file : allFiles) {
|
||||
rulesReader.reset();
|
||||
|
||||
InputStreamReader isr;
|
||||
try {
|
||||
isr = new InputStreamReader(new FileInputStream(file), charset);
|
||||
List<String> lines = FileUtil.readAllLines(isr, true);
|
||||
CardRules rules = rulesReader.readCard(lines);
|
||||
|
||||
System.out.println();
|
||||
System.out.print(rules.getName()); //print each card here in case it gets stuck in utility
|
||||
|
||||
totalParsedCount++;
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
switch (args[i]) {
|
||||
case "updateAbilityManaSymbols":
|
||||
updateAbilityManaSymbols(rules, lines, file, output.get(i - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.print("Total cards: " + totalParsedCount);
|
||||
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
List<String> singleOutput = output.get(i - 1);
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println(args[i] + ":");
|
||||
System.out.println();
|
||||
for (String line : singleOutput) {
|
||||
System.out.println(line);
|
||||
}
|
||||
System.out.println();
|
||||
System.out.print("Total cards: " + singleOutput.size());
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateAbilityManaSymbols(CardRules rules, List<String> lines, File file, List<String> output) {
|
||||
boolean updated = false;
|
||||
|
||||
//ensure mana symbols appear in correct order
|
||||
String wubrg = "WUBRG";
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String newLine = lines.get(i);
|
||||
for (int c = 0; c < 5; c++) {
|
||||
char ch1 = wubrg.charAt(c);
|
||||
char ch2 = wubrg.charAt((c + 1) % 5);
|
||||
char ch3 = wubrg.charAt((c + 2) % 5);
|
||||
newLine = newLine.replaceAll("(^|\\W)(" + ch2 + "|" + ch3 + ")( ?)(/?)" + ch1 + "(\\W|$)", "$1" + ch1 + "$3$4$2$5");
|
||||
newLine = newLine.replaceAll("(^|\\W)\\{(" + ch2 + "|" + ch3 + ")\\}\\{" + ch1 + "\\}(\\W|$)", "$1\\{" + ch1 + "\\}\\{$2\\}$3");
|
||||
}
|
||||
if (!newLine.equals(lines.get(i))) {
|
||||
updated = true;
|
||||
lines.set(i, newLine);
|
||||
i--; //if something changed, repeat in case more than 2 mana symbols consecutively
|
||||
}
|
||||
}
|
||||
|
||||
//convert {2W} and {PW} to {2/W} and {P/W}, and ensure not {W/2} or {W/P}
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String newLine = lines.get(i).replaceAll("\\{([WUBRG2P])([WUBRG])\\}", "\\{$1/$2\\}")
|
||||
.replaceAll("\\{([WUBRG])/2\\}", "\\{2/$1\\}")
|
||||
.replaceAll("\\{([WUBRG])/P\\}", "\\{P/$1\\}");
|
||||
if (!newLine.equals(lines.get(i))) {
|
||||
updated = true;
|
||||
lines.set(i, newLine);
|
||||
}
|
||||
}
|
||||
|
||||
//check for oracle text appearing in ability descriptions missing "{G}" formatting
|
||||
if (updated) { //if lines updated above, ensure updated oracle text used
|
||||
rules = CardRules.fromScript(lines);
|
||||
}
|
||||
String oracleText = rules.getOracleText();
|
||||
String[] sentences = oracleText.replace(rules.getName(), "CARDNAME").split("\\.|\\\\n|\\\"|\\(|\\)");
|
||||
for (String s : sentences) {
|
||||
int idx = s.indexOf(":");
|
||||
if (idx != -1) {
|
||||
s = s.substring(idx + 1);
|
||||
}
|
||||
if (s.isEmpty()) { continue; }
|
||||
try {
|
||||
String pattern = s.replaceAll("\\{([WUBRGSXYZ]|[0-9]+)\\}", "$1[ ]\\?")
|
||||
.replaceAll("\\{([WUBRG2P])/([WUBRG])\\}", "$1$2[ ]\\?")
|
||||
.replaceAll("\\{C\\}", "Chaos");
|
||||
if (pattern.length() != s.length()) {
|
||||
pattern = "Description\\$(.*)" + pattern;
|
||||
s = "Description\\$$1" + s;
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String newLine = lines.get(i).replaceAll(pattern, s);
|
||||
if (newLine.length() != lines.get(i).length()) {
|
||||
updated = true;
|
||||
lines.set(i, newLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
output.add("<Exception (" + rules.getName() + ") " + ex.getMessage() + ">");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//convert mana costs in quoted ability descriptions
|
||||
//TODO: Uncomment when not flawed (currently doesn't work with hybrid, consecutive symbols, "Untap" in place of Q, or Pay # life/Put +1/+1 or -1/-1 costs
|
||||
/*for (int i = 0; i < lines.size(); i++) {
|
||||
String newLine = lines.get(i)
|
||||
.replaceAll("Description\\$(.*)\\\"(.*)Tap:(.*)\\\"", "Description\\$$1\\\"$2\\{T\\}:$3\\\"")
|
||||
.replaceAll("Description\\$(.*)\\\"(.*)Tap([ ,][A-Z0-9\\{].*):(.*)\\\"", "Description\\$$1\\\"$2\\{T\\}$3:$4\\\"")
|
||||
.replaceAll("Description\\$(.*)\\\"(.*)([WUBRGQSTXYZ]|[0-9]+):(.*)\\\"", "Description\\$$1\\\"$2\\{$3\\}:$4\\\"")
|
||||
.replaceAll("Description\\$(.*)\\\"(.*)([WUBRGQSTXYZ]|[0-9]+)([ ,].*):(.*)\\\"", "Description\\$$1\\\"$2\\{$3\\}$4:$5\\\"");
|
||||
if (!newLine.equals(lines.get(i))) {
|
||||
updated = true;
|
||||
lines.set(i, newLine);
|
||||
}
|
||||
}*/
|
||||
|
||||
//check for other key phrases that might be missing "{G}" formatting
|
||||
String[] phrases = new String[] {
|
||||
"Add * to your mana pool",
|
||||
"CostDesc\\$ * \\|"
|
||||
};
|
||||
for (String phrase : phrases) {
|
||||
String pattern = ".*" + phrase.replace("* ", "((([WUBRGSXYZ]|[0-9]+) )+)") + ".*";
|
||||
Pattern p = Pattern.compile(pattern);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String line = lines.get(i);
|
||||
Matcher m = p.matcher(line);
|
||||
if (m.matches()) {
|
||||
StringBuilder newLineBuilder = new StringBuilder();
|
||||
newLineBuilder.append(line.substring(0, m.start(1)));
|
||||
for (String sym : m.group(1).split(" ")) {
|
||||
newLineBuilder.append("{" + sym + "}");
|
||||
}
|
||||
newLineBuilder.append(line.substring(m.end(1) - 1)); //-1 so final space appended
|
||||
updated = true;
|
||||
lines.set(i, newLineBuilder.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
try {
|
||||
PrintWriter p = new PrintWriter(file);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
if (i < lines.size() - 1) {
|
||||
p.println(lines.get(i));
|
||||
}
|
||||
else {
|
||||
p.print(lines.get(i));
|
||||
}
|
||||
}
|
||||
p.close();
|
||||
output.add(rules.getName());
|
||||
} catch (final Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
package forge.card;
|
||||
|
||||
import forge.CardStorageReader;
|
||||
import forge.card.CardRules;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class CardReaderExperiments {
|
||||
|
||||
//utility functions to parse all cards and perform certain actions on each card
|
||||
public static void parseAllCards(String[] args) {
|
||||
if (args.length < 2) { return; }
|
||||
|
||||
int totalParsedCount = 0;
|
||||
final List<List<String>> output = new ArrayList<List<String>>();
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
output.add(new ArrayList<String>());
|
||||
}
|
||||
|
||||
final List<File> allFiles = CardStorageReader.collectCardFiles(new ArrayList<File>(), new File(ForgeConstants.CARD_DATA_DIR));
|
||||
Charset charset = Charset.forName(CardStorageReader.DEFAULT_CHARSET_NAME);
|
||||
final CardRules.Reader rulesReader = new CardRules.Reader();
|
||||
for (File file : allFiles) {
|
||||
rulesReader.reset();
|
||||
|
||||
InputStreamReader isr;
|
||||
try {
|
||||
isr = new InputStreamReader(new FileInputStream(file), charset);
|
||||
List<String> lines = FileUtil.readAllLines(isr, true);
|
||||
CardRules rules = rulesReader.readCard(lines);
|
||||
|
||||
System.out.println();
|
||||
System.out.print(rules.getName()); //print each card here in case it gets stuck in utility
|
||||
|
||||
totalParsedCount++;
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
switch (args[i]) {
|
||||
case "updateAbilityManaSymbols":
|
||||
updateAbilityManaSymbols(rules, lines, file, output.get(i - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.print("Total cards: " + totalParsedCount);
|
||||
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
List<String> singleOutput = output.get(i - 1);
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println(args[i] + ":");
|
||||
System.out.println();
|
||||
for (String line : singleOutput) {
|
||||
System.out.println(line);
|
||||
}
|
||||
System.out.println();
|
||||
System.out.print("Total cards: " + singleOutput.size());
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateAbilityManaSymbols(CardRules rules, List<String> lines, File file, List<String> output) {
|
||||
boolean updated = false;
|
||||
|
||||
//ensure mana symbols appear in correct order
|
||||
String wubrg = "WUBRG";
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String newLine = lines.get(i);
|
||||
for (int c = 0; c < 5; c++) {
|
||||
char ch1 = wubrg.charAt(c);
|
||||
char ch2 = wubrg.charAt((c + 1) % 5);
|
||||
char ch3 = wubrg.charAt((c + 2) % 5);
|
||||
newLine = newLine.replaceAll("(^|\\W)(" + ch2 + "|" + ch3 + ")( ?)(/?)" + ch1 + "(\\W|$)", "$1" + ch1 + "$3$4$2$5");
|
||||
newLine = newLine.replaceAll("(^|\\W)\\{(" + ch2 + "|" + ch3 + ")\\}\\{" + ch1 + "\\}(\\W|$)", "$1\\{" + ch1 + "\\}\\{$2\\}$3");
|
||||
}
|
||||
if (!newLine.equals(lines.get(i))) {
|
||||
updated = true;
|
||||
lines.set(i, newLine);
|
||||
i--; //if something changed, repeat in case more than 2 mana symbols consecutively
|
||||
}
|
||||
}
|
||||
|
||||
//convert {2W} and {PW} to {2/W} and {P/W}, and ensure not {W/2} or {W/P}
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String newLine = lines.get(i).replaceAll("\\{([WUBRG2P])([WUBRG])\\}", "\\{$1/$2\\}")
|
||||
.replaceAll("\\{([WUBRG])/2\\}", "\\{2/$1\\}")
|
||||
.replaceAll("\\{([WUBRG])/P\\}", "\\{P/$1\\}");
|
||||
if (!newLine.equals(lines.get(i))) {
|
||||
updated = true;
|
||||
lines.set(i, newLine);
|
||||
}
|
||||
}
|
||||
|
||||
//check for oracle text appearing in ability descriptions missing "{G}" formatting
|
||||
if (updated) { //if lines updated above, ensure updated oracle text used
|
||||
rules = CardRules.fromScript(lines);
|
||||
}
|
||||
String oracleText = rules.getOracleText();
|
||||
String[] sentences = oracleText.replace(rules.getName(), "CARDNAME").split("\\.|\\\\n|\\\"|\\(|\\)");
|
||||
for (String s : sentences) {
|
||||
int idx = s.indexOf(":");
|
||||
if (idx != -1) {
|
||||
s = s.substring(idx + 1);
|
||||
}
|
||||
if (s.isEmpty()) { continue; }
|
||||
try {
|
||||
String pattern = s.replaceAll("\\{([WUBRGSXYZ]|[0-9]+)\\}", "$1[ ]\\?")
|
||||
.replaceAll("\\{([WUBRG2P])/([WUBRG])\\}", "$1$2[ ]\\?")
|
||||
.replaceAll("\\{C\\}", "Chaos");
|
||||
if (pattern.length() != s.length()) {
|
||||
pattern = "Description\\$(.*)" + pattern;
|
||||
s = "Description\\$$1" + s;
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String newLine = lines.get(i).replaceAll(pattern, s);
|
||||
if (newLine.length() != lines.get(i).length()) {
|
||||
updated = true;
|
||||
lines.set(i, newLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
output.add("<Exception (" + rules.getName() + ") " + ex.getMessage() + ">");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//convert mana costs in quoted ability descriptions
|
||||
//TODO: Uncomment when not flawed (currently doesn't work with hybrid, consecutive symbols, "Untap" in place of Q, or Pay # life/Put +1/+1 or -1/-1 costs
|
||||
/*for (int i = 0; i < lines.size(); i++) {
|
||||
String newLine = lines.get(i)
|
||||
.replaceAll("Description\\$(.*)\\\"(.*)Tap:(.*)\\\"", "Description\\$$1\\\"$2\\{T\\}:$3\\\"")
|
||||
.replaceAll("Description\\$(.*)\\\"(.*)Tap([ ,][A-Z0-9\\{].*):(.*)\\\"", "Description\\$$1\\\"$2\\{T\\}$3:$4\\\"")
|
||||
.replaceAll("Description\\$(.*)\\\"(.*)([WUBRGQSTXYZ]|[0-9]+):(.*)\\\"", "Description\\$$1\\\"$2\\{$3\\}:$4\\\"")
|
||||
.replaceAll("Description\\$(.*)\\\"(.*)([WUBRGQSTXYZ]|[0-9]+)([ ,].*):(.*)\\\"", "Description\\$$1\\\"$2\\{$3\\}$4:$5\\\"");
|
||||
if (!newLine.equals(lines.get(i))) {
|
||||
updated = true;
|
||||
lines.set(i, newLine);
|
||||
}
|
||||
}*/
|
||||
|
||||
//check for other key phrases that might be missing "{G}" formatting
|
||||
String[] phrases = new String[] {
|
||||
"Add * to your mana pool",
|
||||
"CostDesc\\$ * \\|"
|
||||
};
|
||||
for (String phrase : phrases) {
|
||||
String pattern = ".*" + phrase.replace("* ", "((([WUBRGSXYZ]|[0-9]+) )+)") + ".*";
|
||||
Pattern p = Pattern.compile(pattern);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String line = lines.get(i);
|
||||
Matcher m = p.matcher(line);
|
||||
if (m.matches()) {
|
||||
StringBuilder newLineBuilder = new StringBuilder();
|
||||
newLineBuilder.append(line.substring(0, m.start(1)));
|
||||
for (String sym : m.group(1).split(" ")) {
|
||||
newLineBuilder.append("{" + sym + "}");
|
||||
}
|
||||
newLineBuilder.append(line.substring(m.end(1) - 1)); //-1 so final space appended
|
||||
updated = true;
|
||||
lines.set(i, newLineBuilder.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
try {
|
||||
PrintWriter p = new PrintWriter(file);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
if (i < lines.size() - 1) {
|
||||
p.println(lines.get(i));
|
||||
}
|
||||
else {
|
||||
p.print(lines.get(i));
|
||||
}
|
||||
}
|
||||
p.close();
|
||||
output.add(rules.getName());
|
||||
} catch (final Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +1,81 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.card;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
|
||||
public final class CardScriptInfo {
|
||||
private String text;
|
||||
private final File file;
|
||||
|
||||
public CardScriptInfo(final String text0, final File file0) {
|
||||
text = text0;
|
||||
file = file0;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public boolean canEdit() {
|
||||
return file != null;
|
||||
}
|
||||
|
||||
public boolean trySetText(final String text0) {
|
||||
if (file == null) { return false; }
|
||||
|
||||
try {
|
||||
final PrintWriter p = new PrintWriter(file);
|
||||
p.print(text0);
|
||||
p.close();
|
||||
|
||||
text = text0;
|
||||
return true;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
System.err.println("Problem writing file - " + file);
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, CardScriptInfo> allScripts = new ConcurrentHashMap<>();
|
||||
public static CardScriptInfo getScriptFor(final String name) {
|
||||
CardScriptInfo script = allScripts.get(name);
|
||||
if (script == null) { //attempt to load script if not previously loaded
|
||||
final String filename = name.toLowerCase().replace(' ', '_').replace('-', '_').replace("'", "").replace(",", "") + ".txt";
|
||||
final File file = new File(ForgeConstants.CARD_DATA_DIR + filename.charAt(0) + File.separator + filename);
|
||||
if (file.exists()) {
|
||||
script = new CardScriptInfo(FileUtil.readFileToString(file), file);
|
||||
allScripts.put(name, script);
|
||||
}
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.card;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
|
||||
public final class CardScriptInfo {
|
||||
private String text;
|
||||
private final File file;
|
||||
|
||||
public CardScriptInfo(final String text0, final File file0) {
|
||||
text = text0;
|
||||
file = file0;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public boolean canEdit() {
|
||||
return file != null;
|
||||
}
|
||||
|
||||
public boolean trySetText(final String text0) {
|
||||
if (file == null) { return false; }
|
||||
|
||||
try {
|
||||
final PrintWriter p = new PrintWriter(file);
|
||||
p.print(text0);
|
||||
p.close();
|
||||
|
||||
text = text0;
|
||||
return true;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
System.err.println("Problem writing file - " + file);
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, CardScriptInfo> allScripts = new ConcurrentHashMap<>();
|
||||
public static CardScriptInfo getScriptFor(final String name) {
|
||||
CardScriptInfo script = allScripts.get(name);
|
||||
if (script == null) { //attempt to load script if not previously loaded
|
||||
final String filename = name.toLowerCase().replace(' ', '_').replace('-', '_').replace("'", "").replace(",", "") + ".txt";
|
||||
final File file = new File(ForgeConstants.CARD_DATA_DIR + filename.charAt(0) + File.separator + filename);
|
||||
if (file.exists()) {
|
||||
script = new CardScriptInfo(FileUtil.readFileToString(file), file);
|
||||
allScripts.put(name, script);
|
||||
}
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package forge.control;
|
||||
|
||||
/** How 'loudly' the message should sound */
|
||||
public enum ChatArea {
|
||||
Room,
|
||||
Match,
|
||||
Whisper, // that is private
|
||||
Server
|
||||
}
|
||||
package forge.control;
|
||||
|
||||
/** How 'loudly' the message should sound */
|
||||
public enum ChatArea {
|
||||
Room,
|
||||
Match,
|
||||
Whisper, // that is private
|
||||
Server
|
||||
}
|
||||
|
||||
@@ -1,380 +1,380 @@
|
||||
package forge.control;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.event.*;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.zone.PlayerZone;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.interfaces.IGuiGame;
|
||||
import forge.model.FModel;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
import forge.player.PlayerZoneUpdate;
|
||||
import forge.player.PlayerZoneUpdates;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.util.Lang;
|
||||
import forge.util.maps.MapOfLists;
|
||||
|
||||
public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
||||
private final PlayerControllerHuman humanController;
|
||||
private final IGuiGame matchController;
|
||||
private final Set<CardView> cardsUpdate = new HashSet<CardView>();
|
||||
private final Set<CardView> cardsRefreshDetails = new HashSet<CardView>();
|
||||
private final Set<PlayerView> livesUpdate = new HashSet<PlayerView>();
|
||||
private final Set<PlayerView> manaPoolUpdate = new HashSet<PlayerView>();
|
||||
private final PlayerZoneUpdates zonesUpdate = new PlayerZoneUpdates();
|
||||
|
||||
private boolean processEventsQueued, needPhaseUpdate, needCombatUpdate, needStackUpdate, needPlayerControlUpdate;
|
||||
private boolean gameOver, gameFinished;
|
||||
private PlayerView turnUpdate;
|
||||
|
||||
public FControlGameEventHandler(final PlayerControllerHuman humanController0) {
|
||||
humanController = humanController0;
|
||||
matchController = humanController.getGui();
|
||||
}
|
||||
|
||||
private final Runnable processEvents = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
processEventsQueued = false;
|
||||
|
||||
synchronized (cardsUpdate) {
|
||||
if (!cardsUpdate.isEmpty()) {
|
||||
matchController.updateCards(cardsUpdate);
|
||||
cardsUpdate.clear();
|
||||
}
|
||||
}
|
||||
synchronized (cardsRefreshDetails) {
|
||||
if (!cardsRefreshDetails.isEmpty()) {
|
||||
matchController.refreshCardDetails(cardsRefreshDetails);
|
||||
cardsRefreshDetails.clear();
|
||||
}
|
||||
}
|
||||
synchronized (livesUpdate) {
|
||||
if (!livesUpdate.isEmpty()) {
|
||||
matchController.updateLives(livesUpdate);
|
||||
livesUpdate.clear();
|
||||
}
|
||||
}
|
||||
synchronized (manaPoolUpdate) {
|
||||
if (!manaPoolUpdate.isEmpty()) {
|
||||
matchController.updateManaPool(manaPoolUpdate);
|
||||
manaPoolUpdate.clear();
|
||||
}
|
||||
}
|
||||
if (turnUpdate != null) {
|
||||
matchController.updateTurn(turnUpdate);
|
||||
turnUpdate = null;
|
||||
}
|
||||
if (needPhaseUpdate) {
|
||||
needPhaseUpdate = false;
|
||||
matchController.updatePhase();
|
||||
}
|
||||
if (needCombatUpdate) {
|
||||
needCombatUpdate = false;
|
||||
matchController.showCombat();
|
||||
}
|
||||
if (needStackUpdate) {
|
||||
needStackUpdate = false;
|
||||
matchController.updateStack();
|
||||
}
|
||||
if (needPlayerControlUpdate) {
|
||||
needPlayerControlUpdate = false;
|
||||
matchController.updatePlayerControl();
|
||||
}
|
||||
synchronized (zonesUpdate) {
|
||||
if (!zonesUpdate.isEmpty()) {
|
||||
// Copy to prevent concurrency issues
|
||||
matchController.updateZones(new PlayerZoneUpdates(zonesUpdate));
|
||||
zonesUpdate.clear();
|
||||
}
|
||||
}
|
||||
if (gameOver) {
|
||||
gameOver = false;
|
||||
humanController.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete
|
||||
}
|
||||
if (gameFinished) {
|
||||
gameFinished = false;
|
||||
final PlayerView localPlayer = humanController.getLocalPlayerView();
|
||||
humanController.cancelAwaitNextInput(); //ensure "Waiting for opponent..." doesn't appear behind WinLo
|
||||
matchController.showPromptMessage(localPlayer, ""); //clear prompt behind WinLose overlay
|
||||
matchController.updateButtons(localPlayer, "", "", false, false, false);
|
||||
matchController.finishGame();
|
||||
humanController.updateAchievements();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Subscribe
|
||||
public void receiveGameEvent(final GameEvent ev) {
|
||||
ev.visit(this);
|
||||
}
|
||||
|
||||
private Void processEvent() {
|
||||
if (processEventsQueued) { return null; } //avoid queuing event processing multiple times
|
||||
processEventsQueued = true;
|
||||
GuiBase.getInterface().invokeInEdtLater(processEvents);
|
||||
return null;
|
||||
}
|
||||
|
||||
private Void processCard(final Card card, final Set<CardView> list) {
|
||||
synchronized (list) {
|
||||
list.add(card.getView());
|
||||
}
|
||||
return processEvent();
|
||||
}
|
||||
private Void processCards(final Collection<Card> cards, final Set<CardView> list) {
|
||||
if (cards.isEmpty()) { return null; }
|
||||
|
||||
synchronized (list) {
|
||||
for (final Card c : cards) {
|
||||
list.add(c.getView());
|
||||
}
|
||||
}
|
||||
return processEvent();
|
||||
}
|
||||
private Void processPlayer(final Player player, final Set<PlayerView> list) {
|
||||
synchronized (list) {
|
||||
list.add(player.getView());
|
||||
}
|
||||
return processEvent();
|
||||
}
|
||||
private Void updateZone(final Zone z) {
|
||||
if (z == null) { return null; }
|
||||
|
||||
return updateZone(z.getPlayer(), z.getZoneType());
|
||||
}
|
||||
private Void updateZone(final Player p, final ZoneType z) {
|
||||
if (p == null || z == null) { return null; }
|
||||
|
||||
synchronized (zonesUpdate) {
|
||||
zonesUpdate.add(new PlayerZoneUpdate(PlayerView.get(p), z));
|
||||
}
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventTurnPhase ev) {
|
||||
needPhaseUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerPriority event) {
|
||||
needCombatUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventTurnBegan event) {
|
||||
turnUpdate = event.turnOwner.getView();
|
||||
processPlayer(event.turnOwner, livesUpdate);
|
||||
if (FModel.getPreferences().getPrefBoolean(FPref.UI_STACK_CREATURES) && event.turnOwner != null) {
|
||||
// anything except stack will get here
|
||||
updateZone(event.turnOwner, ZoneType.Battlefield);
|
||||
}
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventAnteCardsSelected ev) {
|
||||
final List<CardView> options = Lists.newArrayList();
|
||||
for (final Entry<Player, Card> kv : ev.cards.entries()) {
|
||||
//use fake card so real cards appear with proper formatting
|
||||
final CardView fakeCard = new CardView(-1, null, " -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --");
|
||||
options.add(fakeCard);
|
||||
options.add(kv.getValue().getView());
|
||||
}
|
||||
humanController.getGui().reveal("These cards were chosen to ante", options);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerControl ev) {
|
||||
if (ev.player.getGame().isGameOver()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PlayerControllerHuman newController;
|
||||
if (ev.newController instanceof PlayerControllerHuman) {
|
||||
newController = (PlayerControllerHuman) ev.newController;
|
||||
} else {
|
||||
newController = null;
|
||||
}
|
||||
matchController.setGameController(PlayerView.get(ev.player), newController);
|
||||
|
||||
needPlayerControlUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventGameOutcome ev) {
|
||||
gameOver = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventGameFinished ev) {
|
||||
gameFinished = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventSpellAbilityCast event) {
|
||||
needStackUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventSpellResolved event) {
|
||||
needStackUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventSpellRemovedFromStack event) {
|
||||
needStackUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventZone event) {
|
||||
if (event.player != null) {
|
||||
// anything except stack will get here
|
||||
updateZone(event.player, event.zoneType);
|
||||
return processEvent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardAttachment event) {
|
||||
final Game game = event.equipment.getGame();
|
||||
final PlayerZone zEq = (PlayerZone)game.getZoneOf(event.equipment);
|
||||
if (event.oldEntiy instanceof Card) {
|
||||
updateZone(game.getZoneOf((Card)event.oldEntiy));
|
||||
}
|
||||
if (event.newTarget instanceof Card) {
|
||||
updateZone(game.getZoneOf((Card)event.newTarget));
|
||||
}
|
||||
updateZone(zEq);
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardTapped event) {
|
||||
processCard(event.card, cardsUpdate);
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardPhased event) {
|
||||
processCard(event.card, cardsUpdate);
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardDamaged event) {
|
||||
processCard(event.card, cardsUpdate);
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardCounters event) {
|
||||
processCard(event.card, cardsUpdate);
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventBlockersDeclared event) {
|
||||
final Set<Card> cards = new HashSet<Card>();
|
||||
for (final MapOfLists<Card, Card> kv : event.blockers.values()) {
|
||||
for (final Collection<Card> blockers : kv.values()) {
|
||||
cards.addAll(blockers);
|
||||
}
|
||||
}
|
||||
return processCards(cards, cardsUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventAttackersDeclared event) {
|
||||
return processCards(event.attackersMap.values(), cardsUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCombatChanged event) {
|
||||
needCombatUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCombatEnded event) {
|
||||
needCombatUpdate = true;
|
||||
|
||||
// This should remove sword/shield icons from combatants by the time game moves to M2
|
||||
processCards(event.attackers, cardsUpdate);
|
||||
return processCards(event.blockers, cardsUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardChangeZone event) {
|
||||
updateZone(event.from);
|
||||
return updateZone(event.to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardStatsChanged event) {
|
||||
processCards(event.cards, cardsRefreshDetails);
|
||||
return processCards(event.cards, cardsUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerStatsChanged event) {
|
||||
final CardCollection cards = new CardCollection();
|
||||
for (final Player p : event.players) {
|
||||
cards.addAll(p.getAllCards());
|
||||
processPlayer(p, livesUpdate);
|
||||
}
|
||||
|
||||
return processCards(cards, cardsRefreshDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventShuffle event) {
|
||||
return updateZone(event.player.getZone(ZoneType.Library));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventManaPool event) {
|
||||
return processPlayer(event.player, manaPoolUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerLivesChanged event) {
|
||||
return processPlayer(event.player, livesUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerPoisoned event) {
|
||||
return processPlayer(event.receiver, livesUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerCounters event) {
|
||||
return processPlayer(event.receiver, livesUpdate);
|
||||
}
|
||||
package forge.control;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.event.*;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.zone.PlayerZone;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.interfaces.IGuiGame;
|
||||
import forge.model.FModel;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
import forge.player.PlayerZoneUpdate;
|
||||
import forge.player.PlayerZoneUpdates;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.util.Lang;
|
||||
import forge.util.maps.MapOfLists;
|
||||
|
||||
public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
||||
private final PlayerControllerHuman humanController;
|
||||
private final IGuiGame matchController;
|
||||
private final Set<CardView> cardsUpdate = new HashSet<CardView>();
|
||||
private final Set<CardView> cardsRefreshDetails = new HashSet<CardView>();
|
||||
private final Set<PlayerView> livesUpdate = new HashSet<PlayerView>();
|
||||
private final Set<PlayerView> manaPoolUpdate = new HashSet<PlayerView>();
|
||||
private final PlayerZoneUpdates zonesUpdate = new PlayerZoneUpdates();
|
||||
|
||||
private boolean processEventsQueued, needPhaseUpdate, needCombatUpdate, needStackUpdate, needPlayerControlUpdate;
|
||||
private boolean gameOver, gameFinished;
|
||||
private PlayerView turnUpdate;
|
||||
|
||||
public FControlGameEventHandler(final PlayerControllerHuman humanController0) {
|
||||
humanController = humanController0;
|
||||
matchController = humanController.getGui();
|
||||
}
|
||||
|
||||
private final Runnable processEvents = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
processEventsQueued = false;
|
||||
|
||||
synchronized (cardsUpdate) {
|
||||
if (!cardsUpdate.isEmpty()) {
|
||||
matchController.updateCards(cardsUpdate);
|
||||
cardsUpdate.clear();
|
||||
}
|
||||
}
|
||||
synchronized (cardsRefreshDetails) {
|
||||
if (!cardsRefreshDetails.isEmpty()) {
|
||||
matchController.refreshCardDetails(cardsRefreshDetails);
|
||||
cardsRefreshDetails.clear();
|
||||
}
|
||||
}
|
||||
synchronized (livesUpdate) {
|
||||
if (!livesUpdate.isEmpty()) {
|
||||
matchController.updateLives(livesUpdate);
|
||||
livesUpdate.clear();
|
||||
}
|
||||
}
|
||||
synchronized (manaPoolUpdate) {
|
||||
if (!manaPoolUpdate.isEmpty()) {
|
||||
matchController.updateManaPool(manaPoolUpdate);
|
||||
manaPoolUpdate.clear();
|
||||
}
|
||||
}
|
||||
if (turnUpdate != null) {
|
||||
matchController.updateTurn(turnUpdate);
|
||||
turnUpdate = null;
|
||||
}
|
||||
if (needPhaseUpdate) {
|
||||
needPhaseUpdate = false;
|
||||
matchController.updatePhase();
|
||||
}
|
||||
if (needCombatUpdate) {
|
||||
needCombatUpdate = false;
|
||||
matchController.showCombat();
|
||||
}
|
||||
if (needStackUpdate) {
|
||||
needStackUpdate = false;
|
||||
matchController.updateStack();
|
||||
}
|
||||
if (needPlayerControlUpdate) {
|
||||
needPlayerControlUpdate = false;
|
||||
matchController.updatePlayerControl();
|
||||
}
|
||||
synchronized (zonesUpdate) {
|
||||
if (!zonesUpdate.isEmpty()) {
|
||||
// Copy to prevent concurrency issues
|
||||
matchController.updateZones(new PlayerZoneUpdates(zonesUpdate));
|
||||
zonesUpdate.clear();
|
||||
}
|
||||
}
|
||||
if (gameOver) {
|
||||
gameOver = false;
|
||||
humanController.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete
|
||||
}
|
||||
if (gameFinished) {
|
||||
gameFinished = false;
|
||||
final PlayerView localPlayer = humanController.getLocalPlayerView();
|
||||
humanController.cancelAwaitNextInput(); //ensure "Waiting for opponent..." doesn't appear behind WinLo
|
||||
matchController.showPromptMessage(localPlayer, ""); //clear prompt behind WinLose overlay
|
||||
matchController.updateButtons(localPlayer, "", "", false, false, false);
|
||||
matchController.finishGame();
|
||||
humanController.updateAchievements();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Subscribe
|
||||
public void receiveGameEvent(final GameEvent ev) {
|
||||
ev.visit(this);
|
||||
}
|
||||
|
||||
private Void processEvent() {
|
||||
if (processEventsQueued) { return null; } //avoid queuing event processing multiple times
|
||||
processEventsQueued = true;
|
||||
GuiBase.getInterface().invokeInEdtLater(processEvents);
|
||||
return null;
|
||||
}
|
||||
|
||||
private Void processCard(final Card card, final Set<CardView> list) {
|
||||
synchronized (list) {
|
||||
list.add(card.getView());
|
||||
}
|
||||
return processEvent();
|
||||
}
|
||||
private Void processCards(final Collection<Card> cards, final Set<CardView> list) {
|
||||
if (cards.isEmpty()) { return null; }
|
||||
|
||||
synchronized (list) {
|
||||
for (final Card c : cards) {
|
||||
list.add(c.getView());
|
||||
}
|
||||
}
|
||||
return processEvent();
|
||||
}
|
||||
private Void processPlayer(final Player player, final Set<PlayerView> list) {
|
||||
synchronized (list) {
|
||||
list.add(player.getView());
|
||||
}
|
||||
return processEvent();
|
||||
}
|
||||
private Void updateZone(final Zone z) {
|
||||
if (z == null) { return null; }
|
||||
|
||||
return updateZone(z.getPlayer(), z.getZoneType());
|
||||
}
|
||||
private Void updateZone(final Player p, final ZoneType z) {
|
||||
if (p == null || z == null) { return null; }
|
||||
|
||||
synchronized (zonesUpdate) {
|
||||
zonesUpdate.add(new PlayerZoneUpdate(PlayerView.get(p), z));
|
||||
}
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventTurnPhase ev) {
|
||||
needPhaseUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerPriority event) {
|
||||
needCombatUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventTurnBegan event) {
|
||||
turnUpdate = event.turnOwner.getView();
|
||||
processPlayer(event.turnOwner, livesUpdate);
|
||||
if (FModel.getPreferences().getPrefBoolean(FPref.UI_STACK_CREATURES) && event.turnOwner != null) {
|
||||
// anything except stack will get here
|
||||
updateZone(event.turnOwner, ZoneType.Battlefield);
|
||||
}
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventAnteCardsSelected ev) {
|
||||
final List<CardView> options = Lists.newArrayList();
|
||||
for (final Entry<Player, Card> kv : ev.cards.entries()) {
|
||||
//use fake card so real cards appear with proper formatting
|
||||
final CardView fakeCard = new CardView(-1, null, " -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --");
|
||||
options.add(fakeCard);
|
||||
options.add(kv.getValue().getView());
|
||||
}
|
||||
humanController.getGui().reveal("These cards were chosen to ante", options);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerControl ev) {
|
||||
if (ev.player.getGame().isGameOver()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PlayerControllerHuman newController;
|
||||
if (ev.newController instanceof PlayerControllerHuman) {
|
||||
newController = (PlayerControllerHuman) ev.newController;
|
||||
} else {
|
||||
newController = null;
|
||||
}
|
||||
matchController.setGameController(PlayerView.get(ev.player), newController);
|
||||
|
||||
needPlayerControlUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventGameOutcome ev) {
|
||||
gameOver = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventGameFinished ev) {
|
||||
gameFinished = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventSpellAbilityCast event) {
|
||||
needStackUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventSpellResolved event) {
|
||||
needStackUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventSpellRemovedFromStack event) {
|
||||
needStackUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventZone event) {
|
||||
if (event.player != null) {
|
||||
// anything except stack will get here
|
||||
updateZone(event.player, event.zoneType);
|
||||
return processEvent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardAttachment event) {
|
||||
final Game game = event.equipment.getGame();
|
||||
final PlayerZone zEq = (PlayerZone)game.getZoneOf(event.equipment);
|
||||
if (event.oldEntiy instanceof Card) {
|
||||
updateZone(game.getZoneOf((Card)event.oldEntiy));
|
||||
}
|
||||
if (event.newTarget instanceof Card) {
|
||||
updateZone(game.getZoneOf((Card)event.newTarget));
|
||||
}
|
||||
updateZone(zEq);
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardTapped event) {
|
||||
processCard(event.card, cardsUpdate);
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardPhased event) {
|
||||
processCard(event.card, cardsUpdate);
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardDamaged event) {
|
||||
processCard(event.card, cardsUpdate);
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardCounters event) {
|
||||
processCard(event.card, cardsUpdate);
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventBlockersDeclared event) {
|
||||
final Set<Card> cards = new HashSet<Card>();
|
||||
for (final MapOfLists<Card, Card> kv : event.blockers.values()) {
|
||||
for (final Collection<Card> blockers : kv.values()) {
|
||||
cards.addAll(blockers);
|
||||
}
|
||||
}
|
||||
return processCards(cards, cardsUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventAttackersDeclared event) {
|
||||
return processCards(event.attackersMap.values(), cardsUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCombatChanged event) {
|
||||
needCombatUpdate = true;
|
||||
return processEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCombatEnded event) {
|
||||
needCombatUpdate = true;
|
||||
|
||||
// This should remove sword/shield icons from combatants by the time game moves to M2
|
||||
processCards(event.attackers, cardsUpdate);
|
||||
return processCards(event.blockers, cardsUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardChangeZone event) {
|
||||
updateZone(event.from);
|
||||
return updateZone(event.to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventCardStatsChanged event) {
|
||||
processCards(event.cards, cardsRefreshDetails);
|
||||
return processCards(event.cards, cardsUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerStatsChanged event) {
|
||||
final CardCollection cards = new CardCollection();
|
||||
for (final Player p : event.players) {
|
||||
cards.addAll(p.getAllCards());
|
||||
processPlayer(p, livesUpdate);
|
||||
}
|
||||
|
||||
return processCards(cards, cardsRefreshDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventShuffle event) {
|
||||
return updateZone(event.player.getZone(ZoneType.Library));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventManaPool event) {
|
||||
return processPlayer(event.player, manaPoolUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerLivesChanged event) {
|
||||
return processPlayer(event.player, livesUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerPoisoned event) {
|
||||
return processPlayer(event.receiver, livesUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerCounters event) {
|
||||
return processPlayer(event.receiver, livesUpdate);
|
||||
}
|
||||
}
|
||||
@@ -1,221 +1,221 @@
|
||||
package forge.control;
|
||||
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.event.GameEvent;
|
||||
import forge.game.event.GameEventBlockersDeclared;
|
||||
import forge.game.event.GameEventGameFinished;
|
||||
import forge.game.event.GameEventGameStarted;
|
||||
import forge.game.event.GameEventLandPlayed;
|
||||
import forge.game.event.GameEventPlayerPriority;
|
||||
import forge.game.event.GameEventSpellAbilityCast;
|
||||
import forge.game.event.GameEventSpellResolved;
|
||||
import forge.game.event.GameEventTurnPhase;
|
||||
import forge.game.event.IGameEventVisitor;
|
||||
import forge.match.input.InputPlaybackControl;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
|
||||
public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
|
||||
private InputPlaybackControl inputPlayback;
|
||||
private final AtomicBoolean paused = new AtomicBoolean(false);
|
||||
|
||||
private final CyclicBarrier gameThreadPauser = new CyclicBarrier(2);
|
||||
|
||||
private final PlayerControllerHuman humanController;
|
||||
public FControlGamePlayback(final PlayerControllerHuman humanController0) {
|
||||
this.humanController = humanController0;
|
||||
}
|
||||
|
||||
public final PlayerControllerHuman getController() {
|
||||
return humanController;
|
||||
}
|
||||
|
||||
public InputPlaybackControl getInput() {
|
||||
return inputPlayback;
|
||||
}
|
||||
|
||||
private Game game;
|
||||
|
||||
public Game getGame() {
|
||||
return game;
|
||||
}
|
||||
|
||||
public void setGame(final Game game0) {
|
||||
game = game0;
|
||||
inputPlayback = new InputPlaybackControl(game, this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void receiveGameEvent(final GameEvent ev) {
|
||||
ev.visit(this);
|
||||
}
|
||||
|
||||
public static final int phasesDelay = 200;
|
||||
public static final int combatDelay = 400;
|
||||
public static final int castDelay = 400;
|
||||
public static final int resolveDelay = 400;
|
||||
|
||||
private boolean fasterPlayback = false;
|
||||
|
||||
private void pauseForEvent(final int delay) {
|
||||
try {
|
||||
Thread.sleep(fasterPlayback ? delay / 10 : delay);
|
||||
} catch (final InterruptedException e) {
|
||||
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventBlockersDeclared event) {
|
||||
pauseForEvent(combatDelay);
|
||||
return super.visit(event);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventTurnPhase)
|
||||
*/
|
||||
@Override
|
||||
public Void visit(final GameEventTurnPhase ev) {
|
||||
try {
|
||||
final boolean isUiToStop = !humanController.getGui().isUiSetToSkipPhase(ev.playerTurn.getView(), ev.phase);
|
||||
|
||||
switch(ev.phase) {
|
||||
case COMBAT_END:
|
||||
case COMBAT_DECLARE_ATTACKERS:
|
||||
case COMBAT_DECLARE_BLOCKERS:
|
||||
if (getGame().getPhaseHandler().inCombat()) {
|
||||
pauseForEvent(combatDelay);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (isUiToStop) {
|
||||
pauseForEvent(phasesDelay);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventDuelFinished)
|
||||
*/
|
||||
@Override
|
||||
public Void visit(final GameEventGameFinished event) {
|
||||
humanController.getInputQueue().removeInput(inputPlayback);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventGameStarted event) {
|
||||
humanController.getInputQueue().setInput(inputPlayback);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventLandPlayed event) {
|
||||
pauseForEvent(resolveDelay);
|
||||
return super.visit(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventSpellResolved event) {
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
humanController.getGui().setCard(CardView.get(event.spell.getHostCard()));
|
||||
}
|
||||
});
|
||||
pauseForEvent(resolveDelay);
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventSpellAbilityCast)
|
||||
*/
|
||||
@Override
|
||||
public Void visit(final GameEventSpellAbilityCast event) {
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
humanController.getGui().setCard(CardView.get(event.sa.getHostCard()));
|
||||
}
|
||||
});
|
||||
pauseForEvent(castDelay);
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventPlayerPriority)
|
||||
*/
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerPriority event) {
|
||||
inputPlayback.updateTurnMessage();
|
||||
if (paused.get()) {
|
||||
try {
|
||||
gameThreadPauser.await();
|
||||
gameThreadPauser.reset();
|
||||
}
|
||||
catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (final BrokenBarrierException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void onGameStopRequested() {
|
||||
paused.set(false);
|
||||
if (gameThreadPauser.getNumberWaiting() != 0) {
|
||||
releaseGameThread();
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseGameThread() {
|
||||
// just need to run another thread through the barrier... not edt preferrably :)
|
||||
getGame().getAction().invoke(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
gameThreadPauser.await();
|
||||
} catch (final InterruptedException e) {
|
||||
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
||||
e.printStackTrace();
|
||||
} catch (final BrokenBarrierException e) {
|
||||
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
paused.set(false);
|
||||
releaseGameThread();
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
paused.set(true);
|
||||
}
|
||||
|
||||
public void singleStep() {
|
||||
releaseGameThread();
|
||||
}
|
||||
|
||||
public void setSpeed(final boolean isFast) {
|
||||
fasterPlayback = isFast;
|
||||
}
|
||||
package forge.control;
|
||||
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.event.GameEvent;
|
||||
import forge.game.event.GameEventBlockersDeclared;
|
||||
import forge.game.event.GameEventGameFinished;
|
||||
import forge.game.event.GameEventGameStarted;
|
||||
import forge.game.event.GameEventLandPlayed;
|
||||
import forge.game.event.GameEventPlayerPriority;
|
||||
import forge.game.event.GameEventSpellAbilityCast;
|
||||
import forge.game.event.GameEventSpellResolved;
|
||||
import forge.game.event.GameEventTurnPhase;
|
||||
import forge.game.event.IGameEventVisitor;
|
||||
import forge.match.input.InputPlaybackControl;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
|
||||
public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
|
||||
private InputPlaybackControl inputPlayback;
|
||||
private final AtomicBoolean paused = new AtomicBoolean(false);
|
||||
|
||||
private final CyclicBarrier gameThreadPauser = new CyclicBarrier(2);
|
||||
|
||||
private final PlayerControllerHuman humanController;
|
||||
public FControlGamePlayback(final PlayerControllerHuman humanController0) {
|
||||
this.humanController = humanController0;
|
||||
}
|
||||
|
||||
public final PlayerControllerHuman getController() {
|
||||
return humanController;
|
||||
}
|
||||
|
||||
public InputPlaybackControl getInput() {
|
||||
return inputPlayback;
|
||||
}
|
||||
|
||||
private Game game;
|
||||
|
||||
public Game getGame() {
|
||||
return game;
|
||||
}
|
||||
|
||||
public void setGame(final Game game0) {
|
||||
game = game0;
|
||||
inputPlayback = new InputPlaybackControl(game, this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void receiveGameEvent(final GameEvent ev) {
|
||||
ev.visit(this);
|
||||
}
|
||||
|
||||
public static final int phasesDelay = 200;
|
||||
public static final int combatDelay = 400;
|
||||
public static final int castDelay = 400;
|
||||
public static final int resolveDelay = 400;
|
||||
|
||||
private boolean fasterPlayback = false;
|
||||
|
||||
private void pauseForEvent(final int delay) {
|
||||
try {
|
||||
Thread.sleep(fasterPlayback ? delay / 10 : delay);
|
||||
} catch (final InterruptedException e) {
|
||||
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventBlockersDeclared event) {
|
||||
pauseForEvent(combatDelay);
|
||||
return super.visit(event);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventTurnPhase)
|
||||
*/
|
||||
@Override
|
||||
public Void visit(final GameEventTurnPhase ev) {
|
||||
try {
|
||||
final boolean isUiToStop = !humanController.getGui().isUiSetToSkipPhase(ev.playerTurn.getView(), ev.phase);
|
||||
|
||||
switch(ev.phase) {
|
||||
case COMBAT_END:
|
||||
case COMBAT_DECLARE_ATTACKERS:
|
||||
case COMBAT_DECLARE_BLOCKERS:
|
||||
if (getGame().getPhaseHandler().inCombat()) {
|
||||
pauseForEvent(combatDelay);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (isUiToStop) {
|
||||
pauseForEvent(phasesDelay);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventDuelFinished)
|
||||
*/
|
||||
@Override
|
||||
public Void visit(final GameEventGameFinished event) {
|
||||
humanController.getInputQueue().removeInput(inputPlayback);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventGameStarted event) {
|
||||
humanController.getInputQueue().setInput(inputPlayback);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventLandPlayed event) {
|
||||
pauseForEvent(resolveDelay);
|
||||
return super.visit(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(final GameEventSpellResolved event) {
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
humanController.getGui().setCard(CardView.get(event.spell.getHostCard()));
|
||||
}
|
||||
});
|
||||
pauseForEvent(resolveDelay);
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventSpellAbilityCast)
|
||||
*/
|
||||
@Override
|
||||
public Void visit(final GameEventSpellAbilityCast event) {
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
humanController.getGui().setCard(CardView.get(event.sa.getHostCard()));
|
||||
}
|
||||
});
|
||||
pauseForEvent(castDelay);
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventPlayerPriority)
|
||||
*/
|
||||
@Override
|
||||
public Void visit(final GameEventPlayerPriority event) {
|
||||
inputPlayback.updateTurnMessage();
|
||||
if (paused.get()) {
|
||||
try {
|
||||
gameThreadPauser.await();
|
||||
gameThreadPauser.reset();
|
||||
}
|
||||
catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (final BrokenBarrierException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void onGameStopRequested() {
|
||||
paused.set(false);
|
||||
if (gameThreadPauser.getNumberWaiting() != 0) {
|
||||
releaseGameThread();
|
||||
}
|
||||
}
|
||||
|
||||
private void releaseGameThread() {
|
||||
// just need to run another thread through the barrier... not edt preferrably :)
|
||||
getGame().getAction().invoke(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
gameThreadPauser.await();
|
||||
} catch (final InterruptedException e) {
|
||||
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
||||
e.printStackTrace();
|
||||
} catch (final BrokenBarrierException e) {
|
||||
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
paused.set(false);
|
||||
releaseGameThread();
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
paused.set(true);
|
||||
}
|
||||
|
||||
public void singleStep() {
|
||||
releaseGameThread();
|
||||
}
|
||||
|
||||
public void setSpeed(final boolean isFast) {
|
||||
fasterPlayback = isFast;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
/** Controller (as in model-view-controller) for Forge. */
|
||||
package forge.control;
|
||||
|
||||
/** Controller (as in model-view-controller) for Forge. */
|
||||
package forge.control;
|
||||
|
||||
|
||||
@@ -1,144 +1,144 @@
|
||||
package forge.deck;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.deck.io.CardThemedMatrixIO;
|
||||
import forge.deck.io.DeckStorage;
|
||||
import forge.game.GameFormat;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.storage.IStorage;
|
||||
import forge.util.storage.StorageImmediatelySerialized;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by maustin on 09/05/2017.
|
||||
*/
|
||||
public final class CardRelationMatrixGenerator {
|
||||
|
||||
public static HashMap<GameFormat,HashMap<String,List<Map.Entry<PaperCard,Integer>>>> cardPools = new HashMap<>();
|
||||
|
||||
|
||||
public static void initialize(){
|
||||
HashMap<String,List<Map.Entry<PaperCard,Integer>>> standardMap = CardThemedMatrixIO.loadMatrix(FModel.getFormats().getStandard());
|
||||
HashMap<String,List<Map.Entry<PaperCard,Integer>>> modernMap = CardThemedMatrixIO.loadMatrix(FModel.getFormats().getModern());
|
||||
if(standardMap==null || modernMap==null){
|
||||
reInitialize();
|
||||
return;
|
||||
}
|
||||
cardPools.put(FModel.getFormats().getStandard(),standardMap);
|
||||
cardPools.put(FModel.getFormats().getModern(),modernMap);
|
||||
}
|
||||
|
||||
public static void reInitialize(){
|
||||
cardPools.put(FModel.getFormats().getStandard(),initializeFormat(FModel.getFormats().getStandard()));
|
||||
cardPools.put(FModel.getFormats().getModern(),initializeFormat(FModel.getFormats().getModern()));
|
||||
for(GameFormat format:cardPools.keySet()){
|
||||
HashMap<String,List<Map.Entry<PaperCard,Integer>>> map = cardPools.get(format);
|
||||
CardThemedMatrixIO.saveMatrix(format,map);
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<String,List<Map.Entry<PaperCard,Integer>>> initializeFormat(GameFormat format){
|
||||
|
||||
IStorage<Deck> decks = new StorageImmediatelySerialized<Deck>("Generator", new DeckStorage(new File(ForgeConstants.DECK_GEN_DIR+ForgeConstants.PATH_SEPARATOR+format.getName()),
|
||||
ForgeConstants.DECK_GEN_DIR, false),
|
||||
true);
|
||||
|
||||
final Iterable<PaperCard> cards = Iterables.filter(format.getAllCards()
|
||||
, Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES), PaperCard.FN_GET_RULES));
|
||||
List<PaperCard> cardList = Lists.newArrayList(cards);
|
||||
cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes"));
|
||||
Map<String, Integer> cardIntegerMap = new HashMap<>();
|
||||
Map<Integer, PaperCard> integerCardMap = new HashMap<>();
|
||||
for (int i=0; i<cardList.size(); ++i){
|
||||
cardIntegerMap.put(cardList.get(i).getName(),i);
|
||||
integerCardMap.put(i,cardList.get(i));
|
||||
}
|
||||
|
||||
int[][] matrix = new int[cardList.size()][cardList.size()];
|
||||
|
||||
for (PaperCard card:cardList){
|
||||
for (Deck deck:decks){
|
||||
if (deck.getMain().contains(card)){
|
||||
for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(),
|
||||
Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES), PaperCard.FN_GET_RULES))){
|
||||
if (!pairCard.getName().equals(card.getName())){
|
||||
try {
|
||||
|
||||
int old = matrix[cardIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())];
|
||||
matrix[cardIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())] = old + 1;
|
||||
}catch (NullPointerException ne){
|
||||
//Todo: Not sure what was failing here
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashMap<String,List<Map.Entry<PaperCard,Integer>>> cardPools = new HashMap<>();
|
||||
for (PaperCard card:cardList){
|
||||
int col=cardIntegerMap.get(card.getName());
|
||||
int[] distances = matrix[col];
|
||||
int max = (Integer) Collections.max(Arrays.asList(ArrayUtils.toObject(distances)));
|
||||
if (max>0) {
|
||||
ArrayIndexComparator comparator = new ArrayIndexComparator(ArrayUtils.toObject(distances));
|
||||
Integer[] indices = comparator.createIndexArray();
|
||||
Arrays.sort(indices, comparator);
|
||||
List<Map.Entry<PaperCard,Integer>> deckPool=new ArrayList<>();
|
||||
int k=0;
|
||||
boolean excludeThisCard=false;//if there are too few cards with at least one connection
|
||||
for (int j=0;j<20;++k){
|
||||
if(distances[indices[cardList.size()-1-k]]==0){
|
||||
excludeThisCard = true;
|
||||
break;
|
||||
}
|
||||
PaperCard cardToAdd=integerCardMap.get(indices[cardList.size()-1-k]);
|
||||
if(!cardToAdd.getRules().getMainPart().getType().isLand()){//need x non-land cards
|
||||
++j;
|
||||
}
|
||||
deckPool.add(new AbstractMap.SimpleEntry<PaperCard, Integer>(cardToAdd,distances[indices[cardList.size()-1-k]]));
|
||||
};
|
||||
if(excludeThisCard){
|
||||
continue;
|
||||
}
|
||||
cardPools.put(card.getName(),deckPool);
|
||||
}
|
||||
}
|
||||
return cardPools;
|
||||
}
|
||||
|
||||
public static class ArrayIndexComparator implements Comparator<Integer>
|
||||
{
|
||||
private final Integer[] array;
|
||||
|
||||
public ArrayIndexComparator(Integer[] array)
|
||||
{
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public Integer[] createIndexArray()
|
||||
{
|
||||
Integer[] indexes = new Integer[array.length];
|
||||
for (int i = 0; i < array.length; i++)
|
||||
{
|
||||
indexes[i] = i; // Autoboxing
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(Integer index1, Integer index2)
|
||||
{
|
||||
// Autounbox from Integer to int to use as array indexes
|
||||
return array[index1].compareTo(array[index2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
package forge.deck;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.deck.io.CardThemedMatrixIO;
|
||||
import forge.deck.io.DeckStorage;
|
||||
import forge.game.GameFormat;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.storage.IStorage;
|
||||
import forge.util.storage.StorageImmediatelySerialized;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by maustin on 09/05/2017.
|
||||
*/
|
||||
public final class CardRelationMatrixGenerator {
|
||||
|
||||
public static HashMap<GameFormat,HashMap<String,List<Map.Entry<PaperCard,Integer>>>> cardPools = new HashMap<>();
|
||||
|
||||
|
||||
public static void initialize(){
|
||||
HashMap<String,List<Map.Entry<PaperCard,Integer>>> standardMap = CardThemedMatrixIO.loadMatrix(FModel.getFormats().getStandard());
|
||||
HashMap<String,List<Map.Entry<PaperCard,Integer>>> modernMap = CardThemedMatrixIO.loadMatrix(FModel.getFormats().getModern());
|
||||
if(standardMap==null || modernMap==null){
|
||||
reInitialize();
|
||||
return;
|
||||
}
|
||||
cardPools.put(FModel.getFormats().getStandard(),standardMap);
|
||||
cardPools.put(FModel.getFormats().getModern(),modernMap);
|
||||
}
|
||||
|
||||
public static void reInitialize(){
|
||||
cardPools.put(FModel.getFormats().getStandard(),initializeFormat(FModel.getFormats().getStandard()));
|
||||
cardPools.put(FModel.getFormats().getModern(),initializeFormat(FModel.getFormats().getModern()));
|
||||
for(GameFormat format:cardPools.keySet()){
|
||||
HashMap<String,List<Map.Entry<PaperCard,Integer>>> map = cardPools.get(format);
|
||||
CardThemedMatrixIO.saveMatrix(format,map);
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<String,List<Map.Entry<PaperCard,Integer>>> initializeFormat(GameFormat format){
|
||||
|
||||
IStorage<Deck> decks = new StorageImmediatelySerialized<Deck>("Generator", new DeckStorage(new File(ForgeConstants.DECK_GEN_DIR+ForgeConstants.PATH_SEPARATOR+format.getName()),
|
||||
ForgeConstants.DECK_GEN_DIR, false),
|
||||
true);
|
||||
|
||||
final Iterable<PaperCard> cards = Iterables.filter(format.getAllCards()
|
||||
, Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES), PaperCard.FN_GET_RULES));
|
||||
List<PaperCard> cardList = Lists.newArrayList(cards);
|
||||
cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes"));
|
||||
Map<String, Integer> cardIntegerMap = new HashMap<>();
|
||||
Map<Integer, PaperCard> integerCardMap = new HashMap<>();
|
||||
for (int i=0; i<cardList.size(); ++i){
|
||||
cardIntegerMap.put(cardList.get(i).getName(),i);
|
||||
integerCardMap.put(i,cardList.get(i));
|
||||
}
|
||||
|
||||
int[][] matrix = new int[cardList.size()][cardList.size()];
|
||||
|
||||
for (PaperCard card:cardList){
|
||||
for (Deck deck:decks){
|
||||
if (deck.getMain().contains(card)){
|
||||
for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(),
|
||||
Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES), PaperCard.FN_GET_RULES))){
|
||||
if (!pairCard.getName().equals(card.getName())){
|
||||
try {
|
||||
|
||||
int old = matrix[cardIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())];
|
||||
matrix[cardIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())] = old + 1;
|
||||
}catch (NullPointerException ne){
|
||||
//Todo: Not sure what was failing here
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashMap<String,List<Map.Entry<PaperCard,Integer>>> cardPools = new HashMap<>();
|
||||
for (PaperCard card:cardList){
|
||||
int col=cardIntegerMap.get(card.getName());
|
||||
int[] distances = matrix[col];
|
||||
int max = (Integer) Collections.max(Arrays.asList(ArrayUtils.toObject(distances)));
|
||||
if (max>0) {
|
||||
ArrayIndexComparator comparator = new ArrayIndexComparator(ArrayUtils.toObject(distances));
|
||||
Integer[] indices = comparator.createIndexArray();
|
||||
Arrays.sort(indices, comparator);
|
||||
List<Map.Entry<PaperCard,Integer>> deckPool=new ArrayList<>();
|
||||
int k=0;
|
||||
boolean excludeThisCard=false;//if there are too few cards with at least one connection
|
||||
for (int j=0;j<20;++k){
|
||||
if(distances[indices[cardList.size()-1-k]]==0){
|
||||
excludeThisCard = true;
|
||||
break;
|
||||
}
|
||||
PaperCard cardToAdd=integerCardMap.get(indices[cardList.size()-1-k]);
|
||||
if(!cardToAdd.getRules().getMainPart().getType().isLand()){//need x non-land cards
|
||||
++j;
|
||||
}
|
||||
deckPool.add(new AbstractMap.SimpleEntry<PaperCard, Integer>(cardToAdd,distances[indices[cardList.size()-1-k]]));
|
||||
};
|
||||
if(excludeThisCard){
|
||||
continue;
|
||||
}
|
||||
cardPools.put(card.getName(),deckPool);
|
||||
}
|
||||
}
|
||||
return cardPools;
|
||||
}
|
||||
|
||||
public static class ArrayIndexComparator implements Comparator<Integer>
|
||||
{
|
||||
private final Integer[] array;
|
||||
|
||||
public ArrayIndexComparator(Integer[] array)
|
||||
{
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public Integer[] createIndexArray()
|
||||
{
|
||||
Integer[] indexes = new Integer[array.length];
|
||||
for (int i = 0; i < array.length; i++)
|
||||
{
|
||||
indexes[i] = i; // Autoboxing
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(Integer index1, Integer index2)
|
||||
{
|
||||
// Autounbox from Integer to int to use as array indexes
|
||||
return array[index1].compareTo(array[index2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
package forge.deck;
|
||||
|
||||
import forge.card.CardEdition;
|
||||
import forge.game.GameFormat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by maustin on 09/05/2017.
|
||||
*/
|
||||
public class CardThemedDeckGenerator extends DeckProxy implements Comparable<CardThemedDeckGenerator> {
|
||||
public static List<DeckProxy> getMatrixDecks(GameFormat format, boolean isForAi){
|
||||
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
|
||||
for(String card: CardRelationMatrixGenerator.cardPools.get(format).keySet()) {
|
||||
decks.add(new CardThemedDeckGenerator(card, format, isForAi));
|
||||
}
|
||||
return decks;
|
||||
}
|
||||
private final String name;
|
||||
private final int index;
|
||||
private final GameFormat format;
|
||||
private final boolean isForAi;
|
||||
|
||||
|
||||
private CardThemedDeckGenerator(String cardName, GameFormat format0, boolean isForAi0) {
|
||||
super();
|
||||
name = cardName;
|
||||
index = 0;
|
||||
format=format0;
|
||||
isForAi=isForAi0;
|
||||
}
|
||||
|
||||
public CardEdition getEdition() {
|
||||
return CardEdition.UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final CardThemedDeckGenerator d) {
|
||||
return name.compareTo(d.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deck getDeck() {
|
||||
|
||||
return DeckgenUtil.buildCardGenDeck(name,format,isForAi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGeneratedDeck() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
package forge.deck;
|
||||
|
||||
import forge.card.CardEdition;
|
||||
import forge.game.GameFormat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by maustin on 09/05/2017.
|
||||
*/
|
||||
public class CardThemedDeckGenerator extends DeckProxy implements Comparable<CardThemedDeckGenerator> {
|
||||
public static List<DeckProxy> getMatrixDecks(GameFormat format, boolean isForAi){
|
||||
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
|
||||
for(String card: CardRelationMatrixGenerator.cardPools.get(format).keySet()) {
|
||||
decks.add(new CardThemedDeckGenerator(card, format, isForAi));
|
||||
}
|
||||
return decks;
|
||||
}
|
||||
private final String name;
|
||||
private final int index;
|
||||
private final GameFormat format;
|
||||
private final boolean isForAi;
|
||||
|
||||
|
||||
private CardThemedDeckGenerator(String cardName, GameFormat format0, boolean isForAi0) {
|
||||
super();
|
||||
name = cardName;
|
||||
index = 0;
|
||||
format=format0;
|
||||
isForAi=isForAi0;
|
||||
}
|
||||
|
||||
public CardEdition getEdition() {
|
||||
return CardEdition.UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final CardThemedDeckGenerator d) {
|
||||
return name.compareTo(d.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deck getDeck() {
|
||||
|
||||
return DeckgenUtil.buildCardGenDeck(name,format,isForAi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGeneratedDeck() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
package forge.deck;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.card.CardEdition;
|
||||
import forge.item.PaperCard;
|
||||
import forge.itemmanager.IItemManager;
|
||||
|
||||
public class ColorDeckGenerator extends DeckProxy implements Comparable<ColorDeckGenerator> {
|
||||
public static List<DeckProxy> getColorDecks(final IItemManager<DeckProxy> lstDecks0, final Predicate<PaperCard> formatFilter0, final boolean isAi0) {
|
||||
final String[] colors = new String[] { "Random 1", "Random 2", "Random 3",
|
||||
"White", "Blue", "Black", "Red", "Green" };
|
||||
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
decks.add(new ColorDeckGenerator(colors[i], i, lstDecks0, formatFilter0, isAi0));
|
||||
}
|
||||
return decks;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final int index;
|
||||
private final IItemManager<DeckProxy> lstDecks;
|
||||
private final boolean isAi;
|
||||
private final Predicate<PaperCard> formatFilter;
|
||||
|
||||
private ColorDeckGenerator(final String name0, final int index0, final IItemManager<DeckProxy> lstDecks0,final Predicate<PaperCard> formatFilter0, final boolean isAi0) {
|
||||
super();
|
||||
name = name0;
|
||||
index = index0;
|
||||
lstDecks = lstDecks0;
|
||||
isAi = isAi0;
|
||||
formatFilter = formatFilter0;
|
||||
}
|
||||
|
||||
public CardEdition getEdition() {
|
||||
return CardEdition.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final ColorDeckGenerator d) {
|
||||
return Integer.compare(index, d.index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deck getDeck() {
|
||||
final List<String> selection = new ArrayList<String>();
|
||||
for (final DeckProxy deck : lstDecks.getSelectedItems()) {
|
||||
selection.add(deck.getName());
|
||||
}
|
||||
if (DeckgenUtil.colorCheck(selection)) {
|
||||
return DeckgenUtil.buildColorDeck(selection, formatFilter, isAi);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGeneratedDeck() {
|
||||
return true;
|
||||
}
|
||||
package forge.deck;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.card.CardEdition;
|
||||
import forge.item.PaperCard;
|
||||
import forge.itemmanager.IItemManager;
|
||||
|
||||
public class ColorDeckGenerator extends DeckProxy implements Comparable<ColorDeckGenerator> {
|
||||
public static List<DeckProxy> getColorDecks(final IItemManager<DeckProxy> lstDecks0, final Predicate<PaperCard> formatFilter0, final boolean isAi0) {
|
||||
final String[] colors = new String[] { "Random 1", "Random 2", "Random 3",
|
||||
"White", "Blue", "Black", "Red", "Green" };
|
||||
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
decks.add(new ColorDeckGenerator(colors[i], i, lstDecks0, formatFilter0, isAi0));
|
||||
}
|
||||
return decks;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final int index;
|
||||
private final IItemManager<DeckProxy> lstDecks;
|
||||
private final boolean isAi;
|
||||
private final Predicate<PaperCard> formatFilter;
|
||||
|
||||
private ColorDeckGenerator(final String name0, final int index0, final IItemManager<DeckProxy> lstDecks0,final Predicate<PaperCard> formatFilter0, final boolean isAi0) {
|
||||
super();
|
||||
name = name0;
|
||||
index = index0;
|
||||
lstDecks = lstDecks0;
|
||||
isAi = isAi0;
|
||||
formatFilter = formatFilter0;
|
||||
}
|
||||
|
||||
public CardEdition getEdition() {
|
||||
return CardEdition.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final ColorDeckGenerator d) {
|
||||
return Integer.compare(index, d.index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deck getDeck() {
|
||||
final List<String> selection = new ArrayList<String>();
|
||||
for (final DeckProxy deck : lstDecks.getSelectedItems()) {
|
||||
selection.add(deck.getName());
|
||||
}
|
||||
if (DeckgenUtil.colorCheck(selection)) {
|
||||
return DeckgenUtil.buildColorDeck(selection, formatFilter, isAi);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGeneratedDeck() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,245 +1,245 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.deck;
|
||||
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.generation.DeckGeneratorBase;
|
||||
import forge.deck.generation.IDeckGenPool;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* ThemeDeckGenerator class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: ThemeDeckGenerator.java 25022 2014-03-02 14:19:50Z teferi $
|
||||
*/
|
||||
public class DeckGeneratorTheme extends DeckGeneratorBase {
|
||||
@Override
|
||||
protected final float getLandPercentage() {
|
||||
return 0.44f;
|
||||
}
|
||||
@Override
|
||||
protected final float getCreaturePercentage() {
|
||||
return 0.33f;
|
||||
}
|
||||
@Override
|
||||
protected final float getSpellPercentage() {
|
||||
return 0.23f;
|
||||
}
|
||||
|
||||
private int basicLandPercentage = 0;
|
||||
private String basicLandSet = null;
|
||||
private boolean testing = false;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for ThemeDeckGenerator.
|
||||
* </p>
|
||||
*/
|
||||
public DeckGeneratorTheme(IDeckGenPool pool0) {
|
||||
super(pool0, DeckFormat.Constructed);
|
||||
setBasicLandPool(null);
|
||||
this.maxDuplicates = 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getThemeNames.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link java.util.ArrayList} object.
|
||||
*/
|
||||
public static final List<String> getThemeNames() {
|
||||
final List<String> ltNames = new ArrayList<String>();
|
||||
|
||||
final File file = new File(ForgeConstants.THEMES_DIR);
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("ThemeDeckGenerator : getThemeNames error -- file not found -- filename is "
|
||||
+ file.getAbsolutePath());
|
||||
}
|
||||
|
||||
if (!file.isDirectory()) {
|
||||
throw new RuntimeException("ThemeDeckGenerator : getThemeNames error -- not a directory -- "
|
||||
+ file.getAbsolutePath());
|
||||
}
|
||||
|
||||
final String[] fileList = file.list();
|
||||
for (final String element : fileList) {
|
||||
if (element.endsWith(".thm")) {
|
||||
ltNames.add(element.substring(0, element.indexOf(".thm")));
|
||||
}
|
||||
}
|
||||
|
||||
return ltNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getThemeDeck.
|
||||
* </p>
|
||||
*
|
||||
* @param themeName
|
||||
* a {@link java.lang.String} object.
|
||||
* @param size
|
||||
* a int.
|
||||
* @return a {@link forge.CardList} object.
|
||||
*/
|
||||
public final CardPool getThemeDeck(final String themeName, final int size, final StringBuilder errorBuilder) {
|
||||
String s = "";
|
||||
String[] ss;
|
||||
|
||||
// read theme file
|
||||
final String tFileName = ForgeConstants.THEMES_DIR + "/" + themeName + ".thm";
|
||||
List<String> lines = FileUtil.readFile(tFileName);
|
||||
|
||||
final List<Grp> groups = readGroups(lines);
|
||||
|
||||
// begin assigning cards to the deck
|
||||
final Random r = MyRandom.getRandom();
|
||||
|
||||
for (int i = 0; i < groups.size(); i++) {
|
||||
final Grp g = groups.get(i);
|
||||
final float p = (float) (g.percentage * .01);
|
||||
final int grpCnt = (int) (p * size);
|
||||
final int cnSize = g.cardnames.size();
|
||||
errorBuilder.append("Group" + i + ":" + grpCnt + "\n");
|
||||
|
||||
for (int j = 0; j < grpCnt; j++) {
|
||||
s = g.cardnames.get(r.nextInt(cnSize));
|
||||
ss = s.split("\\|");
|
||||
|
||||
int lc = 0;
|
||||
while ((cardCounts.get(ss[0]) >= g.maxCnt) || (lc > 999)) {
|
||||
// looping
|
||||
// forever
|
||||
s = g.cardnames.get(r.nextInt(cnSize));
|
||||
ss = s.split("\\|");
|
||||
lc++;
|
||||
}
|
||||
if (lc > 999) {
|
||||
throw new RuntimeException("ThemeDeckGenerator : getThemeDeck -- looped too much -- filename is "
|
||||
+ tFileName);
|
||||
}
|
||||
|
||||
final int n = cardCounts.get(ss[0]);
|
||||
if (ss.length == 1) {
|
||||
tDeck.add(pool.getCard(ss[0]));
|
||||
}
|
||||
else {
|
||||
tDeck.add(pool.getCard(ss[0],ss[1]));
|
||||
}
|
||||
cardCounts.put(ss[0], n + 1);
|
||||
errorBuilder.append(s + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
int numBLands;
|
||||
if (basicLandPercentage > 0) { // if theme explicitly defines this
|
||||
numBLands = (int) (size * basicLandPercentage / 100f);
|
||||
}
|
||||
else { // otherwise, just fill in the rest of the deck with basic lands
|
||||
numBLands = size - tDeck.countAll();
|
||||
}
|
||||
|
||||
errorBuilder.append("numBLands:" + numBLands + "\n");
|
||||
|
||||
addBasicLand(numBLands,basicLandSet);
|
||||
|
||||
errorBuilder.append("DeckSize:" + tDeck.countAll() + "\n");
|
||||
|
||||
adjustDeckSize(size);
|
||||
|
||||
errorBuilder.append("DeckSize:" + tDeck.countAll() + "\n");
|
||||
if (!testing) {
|
||||
errorBuilder.delete(0, errorBuilder.length()); //clear if not testing
|
||||
}
|
||||
|
||||
return tDeck;
|
||||
}
|
||||
|
||||
private class Grp {
|
||||
/** The Cardnames. */
|
||||
private final List<String> cardnames = new ArrayList<String>();
|
||||
|
||||
/** The Max cnt. */
|
||||
private int maxCnt;
|
||||
|
||||
/** The Percentage. */
|
||||
private int percentage;
|
||||
}
|
||||
|
||||
private List<Grp> readGroups(List<String> lines) {
|
||||
final List<Grp> groups = new ArrayList<Grp>();
|
||||
|
||||
Grp g = null;
|
||||
for (String s : lines) {
|
||||
if (s.equals("End")) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (s.startsWith("[Group")) {
|
||||
g = new Grp();
|
||||
final String[] ss = s.replaceAll("[\\[\\]]", "").split(" ");
|
||||
for (final String element : ss) {
|
||||
if (element.startsWith("Percentage")) {
|
||||
final String p = element.substring("Percentage".length() + 1);
|
||||
g.percentage = Integer.parseInt(p);
|
||||
}
|
||||
if (element.startsWith("MaxCnt")) {
|
||||
final String m = element.substring("MaxCnt".length() + 1);
|
||||
g.maxCnt = Integer.parseInt(m);
|
||||
}
|
||||
}
|
||||
groups.add(g);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s.equals("[/Group]")) {
|
||||
g = null;
|
||||
}
|
||||
|
||||
if (s.startsWith("BasicLandPercentage")) {
|
||||
final String[] ss = s.split("\\|");
|
||||
basicLandPercentage = Integer.parseInt(ss[0].substring("BasicLandPercentage".length() + 1));
|
||||
if(ss.length > 1)
|
||||
basicLandSet = ss[1];
|
||||
}
|
||||
else if (s.equals("Testing")) {
|
||||
testing = true;
|
||||
}
|
||||
else if (g != null) {
|
||||
g.cardnames.add(s);
|
||||
final String[] ss = s.split("\\|");
|
||||
cardCounts.put(ss[0], 0);
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.deck;
|
||||
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.generation.DeckGeneratorBase;
|
||||
import forge.deck.generation.IDeckGenPool;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* ThemeDeckGenerator class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: ThemeDeckGenerator.java 25022 2014-03-02 14:19:50Z teferi $
|
||||
*/
|
||||
public class DeckGeneratorTheme extends DeckGeneratorBase {
|
||||
@Override
|
||||
protected final float getLandPercentage() {
|
||||
return 0.44f;
|
||||
}
|
||||
@Override
|
||||
protected final float getCreaturePercentage() {
|
||||
return 0.33f;
|
||||
}
|
||||
@Override
|
||||
protected final float getSpellPercentage() {
|
||||
return 0.23f;
|
||||
}
|
||||
|
||||
private int basicLandPercentage = 0;
|
||||
private String basicLandSet = null;
|
||||
private boolean testing = false;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for ThemeDeckGenerator.
|
||||
* </p>
|
||||
*/
|
||||
public DeckGeneratorTheme(IDeckGenPool pool0) {
|
||||
super(pool0, DeckFormat.Constructed);
|
||||
setBasicLandPool(null);
|
||||
this.maxDuplicates = 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getThemeNames.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link java.util.ArrayList} object.
|
||||
*/
|
||||
public static final List<String> getThemeNames() {
|
||||
final List<String> ltNames = new ArrayList<String>();
|
||||
|
||||
final File file = new File(ForgeConstants.THEMES_DIR);
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new RuntimeException("ThemeDeckGenerator : getThemeNames error -- file not found -- filename is "
|
||||
+ file.getAbsolutePath());
|
||||
}
|
||||
|
||||
if (!file.isDirectory()) {
|
||||
throw new RuntimeException("ThemeDeckGenerator : getThemeNames error -- not a directory -- "
|
||||
+ file.getAbsolutePath());
|
||||
}
|
||||
|
||||
final String[] fileList = file.list();
|
||||
for (final String element : fileList) {
|
||||
if (element.endsWith(".thm")) {
|
||||
ltNames.add(element.substring(0, element.indexOf(".thm")));
|
||||
}
|
||||
}
|
||||
|
||||
return ltNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getThemeDeck.
|
||||
* </p>
|
||||
*
|
||||
* @param themeName
|
||||
* a {@link java.lang.String} object.
|
||||
* @param size
|
||||
* a int.
|
||||
* @return a {@link forge.CardList} object.
|
||||
*/
|
||||
public final CardPool getThemeDeck(final String themeName, final int size, final StringBuilder errorBuilder) {
|
||||
String s = "";
|
||||
String[] ss;
|
||||
|
||||
// read theme file
|
||||
final String tFileName = ForgeConstants.THEMES_DIR + "/" + themeName + ".thm";
|
||||
List<String> lines = FileUtil.readFile(tFileName);
|
||||
|
||||
final List<Grp> groups = readGroups(lines);
|
||||
|
||||
// begin assigning cards to the deck
|
||||
final Random r = MyRandom.getRandom();
|
||||
|
||||
for (int i = 0; i < groups.size(); i++) {
|
||||
final Grp g = groups.get(i);
|
||||
final float p = (float) (g.percentage * .01);
|
||||
final int grpCnt = (int) (p * size);
|
||||
final int cnSize = g.cardnames.size();
|
||||
errorBuilder.append("Group" + i + ":" + grpCnt + "\n");
|
||||
|
||||
for (int j = 0; j < grpCnt; j++) {
|
||||
s = g.cardnames.get(r.nextInt(cnSize));
|
||||
ss = s.split("\\|");
|
||||
|
||||
int lc = 0;
|
||||
while ((cardCounts.get(ss[0]) >= g.maxCnt) || (lc > 999)) {
|
||||
// looping
|
||||
// forever
|
||||
s = g.cardnames.get(r.nextInt(cnSize));
|
||||
ss = s.split("\\|");
|
||||
lc++;
|
||||
}
|
||||
if (lc > 999) {
|
||||
throw new RuntimeException("ThemeDeckGenerator : getThemeDeck -- looped too much -- filename is "
|
||||
+ tFileName);
|
||||
}
|
||||
|
||||
final int n = cardCounts.get(ss[0]);
|
||||
if (ss.length == 1) {
|
||||
tDeck.add(pool.getCard(ss[0]));
|
||||
}
|
||||
else {
|
||||
tDeck.add(pool.getCard(ss[0],ss[1]));
|
||||
}
|
||||
cardCounts.put(ss[0], n + 1);
|
||||
errorBuilder.append(s + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
int numBLands;
|
||||
if (basicLandPercentage > 0) { // if theme explicitly defines this
|
||||
numBLands = (int) (size * basicLandPercentage / 100f);
|
||||
}
|
||||
else { // otherwise, just fill in the rest of the deck with basic lands
|
||||
numBLands = size - tDeck.countAll();
|
||||
}
|
||||
|
||||
errorBuilder.append("numBLands:" + numBLands + "\n");
|
||||
|
||||
addBasicLand(numBLands,basicLandSet);
|
||||
|
||||
errorBuilder.append("DeckSize:" + tDeck.countAll() + "\n");
|
||||
|
||||
adjustDeckSize(size);
|
||||
|
||||
errorBuilder.append("DeckSize:" + tDeck.countAll() + "\n");
|
||||
if (!testing) {
|
||||
errorBuilder.delete(0, errorBuilder.length()); //clear if not testing
|
||||
}
|
||||
|
||||
return tDeck;
|
||||
}
|
||||
|
||||
private class Grp {
|
||||
/** The Cardnames. */
|
||||
private final List<String> cardnames = new ArrayList<String>();
|
||||
|
||||
/** The Max cnt. */
|
||||
private int maxCnt;
|
||||
|
||||
/** The Percentage. */
|
||||
private int percentage;
|
||||
}
|
||||
|
||||
private List<Grp> readGroups(List<String> lines) {
|
||||
final List<Grp> groups = new ArrayList<Grp>();
|
||||
|
||||
Grp g = null;
|
||||
for (String s : lines) {
|
||||
if (s.equals("End")) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (s.startsWith("[Group")) {
|
||||
g = new Grp();
|
||||
final String[] ss = s.replaceAll("[\\[\\]]", "").split(" ");
|
||||
for (final String element : ss) {
|
||||
if (element.startsWith("Percentage")) {
|
||||
final String p = element.substring("Percentage".length() + 1);
|
||||
g.percentage = Integer.parseInt(p);
|
||||
}
|
||||
if (element.startsWith("MaxCnt")) {
|
||||
final String m = element.substring("MaxCnt".length() + 1);
|
||||
g.maxCnt = Integer.parseInt(m);
|
||||
}
|
||||
}
|
||||
groups.add(g);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s.equals("[/Group]")) {
|
||||
g = null;
|
||||
}
|
||||
|
||||
if (s.startsWith("BasicLandPercentage")) {
|
||||
final String[] ss = s.split("\\|");
|
||||
basicLandPercentage = Integer.parseInt(ss[0].substring("BasicLandPercentage".length() + 1));
|
||||
if(ss.length > 1)
|
||||
basicLandSet = ss[1];
|
||||
}
|
||||
else if (s.equals("Testing")) {
|
||||
testing = true;
|
||||
}
|
||||
else if (g != null) {
|
||||
g.cardnames.add(s);
|
||||
final String[] ss = s.split("\\|");
|
||||
cardCounts.put(ss[0], 0);
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,93 +1,93 @@
|
||||
package forge.deck;
|
||||
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.interfaces.ICheckBox;
|
||||
import forge.interfaces.IComboBox;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.util.gui.SOptionPane;
|
||||
|
||||
public class DeckImportController {
|
||||
private final boolean replacingDeck;
|
||||
private final ICheckBox newEditionCheck, dateTimeCheck, onlyCoreExpCheck;
|
||||
private final IComboBox<String> monthDropdown;
|
||||
private final IComboBox<Integer> yearDropdown;
|
||||
private final List<DeckRecognizer.Token> tokens = new ArrayList<DeckRecognizer.Token>();
|
||||
|
||||
public DeckImportController(boolean replacingDeck0, ICheckBox newEditionCheck0, ICheckBox dateTimeCheck0, ICheckBox onlyCoreExpCheck0, IComboBox<String> monthDropdown0, IComboBox<Integer> yearDropdown0) {
|
||||
replacingDeck = replacingDeck0;
|
||||
newEditionCheck = newEditionCheck0;
|
||||
dateTimeCheck = dateTimeCheck0;
|
||||
onlyCoreExpCheck = onlyCoreExpCheck0;
|
||||
monthDropdown = monthDropdown0;
|
||||
yearDropdown = yearDropdown0;
|
||||
|
||||
fillDateDropdowns();
|
||||
}
|
||||
|
||||
private void fillDateDropdowns() {
|
||||
DateFormatSymbols dfs = new DateFormatSymbols();
|
||||
monthDropdown.removeAllItems();
|
||||
String[] months = dfs.getMonths();
|
||||
for (String monthName : months) {
|
||||
if (!StringUtils.isBlank(monthName)) {
|
||||
monthDropdown.addItem(monthName);
|
||||
}
|
||||
}
|
||||
int yearNow = Calendar.getInstance().get(Calendar.YEAR);
|
||||
for (int i = yearNow; i >= 1993; i--) {
|
||||
yearDropdown.addItem(Integer.valueOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
public List<DeckRecognizer.Token> parseInput(String input) {
|
||||
tokens.clear();
|
||||
|
||||
DeckRecognizer recognizer = new DeckRecognizer(newEditionCheck.isSelected(), onlyCoreExpCheck.isSelected(), FModel.getMagicDb().getCommonCards());
|
||||
if (dateTimeCheck.isSelected()) {
|
||||
recognizer.setDateConstraint(monthDropdown.getSelectedIndex(), yearDropdown.getSelectedItem());
|
||||
}
|
||||
String[] lines = input.split("\n");
|
||||
for (String line : lines) {
|
||||
tokens.add(recognizer.recognizeLine(line));
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
public Deck accept() {
|
||||
if (tokens.isEmpty()) { return null; }
|
||||
|
||||
if (replacingDeck) {
|
||||
final String warning = "This will replace the contents of your current deck with these cards.\n\nProceed?";
|
||||
if (!SOptionPane.showConfirmDialog(warning, "Replace Current Deck", "Replace", "Cancel")) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final Deck result = new Deck();
|
||||
boolean isMain = true;
|
||||
for (final DeckRecognizer.Token t : tokens) {
|
||||
final DeckRecognizer.TokenType type = t.getType();
|
||||
if ((type == DeckRecognizer.TokenType.SectionName) && t.getText().toLowerCase().contains("side")) {
|
||||
isMain = false;
|
||||
}
|
||||
if (type != DeckRecognizer.TokenType.KnownCard) {
|
||||
continue;
|
||||
}
|
||||
final PaperCard crd = t.getCard();
|
||||
if (isMain) {
|
||||
result.getMain().add(crd, t.getNumber());
|
||||
}
|
||||
else {
|
||||
result.getOrCreate(DeckSection.Sideboard).add(crd, t.getNumber());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
package forge.deck;
|
||||
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.interfaces.ICheckBox;
|
||||
import forge.interfaces.IComboBox;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.util.gui.SOptionPane;
|
||||
|
||||
public class DeckImportController {
|
||||
private final boolean replacingDeck;
|
||||
private final ICheckBox newEditionCheck, dateTimeCheck, onlyCoreExpCheck;
|
||||
private final IComboBox<String> monthDropdown;
|
||||
private final IComboBox<Integer> yearDropdown;
|
||||
private final List<DeckRecognizer.Token> tokens = new ArrayList<DeckRecognizer.Token>();
|
||||
|
||||
public DeckImportController(boolean replacingDeck0, ICheckBox newEditionCheck0, ICheckBox dateTimeCheck0, ICheckBox onlyCoreExpCheck0, IComboBox<String> monthDropdown0, IComboBox<Integer> yearDropdown0) {
|
||||
replacingDeck = replacingDeck0;
|
||||
newEditionCheck = newEditionCheck0;
|
||||
dateTimeCheck = dateTimeCheck0;
|
||||
onlyCoreExpCheck = onlyCoreExpCheck0;
|
||||
monthDropdown = monthDropdown0;
|
||||
yearDropdown = yearDropdown0;
|
||||
|
||||
fillDateDropdowns();
|
||||
}
|
||||
|
||||
private void fillDateDropdowns() {
|
||||
DateFormatSymbols dfs = new DateFormatSymbols();
|
||||
monthDropdown.removeAllItems();
|
||||
String[] months = dfs.getMonths();
|
||||
for (String monthName : months) {
|
||||
if (!StringUtils.isBlank(monthName)) {
|
||||
monthDropdown.addItem(monthName);
|
||||
}
|
||||
}
|
||||
int yearNow = Calendar.getInstance().get(Calendar.YEAR);
|
||||
for (int i = yearNow; i >= 1993; i--) {
|
||||
yearDropdown.addItem(Integer.valueOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
public List<DeckRecognizer.Token> parseInput(String input) {
|
||||
tokens.clear();
|
||||
|
||||
DeckRecognizer recognizer = new DeckRecognizer(newEditionCheck.isSelected(), onlyCoreExpCheck.isSelected(), FModel.getMagicDb().getCommonCards());
|
||||
if (dateTimeCheck.isSelected()) {
|
||||
recognizer.setDateConstraint(monthDropdown.getSelectedIndex(), yearDropdown.getSelectedItem());
|
||||
}
|
||||
String[] lines = input.split("\n");
|
||||
for (String line : lines) {
|
||||
tokens.add(recognizer.recognizeLine(line));
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
public Deck accept() {
|
||||
if (tokens.isEmpty()) { return null; }
|
||||
|
||||
if (replacingDeck) {
|
||||
final String warning = "This will replace the contents of your current deck with these cards.\n\nProceed?";
|
||||
if (!SOptionPane.showConfirmDialog(warning, "Replace Current Deck", "Replace", "Cancel")) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final Deck result = new Deck();
|
||||
boolean isMain = true;
|
||||
for (final DeckRecognizer.Token t : tokens) {
|
||||
final DeckRecognizer.TokenType type = t.getType();
|
||||
if ((type == DeckRecognizer.TokenType.SectionName) && t.getText().toLowerCase().contains("side")) {
|
||||
isMain = false;
|
||||
}
|
||||
if (type != DeckRecognizer.TokenType.KnownCard) {
|
||||
continue;
|
||||
}
|
||||
final PaperCard crd = t.getCard();
|
||||
if (isMain) {
|
||||
result.getMain().add(crd, t.getNumber());
|
||||
}
|
||||
else {
|
||||
result.getOrCreate(DeckSection.Sideboard).add(crd, t.getNumber());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,68 +1,68 @@
|
||||
package forge.deck;
|
||||
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgePreferences;
|
||||
|
||||
public enum DeckType {
|
||||
CUSTOM_DECK ("Custom User Decks"),
|
||||
CONSTRUCTED_DECK ("Constructed Decks"),
|
||||
COMMANDER_DECK ("Commander Decks"),
|
||||
TINY_LEADERS_DECKS ("Tiny Leaders Decks"),
|
||||
SCHEME_DECKS ("Scheme Decks"),
|
||||
PLANAR_DECKS ("Planar Decks"),
|
||||
DRAFT_DECKS ("Draft Decks"),
|
||||
SEALED_DECKS ("Sealed Decks"),
|
||||
PRECONSTRUCTED_DECK("Preconstructed Decks"),
|
||||
QUEST_OPPONENT_DECK ("Quest Opponent Decks"),
|
||||
COLOR_DECK ("Random Color Decks"),
|
||||
STANDARD_CARDGEN_DECK ("Random Standard Card-themed Decks"),
|
||||
MODERN_CARDGEN_DECK ("Random Modern Card-themed Decks"),
|
||||
STANDARD_COLOR_DECK ("Random Standard Color Decks"),
|
||||
MODERN_COLOR_DECK ("Random Modern Color Decks"),
|
||||
THEME_DECK ("Random Theme Decks"),
|
||||
RANDOM_DECK ("Random Decks"),
|
||||
NET_DECK ("Net Decks"),
|
||||
NET_COMMANDER_DECK ("Net Commander Decks");
|
||||
|
||||
public static DeckType[] ConstructedOptions;
|
||||
|
||||
static {
|
||||
if (!FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY)) {
|
||||
ConstructedOptions = new DeckType[]{
|
||||
DeckType.CUSTOM_DECK,
|
||||
DeckType.PRECONSTRUCTED_DECK,
|
||||
DeckType.QUEST_OPPONENT_DECK,
|
||||
DeckType.COLOR_DECK,
|
||||
DeckType.STANDARD_COLOR_DECK,
|
||||
DeckType.STANDARD_CARDGEN_DECK,
|
||||
DeckType.MODERN_CARDGEN_DECK,
|
||||
DeckType.MODERN_COLOR_DECK,
|
||||
DeckType.THEME_DECK,
|
||||
DeckType.RANDOM_DECK,
|
||||
DeckType.NET_DECK
|
||||
};
|
||||
} else {
|
||||
ConstructedOptions = new DeckType[]{
|
||||
DeckType.CUSTOM_DECK,
|
||||
DeckType.PRECONSTRUCTED_DECK,
|
||||
DeckType.QUEST_OPPONENT_DECK,
|
||||
DeckType.COLOR_DECK,
|
||||
DeckType.STANDARD_COLOR_DECK,
|
||||
DeckType.MODERN_COLOR_DECK,
|
||||
DeckType.THEME_DECK,
|
||||
DeckType.RANDOM_DECK,
|
||||
DeckType.NET_DECK
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private String value;
|
||||
private DeckType(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
package forge.deck;
|
||||
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgePreferences;
|
||||
|
||||
public enum DeckType {
|
||||
CUSTOM_DECK ("Custom User Decks"),
|
||||
CONSTRUCTED_DECK ("Constructed Decks"),
|
||||
COMMANDER_DECK ("Commander Decks"),
|
||||
TINY_LEADERS_DECKS ("Tiny Leaders Decks"),
|
||||
SCHEME_DECKS ("Scheme Decks"),
|
||||
PLANAR_DECKS ("Planar Decks"),
|
||||
DRAFT_DECKS ("Draft Decks"),
|
||||
SEALED_DECKS ("Sealed Decks"),
|
||||
PRECONSTRUCTED_DECK("Preconstructed Decks"),
|
||||
QUEST_OPPONENT_DECK ("Quest Opponent Decks"),
|
||||
COLOR_DECK ("Random Color Decks"),
|
||||
STANDARD_CARDGEN_DECK ("Random Standard Card-themed Decks"),
|
||||
MODERN_CARDGEN_DECK ("Random Modern Card-themed Decks"),
|
||||
STANDARD_COLOR_DECK ("Random Standard Color Decks"),
|
||||
MODERN_COLOR_DECK ("Random Modern Color Decks"),
|
||||
THEME_DECK ("Random Theme Decks"),
|
||||
RANDOM_DECK ("Random Decks"),
|
||||
NET_DECK ("Net Decks"),
|
||||
NET_COMMANDER_DECK ("Net Commander Decks");
|
||||
|
||||
public static DeckType[] ConstructedOptions;
|
||||
|
||||
static {
|
||||
if (!FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY)) {
|
||||
ConstructedOptions = new DeckType[]{
|
||||
DeckType.CUSTOM_DECK,
|
||||
DeckType.PRECONSTRUCTED_DECK,
|
||||
DeckType.QUEST_OPPONENT_DECK,
|
||||
DeckType.COLOR_DECK,
|
||||
DeckType.STANDARD_COLOR_DECK,
|
||||
DeckType.STANDARD_CARDGEN_DECK,
|
||||
DeckType.MODERN_CARDGEN_DECK,
|
||||
DeckType.MODERN_COLOR_DECK,
|
||||
DeckType.THEME_DECK,
|
||||
DeckType.RANDOM_DECK,
|
||||
DeckType.NET_DECK
|
||||
};
|
||||
} else {
|
||||
ConstructedOptions = new DeckType[]{
|
||||
DeckType.CUSTOM_DECK,
|
||||
DeckType.PRECONSTRUCTED_DECK,
|
||||
DeckType.QUEST_OPPONENT_DECK,
|
||||
DeckType.COLOR_DECK,
|
||||
DeckType.STANDARD_COLOR_DECK,
|
||||
DeckType.MODERN_COLOR_DECK,
|
||||
DeckType.THEME_DECK,
|
||||
DeckType.RANDOM_DECK,
|
||||
DeckType.NET_DECK
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private String value;
|
||||
private DeckType(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,127 +1,127 @@
|
||||
package forge.deck;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.deck.io.DeckSerializer;
|
||||
import forge.deck.io.DeckStorage;
|
||||
import forge.download.GuiDownloadZipService;
|
||||
import forge.game.GameType;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.WaitCallback;
|
||||
import forge.util.gui.SGuiChoose;
|
||||
import forge.util.storage.StorageBase;
|
||||
|
||||
public class NetDeckCategory extends StorageBase<Deck> {
|
||||
public static final String PREFIX = "NET_DECK_";
|
||||
private static Map<String, NetDeckCategory> constructed, commander;
|
||||
|
||||
private static Map<String, NetDeckCategory> loadCategories(String filename) {
|
||||
Map<String, NetDeckCategory> categories = new TreeMap<String, NetDeckCategory>();
|
||||
if (FileUtil.doesFileExist(filename)) {
|
||||
List<String> lines = FileUtil.readFile(filename);
|
||||
for (String line : lines) {
|
||||
int idx = line.indexOf('|');
|
||||
if (idx != -1) {
|
||||
String name = line.substring(0, idx).trim();
|
||||
String url = line.substring(idx + 1).trim();
|
||||
categories.put(name, new NetDeckCategory(name, url));
|
||||
}
|
||||
}
|
||||
}
|
||||
return categories;
|
||||
}
|
||||
|
||||
public static NetDeckCategory selectAndLoad(GameType gameType) {
|
||||
return selectAndLoad(gameType, null);
|
||||
}
|
||||
public static NetDeckCategory selectAndLoad(GameType gameType, String name) {
|
||||
Map<String, NetDeckCategory> categories;
|
||||
switch (gameType) {
|
||||
case Constructed:
|
||||
case Gauntlet:
|
||||
if (constructed == null) {
|
||||
constructed = loadCategories(ForgeConstants.NET_DECKS_LIST_FILE);
|
||||
}
|
||||
categories = constructed;
|
||||
break;
|
||||
case Commander:
|
||||
if (commander == null) {
|
||||
commander = loadCategories(ForgeConstants.NET_DECKS_COMMANDER_LIST_FILE);
|
||||
}
|
||||
categories = commander;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
NetDeckCategory category = categories.get(name);
|
||||
if (category != null && category.map.isEmpty()) {
|
||||
//if name passed in, try to load decks from current cached files
|
||||
File downloadDir = new File(category.getFullPath());
|
||||
if (downloadDir.exists()) {
|
||||
for (File file : downloadDir.listFiles(DeckStorage.DCK_FILE_FILTER)) {
|
||||
Deck deck = DeckSerializer.fromFile(file);
|
||||
if (deck != null) {
|
||||
category.map.put(deck.getName(), deck);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return category;
|
||||
}
|
||||
|
||||
final NetDeckCategory c = SGuiChoose.oneOrNone("Select a Net Deck category", categories.values());
|
||||
if (c == null) { return null; }
|
||||
|
||||
if (c.map.isEmpty()) { //only download decks once per session
|
||||
WaitCallback<Boolean> callback = new WaitCallback<Boolean>() {
|
||||
@Override
|
||||
public void run() {
|
||||
String downloadLoc = c.getFullPath();
|
||||
GuiBase.getInterface().download(new GuiDownloadZipService(c.getName(), "decks", c.getUrl(), downloadLoc, downloadLoc, null) {
|
||||
@Override
|
||||
protected void copyInputStream(InputStream in, String outPath) throws IOException {
|
||||
super.copyInputStream(in, outPath);
|
||||
|
||||
Deck deck = DeckSerializer.fromFile(new File(outPath));
|
||||
if (deck != null) {
|
||||
c.map.put(deck.getName(), deck);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
if (!callback.invokeAndWait()) { return null; } //wait for download to finish
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private final String url;
|
||||
|
||||
private NetDeckCategory(String name0, String url0) {
|
||||
super(name0, ForgeConstants.DECK_NET_DIR + name0, new HashMap<String, Deck>());
|
||||
url = url0;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getDeckType() {
|
||||
return "Net Decks - " + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
package forge.deck;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.deck.io.DeckSerializer;
|
||||
import forge.deck.io.DeckStorage;
|
||||
import forge.download.GuiDownloadZipService;
|
||||
import forge.game.GameType;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.WaitCallback;
|
||||
import forge.util.gui.SGuiChoose;
|
||||
import forge.util.storage.StorageBase;
|
||||
|
||||
public class NetDeckCategory extends StorageBase<Deck> {
|
||||
public static final String PREFIX = "NET_DECK_";
|
||||
private static Map<String, NetDeckCategory> constructed, commander;
|
||||
|
||||
private static Map<String, NetDeckCategory> loadCategories(String filename) {
|
||||
Map<String, NetDeckCategory> categories = new TreeMap<String, NetDeckCategory>();
|
||||
if (FileUtil.doesFileExist(filename)) {
|
||||
List<String> lines = FileUtil.readFile(filename);
|
||||
for (String line : lines) {
|
||||
int idx = line.indexOf('|');
|
||||
if (idx != -1) {
|
||||
String name = line.substring(0, idx).trim();
|
||||
String url = line.substring(idx + 1).trim();
|
||||
categories.put(name, new NetDeckCategory(name, url));
|
||||
}
|
||||
}
|
||||
}
|
||||
return categories;
|
||||
}
|
||||
|
||||
public static NetDeckCategory selectAndLoad(GameType gameType) {
|
||||
return selectAndLoad(gameType, null);
|
||||
}
|
||||
public static NetDeckCategory selectAndLoad(GameType gameType, String name) {
|
||||
Map<String, NetDeckCategory> categories;
|
||||
switch (gameType) {
|
||||
case Constructed:
|
||||
case Gauntlet:
|
||||
if (constructed == null) {
|
||||
constructed = loadCategories(ForgeConstants.NET_DECKS_LIST_FILE);
|
||||
}
|
||||
categories = constructed;
|
||||
break;
|
||||
case Commander:
|
||||
if (commander == null) {
|
||||
commander = loadCategories(ForgeConstants.NET_DECKS_COMMANDER_LIST_FILE);
|
||||
}
|
||||
categories = commander;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
if (name != null) {
|
||||
NetDeckCategory category = categories.get(name);
|
||||
if (category != null && category.map.isEmpty()) {
|
||||
//if name passed in, try to load decks from current cached files
|
||||
File downloadDir = new File(category.getFullPath());
|
||||
if (downloadDir.exists()) {
|
||||
for (File file : downloadDir.listFiles(DeckStorage.DCK_FILE_FILTER)) {
|
||||
Deck deck = DeckSerializer.fromFile(file);
|
||||
if (deck != null) {
|
||||
category.map.put(deck.getName(), deck);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return category;
|
||||
}
|
||||
|
||||
final NetDeckCategory c = SGuiChoose.oneOrNone("Select a Net Deck category", categories.values());
|
||||
if (c == null) { return null; }
|
||||
|
||||
if (c.map.isEmpty()) { //only download decks once per session
|
||||
WaitCallback<Boolean> callback = new WaitCallback<Boolean>() {
|
||||
@Override
|
||||
public void run() {
|
||||
String downloadLoc = c.getFullPath();
|
||||
GuiBase.getInterface().download(new GuiDownloadZipService(c.getName(), "decks", c.getUrl(), downloadLoc, downloadLoc, null) {
|
||||
@Override
|
||||
protected void copyInputStream(InputStream in, String outPath) throws IOException {
|
||||
super.copyInputStream(in, outPath);
|
||||
|
||||
Deck deck = DeckSerializer.fromFile(new File(outPath));
|
||||
if (deck != null) {
|
||||
c.map.put(deck.getName(), deck);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
if (!callback.invokeAndWait()) { return null; } //wait for download to finish
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private final String url;
|
||||
|
||||
private NetDeckCategory(String name0, String url0) {
|
||||
super(name0, ForgeConstants.DECK_NET_DIR + name0, new HashMap<String, Deck>());
|
||||
url = url0;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getDeckType() {
|
||||
return "Net Decks - " + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,188 +1,188 @@
|
||||
package forge.deck;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.game.GameType;
|
||||
import forge.game.IHasGameType;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.QuestController;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
public class RandomDeckGenerator extends DeckProxy implements Comparable<RandomDeckGenerator> {
|
||||
private enum RandomDeckType {
|
||||
Generated,
|
||||
User,
|
||||
Favorite
|
||||
}
|
||||
|
||||
public static List<DeckProxy> getRandomDecks(final IHasGameType lstDecks0, final boolean isAi0) {
|
||||
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
|
||||
|
||||
decks.add(new RandomDeckGenerator("Random Generated Deck", RandomDeckType.Generated, lstDecks0, isAi0));
|
||||
decks.add(new RandomDeckGenerator("Random User Deck", RandomDeckType.User, lstDecks0, isAi0));
|
||||
decks.add(new RandomDeckGenerator("Random Favorite Deck", RandomDeckType.Favorite, lstDecks0, isAi0));
|
||||
|
||||
return decks;
|
||||
}
|
||||
|
||||
public static Deck getRandomUserDeck(final IHasGameType lstDecks0, final boolean isAi0) {
|
||||
RandomDeckGenerator generator = new RandomDeckGenerator(null, RandomDeckType.User, lstDecks0, isAi0);
|
||||
return generator.getDeck();
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final RandomDeckType type;
|
||||
private final IHasGameType lstDecks;
|
||||
private final boolean isAi;
|
||||
|
||||
private RandomDeckGenerator(final String name0, final RandomDeckType type0, final IHasGameType lstDecks0, final boolean isAi0) {
|
||||
super();
|
||||
name = name0;
|
||||
type = type0;
|
||||
lstDecks = lstDecks0;
|
||||
isAi = isAi0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final RandomDeckGenerator d) {
|
||||
return Integer.compare(type.ordinal(), d.type.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deck getDeck() {
|
||||
switch (type) {
|
||||
case Generated:
|
||||
return getGeneratedDeck();
|
||||
case User:
|
||||
return getUserDeck();
|
||||
default:
|
||||
return getFavoriteDeck();
|
||||
}
|
||||
}
|
||||
|
||||
private Deck getGeneratedDeck() {
|
||||
switch (lstDecks.getGameType()) {
|
||||
case Commander:
|
||||
return DeckgenUtil.generateCommanderDeck(isAi, GameType.Commander);
|
||||
case TinyLeaders:
|
||||
return DeckgenUtil.generateCommanderDeck(isAi, GameType.TinyLeaders);
|
||||
case Archenemy:
|
||||
return DeckgenUtil.generateSchemeDeck();
|
||||
case Planechase:
|
||||
return DeckgenUtil.generatePlanarDeck();
|
||||
default:
|
||||
while (true) {
|
||||
switch (Aggregates.random(DeckType.ConstructedOptions)) {
|
||||
case PRECONSTRUCTED_DECK:
|
||||
return Aggregates.random(DeckProxy.getAllPreconstructedDecks(QuestController.getPrecons())).getDeck();
|
||||
case QUEST_OPPONENT_DECK:
|
||||
return Aggregates.random(DeckProxy.getAllQuestEventAndChallenges()).getDeck();
|
||||
case COLOR_DECK:
|
||||
List<String> colors = new ArrayList<String>();
|
||||
int count = Aggregates.randomInt(1, 3);
|
||||
for (int i = 1; i <= count; i++) {
|
||||
colors.add("Random " + i);
|
||||
}
|
||||
return DeckgenUtil.buildColorDeck(colors, null, isAi);
|
||||
case STANDARD_CARDGEN_DECK:
|
||||
return DeckgenUtil.buildCardGenDeck(FModel.getFormats().getStandard(),isAi);
|
||||
case MODERN_CARDGEN_DECK:
|
||||
return DeckgenUtil.buildCardGenDeck(FModel.getFormats().getModern(),isAi);
|
||||
case STANDARD_COLOR_DECK:
|
||||
colors = new ArrayList<String>();
|
||||
count = Aggregates.randomInt(1, 3);
|
||||
for (int i = 1; i <= count; i++) {
|
||||
colors.add("Random " + i);
|
||||
}
|
||||
return DeckgenUtil.buildColorDeck(colors, FModel.getFormats().getStandard().getFilterPrinted(), isAi);
|
||||
case MODERN_COLOR_DECK:
|
||||
colors = new ArrayList<String>();
|
||||
count = Aggregates.randomInt(1, 3);
|
||||
for (int i = 1; i <= count; i++) {
|
||||
colors.add("Random " + i);
|
||||
}
|
||||
return DeckgenUtil.buildColorDeck(colors, FModel.getFormats().getModern().getFilterPrinted(), isAi);
|
||||
case THEME_DECK:
|
||||
return Aggregates.random(DeckProxy.getAllThemeDecks()).getDeck();
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Deck getUserDeck() {
|
||||
Iterable<DeckProxy> decks;
|
||||
final GameType gameType = lstDecks.getGameType();
|
||||
switch (gameType) {
|
||||
case Commander:
|
||||
decks = DeckProxy.getAllCommanderDecks(DeckFormat.Commander.isLegalDeckPredicate());
|
||||
break;
|
||||
case TinyLeaders:
|
||||
decks = DeckProxy.getAllTinyLeadersDecks(DeckFormat.TinyLeaders.isLegalDeckPredicate());
|
||||
break;
|
||||
case Archenemy:
|
||||
decks = DeckProxy.getAllSchemeDecks(DeckFormat.Archenemy.isLegalDeckPredicate());
|
||||
break;
|
||||
case Planechase:
|
||||
decks = DeckProxy.getAllPlanarDecks(DeckFormat.Planechase.isLegalDeckPredicate());
|
||||
break;
|
||||
default:
|
||||
decks = DeckProxy.getAllConstructedDecks(gameType.getDeckFormat().isLegalDeckPredicate());
|
||||
break;
|
||||
}
|
||||
if (Iterables.isEmpty(decks)) {
|
||||
return getGeneratedDeck(); //fall back to generated deck if no decks in filtered list
|
||||
}
|
||||
return Aggregates.random(decks).getDeck();
|
||||
}
|
||||
|
||||
private Deck getFavoriteDeck() {
|
||||
Iterable<DeckProxy> decks;
|
||||
switch (lstDecks.getGameType()) {
|
||||
case Commander:
|
||||
decks = DeckProxy.getAllCommanderDecks();
|
||||
break;
|
||||
case TinyLeaders:
|
||||
decks = DeckProxy.getAllTinyLeadersDecks();
|
||||
break;
|
||||
case Archenemy:
|
||||
decks = DeckProxy.getAllSchemeDecks();
|
||||
break;
|
||||
case Planechase:
|
||||
decks = DeckProxy.getAllPlanarDecks();
|
||||
break;
|
||||
default:
|
||||
decks = DeckProxy.getAllConstructedDecks();
|
||||
break;
|
||||
}
|
||||
decks = Iterables.filter(decks, new Predicate<DeckProxy>() {
|
||||
@Override public boolean apply(final DeckProxy deck) {
|
||||
return deck.isFavoriteDeck();
|
||||
}
|
||||
});
|
||||
if (Iterables.isEmpty(decks)) {
|
||||
return getGeneratedDeck(); //fall back to generated deck if no favorite decks
|
||||
}
|
||||
return Aggregates.random(decks).getDeck();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGeneratedDeck() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
package forge.deck;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.game.GameType;
|
||||
import forge.game.IHasGameType;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.QuestController;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
public class RandomDeckGenerator extends DeckProxy implements Comparable<RandomDeckGenerator> {
|
||||
private enum RandomDeckType {
|
||||
Generated,
|
||||
User,
|
||||
Favorite
|
||||
}
|
||||
|
||||
public static List<DeckProxy> getRandomDecks(final IHasGameType lstDecks0, final boolean isAi0) {
|
||||
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
|
||||
|
||||
decks.add(new RandomDeckGenerator("Random Generated Deck", RandomDeckType.Generated, lstDecks0, isAi0));
|
||||
decks.add(new RandomDeckGenerator("Random User Deck", RandomDeckType.User, lstDecks0, isAi0));
|
||||
decks.add(new RandomDeckGenerator("Random Favorite Deck", RandomDeckType.Favorite, lstDecks0, isAi0));
|
||||
|
||||
return decks;
|
||||
}
|
||||
|
||||
public static Deck getRandomUserDeck(final IHasGameType lstDecks0, final boolean isAi0) {
|
||||
RandomDeckGenerator generator = new RandomDeckGenerator(null, RandomDeckType.User, lstDecks0, isAi0);
|
||||
return generator.getDeck();
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final RandomDeckType type;
|
||||
private final IHasGameType lstDecks;
|
||||
private final boolean isAi;
|
||||
|
||||
private RandomDeckGenerator(final String name0, final RandomDeckType type0, final IHasGameType lstDecks0, final boolean isAi0) {
|
||||
super();
|
||||
name = name0;
|
||||
type = type0;
|
||||
lstDecks = lstDecks0;
|
||||
isAi = isAi0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final RandomDeckGenerator d) {
|
||||
return Integer.compare(type.ordinal(), d.type.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deck getDeck() {
|
||||
switch (type) {
|
||||
case Generated:
|
||||
return getGeneratedDeck();
|
||||
case User:
|
||||
return getUserDeck();
|
||||
default:
|
||||
return getFavoriteDeck();
|
||||
}
|
||||
}
|
||||
|
||||
private Deck getGeneratedDeck() {
|
||||
switch (lstDecks.getGameType()) {
|
||||
case Commander:
|
||||
return DeckgenUtil.generateCommanderDeck(isAi, GameType.Commander);
|
||||
case TinyLeaders:
|
||||
return DeckgenUtil.generateCommanderDeck(isAi, GameType.TinyLeaders);
|
||||
case Archenemy:
|
||||
return DeckgenUtil.generateSchemeDeck();
|
||||
case Planechase:
|
||||
return DeckgenUtil.generatePlanarDeck();
|
||||
default:
|
||||
while (true) {
|
||||
switch (Aggregates.random(DeckType.ConstructedOptions)) {
|
||||
case PRECONSTRUCTED_DECK:
|
||||
return Aggregates.random(DeckProxy.getAllPreconstructedDecks(QuestController.getPrecons())).getDeck();
|
||||
case QUEST_OPPONENT_DECK:
|
||||
return Aggregates.random(DeckProxy.getAllQuestEventAndChallenges()).getDeck();
|
||||
case COLOR_DECK:
|
||||
List<String> colors = new ArrayList<String>();
|
||||
int count = Aggregates.randomInt(1, 3);
|
||||
for (int i = 1; i <= count; i++) {
|
||||
colors.add("Random " + i);
|
||||
}
|
||||
return DeckgenUtil.buildColorDeck(colors, null, isAi);
|
||||
case STANDARD_CARDGEN_DECK:
|
||||
return DeckgenUtil.buildCardGenDeck(FModel.getFormats().getStandard(),isAi);
|
||||
case MODERN_CARDGEN_DECK:
|
||||
return DeckgenUtil.buildCardGenDeck(FModel.getFormats().getModern(),isAi);
|
||||
case STANDARD_COLOR_DECK:
|
||||
colors = new ArrayList<String>();
|
||||
count = Aggregates.randomInt(1, 3);
|
||||
for (int i = 1; i <= count; i++) {
|
||||
colors.add("Random " + i);
|
||||
}
|
||||
return DeckgenUtil.buildColorDeck(colors, FModel.getFormats().getStandard().getFilterPrinted(), isAi);
|
||||
case MODERN_COLOR_DECK:
|
||||
colors = new ArrayList<String>();
|
||||
count = Aggregates.randomInt(1, 3);
|
||||
for (int i = 1; i <= count; i++) {
|
||||
colors.add("Random " + i);
|
||||
}
|
||||
return DeckgenUtil.buildColorDeck(colors, FModel.getFormats().getModern().getFilterPrinted(), isAi);
|
||||
case THEME_DECK:
|
||||
return Aggregates.random(DeckProxy.getAllThemeDecks()).getDeck();
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Deck getUserDeck() {
|
||||
Iterable<DeckProxy> decks;
|
||||
final GameType gameType = lstDecks.getGameType();
|
||||
switch (gameType) {
|
||||
case Commander:
|
||||
decks = DeckProxy.getAllCommanderDecks(DeckFormat.Commander.isLegalDeckPredicate());
|
||||
break;
|
||||
case TinyLeaders:
|
||||
decks = DeckProxy.getAllTinyLeadersDecks(DeckFormat.TinyLeaders.isLegalDeckPredicate());
|
||||
break;
|
||||
case Archenemy:
|
||||
decks = DeckProxy.getAllSchemeDecks(DeckFormat.Archenemy.isLegalDeckPredicate());
|
||||
break;
|
||||
case Planechase:
|
||||
decks = DeckProxy.getAllPlanarDecks(DeckFormat.Planechase.isLegalDeckPredicate());
|
||||
break;
|
||||
default:
|
||||
decks = DeckProxy.getAllConstructedDecks(gameType.getDeckFormat().isLegalDeckPredicate());
|
||||
break;
|
||||
}
|
||||
if (Iterables.isEmpty(decks)) {
|
||||
return getGeneratedDeck(); //fall back to generated deck if no decks in filtered list
|
||||
}
|
||||
return Aggregates.random(decks).getDeck();
|
||||
}
|
||||
|
||||
private Deck getFavoriteDeck() {
|
||||
Iterable<DeckProxy> decks;
|
||||
switch (lstDecks.getGameType()) {
|
||||
case Commander:
|
||||
decks = DeckProxy.getAllCommanderDecks();
|
||||
break;
|
||||
case TinyLeaders:
|
||||
decks = DeckProxy.getAllTinyLeadersDecks();
|
||||
break;
|
||||
case Archenemy:
|
||||
decks = DeckProxy.getAllSchemeDecks();
|
||||
break;
|
||||
case Planechase:
|
||||
decks = DeckProxy.getAllPlanarDecks();
|
||||
break;
|
||||
default:
|
||||
decks = DeckProxy.getAllConstructedDecks();
|
||||
break;
|
||||
}
|
||||
decks = Iterables.filter(decks, new Predicate<DeckProxy>() {
|
||||
@Override public boolean apply(final DeckProxy deck) {
|
||||
return deck.isFavoriteDeck();
|
||||
}
|
||||
});
|
||||
if (Iterables.isEmpty(decks)) {
|
||||
return getGeneratedDeck(); //fall back to generated deck if no favorite decks
|
||||
}
|
||||
return Aggregates.random(decks).getDeck();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGeneratedDeck() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,67 +1,67 @@
|
||||
package forge.deck.io;
|
||||
|
||||
import java.io.File;
|
||||
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 java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.game.GameFormat;
|
||||
import forge.item.PaperCard;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
/**
|
||||
* Created by maustin on 11/05/2017.
|
||||
*/
|
||||
public class CardThemedMatrixIO {
|
||||
|
||||
/** suffix for all gauntlet data files */
|
||||
public static final String SUFFIX_DATA = ".dat";
|
||||
|
||||
public static void saveMatrix(GameFormat format, HashMap<String,List<Map.Entry<PaperCard,Integer>>> map){
|
||||
File file = getMatrixFile(format);
|
||||
ObjectOutputStream s = null;
|
||||
try {
|
||||
FileOutputStream f = new FileOutputStream(file);
|
||||
s = new ObjectOutputStream(f);
|
||||
s.writeObject(map);
|
||||
s.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error writing matrix data: " + e);
|
||||
} finally {
|
||||
if(s!=null) {
|
||||
try {
|
||||
s.close();
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<String,List<Map.Entry<PaperCard,Integer>>> loadMatrix(GameFormat format){
|
||||
try {
|
||||
FileInputStream fin = new FileInputStream(getMatrixFile(format));
|
||||
ObjectInputStream s = new ObjectInputStream(fin);
|
||||
HashMap<String, List<Map.Entry<PaperCard,Integer>>> matrix = (HashMap<String, List<Map.Entry<PaperCard,Integer>>>) s.readObject();
|
||||
s.close();
|
||||
return matrix;
|
||||
}catch (Exception e){
|
||||
System.out.println("Error reading matrix data: " + e);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static File getMatrixFile(final String name) {
|
||||
return new File(ForgeConstants.DECK_GEN_DIR, name + SUFFIX_DATA);
|
||||
}
|
||||
|
||||
public static File getMatrixFile(final GameFormat gf) {
|
||||
return getMatrixFile(gf.getName());
|
||||
}
|
||||
}
|
||||
package forge.deck.io;
|
||||
|
||||
import java.io.File;
|
||||
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 java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.game.GameFormat;
|
||||
import forge.item.PaperCard;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
/**
|
||||
* Created by maustin on 11/05/2017.
|
||||
*/
|
||||
public class CardThemedMatrixIO {
|
||||
|
||||
/** suffix for all gauntlet data files */
|
||||
public static final String SUFFIX_DATA = ".dat";
|
||||
|
||||
public static void saveMatrix(GameFormat format, HashMap<String,List<Map.Entry<PaperCard,Integer>>> map){
|
||||
File file = getMatrixFile(format);
|
||||
ObjectOutputStream s = null;
|
||||
try {
|
||||
FileOutputStream f = new FileOutputStream(file);
|
||||
s = new ObjectOutputStream(f);
|
||||
s.writeObject(map);
|
||||
s.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error writing matrix data: " + e);
|
||||
} finally {
|
||||
if(s!=null) {
|
||||
try {
|
||||
s.close();
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<String,List<Map.Entry<PaperCard,Integer>>> loadMatrix(GameFormat format){
|
||||
try {
|
||||
FileInputStream fin = new FileInputStream(getMatrixFile(format));
|
||||
ObjectInputStream s = new ObjectInputStream(fin);
|
||||
HashMap<String, List<Map.Entry<PaperCard,Integer>>> matrix = (HashMap<String, List<Map.Entry<PaperCard,Integer>>>) s.readObject();
|
||||
s.close();
|
||||
return matrix;
|
||||
}catch (Exception e){
|
||||
System.out.println("Error reading matrix data: " + e);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static File getMatrixFile(final String name) {
|
||||
return new File(ForgeConstants.DECK_GEN_DIR, name + SUFFIX_DATA);
|
||||
}
|
||||
|
||||
public static File getMatrixFile(final GameFormat gf) {
|
||||
return getMatrixFile(gf.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,176 +1,176 @@
|
||||
package forge.deck.io;
|
||||
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Preferences associated with individual decks
|
||||
*
|
||||
*/
|
||||
public class DeckPreferences {
|
||||
private static String currentDeck = "", draftDeck = "", sealedDeck = "", commanderDeck = "", tinyLeadersDeck = "", planarDeck = "", schemeDeck = "";
|
||||
private static Map<String, DeckPreferences> allPrefs = new HashMap<String, DeckPreferences>();
|
||||
|
||||
public static String getCurrentDeck() {
|
||||
return currentDeck;
|
||||
}
|
||||
public static void setCurrentDeck(String currentDeck0) {
|
||||
if (currentDeck.equals(currentDeck0)) { return; }
|
||||
currentDeck = currentDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getDraftDeck() {
|
||||
return draftDeck;
|
||||
}
|
||||
public static void setDraftDeck(String draftDeck0) {
|
||||
if (draftDeck.equals(draftDeck0)) { return; }
|
||||
draftDeck = draftDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getSealedDeck() {
|
||||
return sealedDeck;
|
||||
}
|
||||
public static void setSealedDeck(String sealedDeck0) {
|
||||
if (sealedDeck.equals(sealedDeck0)) { return; }
|
||||
sealedDeck = sealedDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getCommanderDeck() {
|
||||
return commanderDeck;
|
||||
}
|
||||
public static void setCommanderDeck(String commanderDeck0) {
|
||||
if (commanderDeck.equals(commanderDeck0)) { return; }
|
||||
commanderDeck = commanderDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getTinyLeadersDeck() {
|
||||
return tinyLeadersDeck;
|
||||
}
|
||||
public static void setTinyLeadersDeck(String tinyLeadersDeck0) {
|
||||
if (tinyLeadersDeck.equals(tinyLeadersDeck0)) { return; }
|
||||
tinyLeadersDeck = tinyLeadersDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getPlanarDeck() {
|
||||
return planarDeck;
|
||||
}
|
||||
public static void setPlanarDeck(String planarDeck0) {
|
||||
if (planarDeck.equals(planarDeck0)) { return; }
|
||||
planarDeck = planarDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getSchemeDeck() {
|
||||
return schemeDeck;
|
||||
}
|
||||
public static void setSchemeDeck(String schemeDeck0) {
|
||||
if (schemeDeck.equals(schemeDeck0)) { return; }
|
||||
schemeDeck = schemeDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static DeckPreferences getPrefs(DeckProxy deck) {
|
||||
String key = deck.getUniqueKey();
|
||||
DeckPreferences prefs = allPrefs.get(key);
|
||||
if (prefs == null) {
|
||||
prefs = new DeckPreferences();
|
||||
allPrefs.put(key, prefs);
|
||||
}
|
||||
return prefs;
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
allPrefs.clear();
|
||||
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final Document document = builder.parse(new File(ForgeConstants.DECK_PREFS_FILE));
|
||||
|
||||
final Element root = (Element)document.getElementsByTagName("preferences").item(0);
|
||||
currentDeck = root.getAttribute("currentDeck");
|
||||
draftDeck = root.getAttribute("draftDeck");
|
||||
sealedDeck = root.getAttribute("sealedDeck");
|
||||
commanderDeck = root.getAttribute("commanderDeck");
|
||||
tinyLeadersDeck = root.getAttribute("tinyLeadersDeck");
|
||||
planarDeck = root.getAttribute("planarDeck");
|
||||
schemeDeck = root.getAttribute("schemeDeck");
|
||||
|
||||
final NodeList cards = document.getElementsByTagName("deck");
|
||||
for (int i = 0; i < cards.getLength(); i++) {
|
||||
final DeckPreferences prefs = new DeckPreferences();
|
||||
final Element el = (Element)cards.item(i);
|
||||
allPrefs.put(el.getAttribute("key"), prefs);
|
||||
prefs.starCount = XmlUtil.getIntAttribute(el, "stars");
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
//ok if file not found
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void save() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
Element root = document.createElement("preferences");
|
||||
root.setAttribute("type", "decks");
|
||||
root.setAttribute("currentDeck", currentDeck);
|
||||
root.setAttribute("draftDeck", draftDeck);
|
||||
root.setAttribute("sealedDeck", sealedDeck);
|
||||
root.setAttribute("commanderDeck", commanderDeck);
|
||||
root.setAttribute("tinyLeadersDeck", tinyLeadersDeck);
|
||||
root.setAttribute("planarDeck", planarDeck);
|
||||
root.setAttribute("schemeDeck", schemeDeck);
|
||||
document.appendChild(root);
|
||||
|
||||
for (Map.Entry<String, DeckPreferences> entry : allPrefs.entrySet()) {
|
||||
if (entry.getValue().starCount > 0) {
|
||||
Element deck = document.createElement("deck");
|
||||
deck.setAttribute("key", entry.getKey());
|
||||
deck.setAttribute("stars", String.valueOf(entry.getValue().starCount));
|
||||
root.appendChild(deck);
|
||||
}
|
||||
}
|
||||
XmlUtil.saveDocument(document, ForgeConstants.DECK_PREFS_FILE);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private int starCount;
|
||||
|
||||
private DeckPreferences() {
|
||||
}
|
||||
|
||||
public int getStarCount() {
|
||||
return this.starCount;
|
||||
}
|
||||
|
||||
public void setStarCount(int starCount0) {
|
||||
if (this.starCount == starCount0) { return; }
|
||||
this.starCount = starCount0;
|
||||
save();
|
||||
}
|
||||
package forge.deck.io;
|
||||
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Preferences associated with individual decks
|
||||
*
|
||||
*/
|
||||
public class DeckPreferences {
|
||||
private static String currentDeck = "", draftDeck = "", sealedDeck = "", commanderDeck = "", tinyLeadersDeck = "", planarDeck = "", schemeDeck = "";
|
||||
private static Map<String, DeckPreferences> allPrefs = new HashMap<String, DeckPreferences>();
|
||||
|
||||
public static String getCurrentDeck() {
|
||||
return currentDeck;
|
||||
}
|
||||
public static void setCurrentDeck(String currentDeck0) {
|
||||
if (currentDeck.equals(currentDeck0)) { return; }
|
||||
currentDeck = currentDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getDraftDeck() {
|
||||
return draftDeck;
|
||||
}
|
||||
public static void setDraftDeck(String draftDeck0) {
|
||||
if (draftDeck.equals(draftDeck0)) { return; }
|
||||
draftDeck = draftDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getSealedDeck() {
|
||||
return sealedDeck;
|
||||
}
|
||||
public static void setSealedDeck(String sealedDeck0) {
|
||||
if (sealedDeck.equals(sealedDeck0)) { return; }
|
||||
sealedDeck = sealedDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getCommanderDeck() {
|
||||
return commanderDeck;
|
||||
}
|
||||
public static void setCommanderDeck(String commanderDeck0) {
|
||||
if (commanderDeck.equals(commanderDeck0)) { return; }
|
||||
commanderDeck = commanderDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getTinyLeadersDeck() {
|
||||
return tinyLeadersDeck;
|
||||
}
|
||||
public static void setTinyLeadersDeck(String tinyLeadersDeck0) {
|
||||
if (tinyLeadersDeck.equals(tinyLeadersDeck0)) { return; }
|
||||
tinyLeadersDeck = tinyLeadersDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getPlanarDeck() {
|
||||
return planarDeck;
|
||||
}
|
||||
public static void setPlanarDeck(String planarDeck0) {
|
||||
if (planarDeck.equals(planarDeck0)) { return; }
|
||||
planarDeck = planarDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static String getSchemeDeck() {
|
||||
return schemeDeck;
|
||||
}
|
||||
public static void setSchemeDeck(String schemeDeck0) {
|
||||
if (schemeDeck.equals(schemeDeck0)) { return; }
|
||||
schemeDeck = schemeDeck0;
|
||||
save();
|
||||
}
|
||||
|
||||
public static DeckPreferences getPrefs(DeckProxy deck) {
|
||||
String key = deck.getUniqueKey();
|
||||
DeckPreferences prefs = allPrefs.get(key);
|
||||
if (prefs == null) {
|
||||
prefs = new DeckPreferences();
|
||||
allPrefs.put(key, prefs);
|
||||
}
|
||||
return prefs;
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
allPrefs.clear();
|
||||
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final Document document = builder.parse(new File(ForgeConstants.DECK_PREFS_FILE));
|
||||
|
||||
final Element root = (Element)document.getElementsByTagName("preferences").item(0);
|
||||
currentDeck = root.getAttribute("currentDeck");
|
||||
draftDeck = root.getAttribute("draftDeck");
|
||||
sealedDeck = root.getAttribute("sealedDeck");
|
||||
commanderDeck = root.getAttribute("commanderDeck");
|
||||
tinyLeadersDeck = root.getAttribute("tinyLeadersDeck");
|
||||
planarDeck = root.getAttribute("planarDeck");
|
||||
schemeDeck = root.getAttribute("schemeDeck");
|
||||
|
||||
final NodeList cards = document.getElementsByTagName("deck");
|
||||
for (int i = 0; i < cards.getLength(); i++) {
|
||||
final DeckPreferences prefs = new DeckPreferences();
|
||||
final Element el = (Element)cards.item(i);
|
||||
allPrefs.put(el.getAttribute("key"), prefs);
|
||||
prefs.starCount = XmlUtil.getIntAttribute(el, "stars");
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
//ok if file not found
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void save() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
Element root = document.createElement("preferences");
|
||||
root.setAttribute("type", "decks");
|
||||
root.setAttribute("currentDeck", currentDeck);
|
||||
root.setAttribute("draftDeck", draftDeck);
|
||||
root.setAttribute("sealedDeck", sealedDeck);
|
||||
root.setAttribute("commanderDeck", commanderDeck);
|
||||
root.setAttribute("tinyLeadersDeck", tinyLeadersDeck);
|
||||
root.setAttribute("planarDeck", planarDeck);
|
||||
root.setAttribute("schemeDeck", schemeDeck);
|
||||
document.appendChild(root);
|
||||
|
||||
for (Map.Entry<String, DeckPreferences> entry : allPrefs.entrySet()) {
|
||||
if (entry.getValue().starCount > 0) {
|
||||
Element deck = document.createElement("deck");
|
||||
deck.setAttribute("key", entry.getKey());
|
||||
deck.setAttribute("stars", String.valueOf(entry.getValue().starCount));
|
||||
root.appendChild(deck);
|
||||
}
|
||||
}
|
||||
XmlUtil.saveDocument(document, ForgeConstants.DECK_PREFS_FILE);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private int starCount;
|
||||
|
||||
private DeckPreferences() {
|
||||
}
|
||||
|
||||
public int getStarCount() {
|
||||
return this.starCount;
|
||||
}
|
||||
|
||||
public void setStarCount(int starCount0) {
|
||||
if (this.starCount == starCount0) { return; }
|
||||
this.starCount = starCount0;
|
||||
save();
|
||||
}
|
||||
}
|
||||
@@ -1,57 +1,57 @@
|
||||
package forge.deck.io;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.ai.LobbyPlayerAi;
|
||||
import forge.game.GameOutcome;
|
||||
import forge.game.Match;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class DeckRecords {
|
||||
private static final Map<String, DeckRecords> recordLookup = new HashMap<String, DeckRecords>();
|
||||
|
||||
public static void recordMatchOutcome(Match match) {
|
||||
for (RegisteredPlayer p1 : match.getPlayers()) {
|
||||
for (RegisteredPlayer p2 : match.getPlayers()) {
|
||||
if (p1 != p2) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final List<DeckMatch> matches = new ArrayList<DeckMatch>();
|
||||
|
||||
public void addMatch(Match match, LobbyPlayer player) {
|
||||
matches.add(new DeckMatch(match, player));
|
||||
}
|
||||
|
||||
private static class DeckMatch {
|
||||
private final long timestamp;
|
||||
private final boolean isAi;
|
||||
private final int results;
|
||||
|
||||
private DeckMatch(Match match, LobbyPlayer player) {
|
||||
timestamp = new Date().getTime();
|
||||
isAi = (player instanceof LobbyPlayerAi);
|
||||
|
||||
int results0 = 0;
|
||||
int bit = 1;
|
||||
for (GameOutcome outcome : match.getOutcomes()) {
|
||||
if (outcome.isWinner(player)) {
|
||||
results0 += bit;
|
||||
}
|
||||
else if (outcome.isDraw()) {
|
||||
|
||||
}
|
||||
bit *= 2;
|
||||
}
|
||||
results = results0;
|
||||
}
|
||||
}
|
||||
}
|
||||
package forge.deck.io;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.ai.LobbyPlayerAi;
|
||||
import forge.game.GameOutcome;
|
||||
import forge.game.Match;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class DeckRecords {
|
||||
private static final Map<String, DeckRecords> recordLookup = new HashMap<String, DeckRecords>();
|
||||
|
||||
public static void recordMatchOutcome(Match match) {
|
||||
for (RegisteredPlayer p1 : match.getPlayers()) {
|
||||
for (RegisteredPlayer p2 : match.getPlayers()) {
|
||||
if (p1 != p2) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final List<DeckMatch> matches = new ArrayList<DeckMatch>();
|
||||
|
||||
public void addMatch(Match match, LobbyPlayer player) {
|
||||
matches.add(new DeckMatch(match, player));
|
||||
}
|
||||
|
||||
private static class DeckMatch {
|
||||
private final long timestamp;
|
||||
private final boolean isAi;
|
||||
private final int results;
|
||||
|
||||
private DeckMatch(Match match, LobbyPlayer player) {
|
||||
timestamp = new Date().getTime();
|
||||
isAi = (player instanceof LobbyPlayerAi);
|
||||
|
||||
int results0 = 0;
|
||||
int bit = 1;
|
||||
for (GameOutcome outcome : match.getOutcomes()) {
|
||||
if (outcome.isWinner(player)) {
|
||||
results0 += bit;
|
||||
}
|
||||
else if (outcome.isDraw()) {
|
||||
|
||||
}
|
||||
bit *= 2;
|
||||
}
|
||||
results = results0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,67 +1,67 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.download;
|
||||
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.ImageUtil;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class GuiDownloadPicturesLQ extends GuiDownloadService {
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Download LQ Card Pictures";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Map<String, String> getNeededFiles() {
|
||||
final Map<String, String> downloads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
for (final PaperCard c : FModel.getMagicDb().getCommonCards().getAllCards()) {
|
||||
addDLObject(c, downloads, false);
|
||||
if (ImageUtil.hasBackFacePicture(c)) {
|
||||
addDLObject(c, downloads, true);
|
||||
}
|
||||
}
|
||||
|
||||
for (final PaperCard c : FModel.getMagicDb().getVariantCards().getAllCards()) {
|
||||
addDLObject(c, downloads, false);
|
||||
}
|
||||
|
||||
// Add missing tokens to the list of things to download.
|
||||
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
|
||||
|
||||
return downloads;
|
||||
}
|
||||
|
||||
private static void addDLObject(final PaperCard c, final Map<String, String> downloads, final boolean backFace) {
|
||||
String[] result = ImageUtil.getDownloadUrlAndDestination(ForgeConstants.CACHE_CARD_PICS_DIR, c, backFace);
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
final String urlToDownload = result[0];
|
||||
final String destPath = result[1];
|
||||
if (downloads.containsKey(destPath)) {
|
||||
return;
|
||||
}
|
||||
downloads.put(destPath, urlToDownload);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.download;
|
||||
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.ImageUtil;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class GuiDownloadPicturesLQ extends GuiDownloadService {
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Download LQ Card Pictures";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Map<String, String> getNeededFiles() {
|
||||
final Map<String, String> downloads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
for (final PaperCard c : FModel.getMagicDb().getCommonCards().getAllCards()) {
|
||||
addDLObject(c, downloads, false);
|
||||
if (ImageUtil.hasBackFacePicture(c)) {
|
||||
addDLObject(c, downloads, true);
|
||||
}
|
||||
}
|
||||
|
||||
for (final PaperCard c : FModel.getMagicDb().getVariantCards().getAllCards()) {
|
||||
addDLObject(c, downloads, false);
|
||||
}
|
||||
|
||||
// Add missing tokens to the list of things to download.
|
||||
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
|
||||
|
||||
return downloads;
|
||||
}
|
||||
|
||||
private static void addDLObject(final PaperCard c, final Map<String, String> downloads, final boolean backFace) {
|
||||
String[] result = ImageUtil.getDownloadUrlAndDestination(ForgeConstants.CACHE_CARD_PICS_DIR, c, backFace);
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
final String urlToDownload = result[0];
|
||||
final String destPath = result[1];
|
||||
if (downloads.containsKey(destPath)) {
|
||||
return;
|
||||
}
|
||||
downloads.put(destPath, urlToDownload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.download;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class GuiDownloadPrices extends GuiDownloadService {
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Download Card Prices";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getNeededFiles() {
|
||||
return ImmutableMap.of(ForgeConstants.QUEST_CARD_PRICE_FILE, ForgeConstants.URL_PRICE_DOWNLOAD);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.download;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
public class GuiDownloadPrices extends GuiDownloadService {
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Download Card Prices";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getNeededFiles() {
|
||||
return ImmutableMap.of(ForgeConstants.QUEST_CARD_PRICE_FILE, ForgeConstants.URL_PRICE_DOWNLOAD);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,113 +1,113 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.download;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import forge.StaticData;
|
||||
import forge.card.CardEdition;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.HttpUtil;
|
||||
import forge.util.ImageUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
public class GuiDownloadSetPicturesLQ extends GuiDownloadService {
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Download LQ Set Pictures";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Map<String, String> getNeededFiles() {
|
||||
final Map<String, String> downloads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
final Map<String, String> setMapping = new HashMap<>();
|
||||
final HashSet<String> existingSets = retrieveManifestDirectory();
|
||||
final HashSet<String> missingSets = new HashSet<>();
|
||||
|
||||
for (final PaperCard c : Iterables.concat(FModel.getMagicDb().getCommonCards().getAllCards(), FModel.getMagicDb().getVariantCards().getAllCards())) {
|
||||
final String setCode3 = c.getEdition();
|
||||
|
||||
if (!setMapping.containsKey(setCode3)) {
|
||||
setMapping.put(setCode3, StaticData.instance().getEditions().getCode2ByCode(setCode3));
|
||||
}
|
||||
final String setCode2 = setMapping.get(setCode3);
|
||||
|
||||
if (StringUtils.isBlank(setCode3) || CardEdition.UNKNOWN.getCode().equals(setCode3)) {
|
||||
// we don't want cards from unknown sets
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(existingSets.contains(setCode3) || existingSets.contains(setCode2))) {
|
||||
// If set doesn't exist on server, don't try to download cards for it
|
||||
if (!missingSets.contains(setCode3)) {
|
||||
missingSets.add(setCode3);
|
||||
System.out.println(setCode3 + " not found on server. Ignoring downloads for this set.");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
addDLObject(ImageUtil.getDownloadUrl(c, false), ImageUtil.getImageKey(c, false, true), downloads);
|
||||
|
||||
if (ImageUtil.hasBackFacePicture(c)) {
|
||||
addDLObject(ImageUtil.getDownloadUrl(c, true), ImageUtil.getImageKey(c, true, true), downloads);
|
||||
}
|
||||
}
|
||||
|
||||
// Add missing tokens to the list of things to download.
|
||||
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
|
||||
|
||||
return downloads;
|
||||
}
|
||||
|
||||
private static void addDLObject(final String urlPath, final String filename, final Map<String, String> downloads) {
|
||||
final File destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR, filename + ".jpg");
|
||||
// System.out.println(filename);
|
||||
if (!destFile.exists()) {
|
||||
downloads.put(destFile.getAbsolutePath(), ForgeConstants.URL_PIC_DOWNLOAD + urlPath);
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<String> retrieveManifestDirectory() {
|
||||
String manifestUrl = ForgeConstants.URL_PIC_DOWNLOAD;
|
||||
HashSet<String> existingSets = new HashSet<>();
|
||||
|
||||
String response = HttpUtil.getURL(manifestUrl);
|
||||
|
||||
if (response == null) return null;
|
||||
|
||||
String[] strings = response.split("<a href=\"");
|
||||
|
||||
for (String s : strings) {
|
||||
int idx = s.indexOf('/');
|
||||
if (!Character.isLetterOrDigit(s.charAt(0)) || idx > 4 || idx == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String set = s.substring(0, idx);
|
||||
existingSets.add(set);
|
||||
}
|
||||
|
||||
return existingSets;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.download;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import forge.StaticData;
|
||||
import forge.card.CardEdition;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.HttpUtil;
|
||||
import forge.util.ImageUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
public class GuiDownloadSetPicturesLQ extends GuiDownloadService {
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Download LQ Set Pictures";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Map<String, String> getNeededFiles() {
|
||||
final Map<String, String> downloads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
final Map<String, String> setMapping = new HashMap<>();
|
||||
final HashSet<String> existingSets = retrieveManifestDirectory();
|
||||
final HashSet<String> missingSets = new HashSet<>();
|
||||
|
||||
for (final PaperCard c : Iterables.concat(FModel.getMagicDb().getCommonCards().getAllCards(), FModel.getMagicDb().getVariantCards().getAllCards())) {
|
||||
final String setCode3 = c.getEdition();
|
||||
|
||||
if (!setMapping.containsKey(setCode3)) {
|
||||
setMapping.put(setCode3, StaticData.instance().getEditions().getCode2ByCode(setCode3));
|
||||
}
|
||||
final String setCode2 = setMapping.get(setCode3);
|
||||
|
||||
if (StringUtils.isBlank(setCode3) || CardEdition.UNKNOWN.getCode().equals(setCode3)) {
|
||||
// we don't want cards from unknown sets
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(existingSets.contains(setCode3) || existingSets.contains(setCode2))) {
|
||||
// If set doesn't exist on server, don't try to download cards for it
|
||||
if (!missingSets.contains(setCode3)) {
|
||||
missingSets.add(setCode3);
|
||||
System.out.println(setCode3 + " not found on server. Ignoring downloads for this set.");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
addDLObject(ImageUtil.getDownloadUrl(c, false), ImageUtil.getImageKey(c, false, true), downloads);
|
||||
|
||||
if (ImageUtil.hasBackFacePicture(c)) {
|
||||
addDLObject(ImageUtil.getDownloadUrl(c, true), ImageUtil.getImageKey(c, true, true), downloads);
|
||||
}
|
||||
}
|
||||
|
||||
// Add missing tokens to the list of things to download.
|
||||
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
|
||||
|
||||
return downloads;
|
||||
}
|
||||
|
||||
private static void addDLObject(final String urlPath, final String filename, final Map<String, String> downloads) {
|
||||
final File destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR, filename + ".jpg");
|
||||
// System.out.println(filename);
|
||||
if (!destFile.exists()) {
|
||||
downloads.put(destFile.getAbsolutePath(), ForgeConstants.URL_PIC_DOWNLOAD + urlPath);
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<String> retrieveManifestDirectory() {
|
||||
String manifestUrl = ForgeConstants.URL_PIC_DOWNLOAD;
|
||||
HashSet<String> existingSets = new HashSet<>();
|
||||
|
||||
String response = HttpUtil.getURL(manifestUrl);
|
||||
|
||||
if (response == null) return null;
|
||||
|
||||
String[] strings = response.split("<a href=\"");
|
||||
|
||||
for (String s : strings) {
|
||||
int idx = s.indexOf('/');
|
||||
if (!Character.isLetterOrDigit(s.charAt(0)) || idx > 4 || idx == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String set = s.substring(0, idx);
|
||||
existingSets.add(set);
|
||||
}
|
||||
|
||||
return existingSets;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,224 +1,224 @@
|
||||
package forge.download;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.GuiBase;
|
||||
import forge.interfaces.IProgressBar;
|
||||
import forge.util.FileUtil;
|
||||
|
||||
public class GuiDownloadZipService extends GuiDownloadService {
|
||||
private final String name, desc, sourceUrl, destFolder, deleteFolder;
|
||||
private int filesExtracted;
|
||||
|
||||
public GuiDownloadZipService(final String name0, final String desc0, final String sourceUrl0, final String destFolder0, final String deleteFolder0, final IProgressBar progressBar0) {
|
||||
name = name0;
|
||||
desc = desc0;
|
||||
sourceUrl = sourceUrl0;
|
||||
destFolder = destFolder0;
|
||||
deleteFolder = deleteFolder0;
|
||||
progressBar = progressBar0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Download " + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getStartOverrideDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Map<String, String> getNeededFiles() {
|
||||
final Map<String, String> files = new HashMap<String, String>();
|
||||
files.put("_", "_");
|
||||
return files; //not needed by zip service, so just return map of size 1
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
downloadAndUnzip();
|
||||
if (!cancel) {
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.setDescription(filesExtracted + " " + desc + " extracted");
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadAndUnzip() {
|
||||
filesExtracted = 0;
|
||||
String zipFilename = download("temp.zip");
|
||||
if (zipFilename == null) { return; }
|
||||
|
||||
//if assets.zip downloaded successfully, unzip into destination folder
|
||||
try {
|
||||
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while unzipping
|
||||
|
||||
if (deleteFolder != null) {
|
||||
final File deleteDir = new File(deleteFolder);
|
||||
if (deleteDir.exists()) {
|
||||
//attempt to delete previous res directory if to be rebuilt
|
||||
progressBar.reset();
|
||||
progressBar.setDescription("Deleting old " + desc + "...");
|
||||
if (deleteFolder.equals(destFolder)) { //move zip file to prevent deleting it
|
||||
final String oldZipFilename = zipFilename;
|
||||
zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip";
|
||||
Files.move(new File(oldZipFilename), new File(zipFilename));
|
||||
}
|
||||
FileUtil.deleteDirectory(deleteDir);
|
||||
}
|
||||
}
|
||||
|
||||
final ZipFile zipFile = new ZipFile(zipFilename);
|
||||
final Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
|
||||
progressBar.reset();
|
||||
progressBar.setPercentMode(true);
|
||||
progressBar.setDescription("Extracting " + desc);
|
||||
progressBar.setMaximum(zipFile.size());
|
||||
|
||||
FileUtil.ensureDirectoryExists(destFolder);
|
||||
|
||||
int count = 0;
|
||||
int failedCount = 0;
|
||||
while (entries.hasMoreElements()) {
|
||||
if (cancel) { break; }
|
||||
|
||||
try {
|
||||
final ZipEntry entry = entries.nextElement();
|
||||
|
||||
final String path = destFolder + entry.getName();
|
||||
if (entry.isDirectory()) {
|
||||
new File(path).mkdir();
|
||||
progressBar.setValue(++count);
|
||||
continue;
|
||||
}
|
||||
copyInputStream(zipFile.getInputStream(entry), path);
|
||||
progressBar.setValue(++count);
|
||||
filesExtracted++;
|
||||
}
|
||||
catch (final Exception e) { //don't quit out completely if an entry is not UTF-8
|
||||
progressBar.setValue(++count);
|
||||
failedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (failedCount > 0) {
|
||||
Log.error("Downloading " + desc, failedCount + " " + desc + " could not be extracted");
|
||||
}
|
||||
|
||||
zipFile.close();
|
||||
new File(zipFilename).delete();
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
GuiBase.getInterface().preventSystemSleep(false);
|
||||
}
|
||||
}
|
||||
|
||||
public String download(final String filename) {
|
||||
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while downloading
|
||||
|
||||
progressBar.reset();
|
||||
progressBar.setPercentMode(true);
|
||||
progressBar.setDescription("Downloading " + desc);
|
||||
|
||||
try {
|
||||
final URL url = new URL(sourceUrl);
|
||||
final HttpURLConnection conn = (HttpURLConnection) url.openConnection(getProxy());
|
||||
|
||||
if (url.getPath().endsWith(".php")) {
|
||||
//ensure file can be downloaded if returned from PHP script
|
||||
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)");
|
||||
}
|
||||
|
||||
conn.connect();
|
||||
|
||||
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final long contentLength = conn.getContentLength();
|
||||
if (contentLength == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
progressBar.setMaximum(100);
|
||||
|
||||
// input stream to read file - with 8k buffer
|
||||
final InputStream input = new BufferedInputStream(conn.getInputStream(), 8192);
|
||||
|
||||
FileUtil.ensureDirectoryExists(destFolder);
|
||||
|
||||
// output stream to write file
|
||||
final String destFile = destFolder + filename;
|
||||
final OutputStream output = new FileOutputStream(destFile);
|
||||
|
||||
int count;
|
||||
long total = 0;
|
||||
final byte data[] = new byte[1024];
|
||||
|
||||
while ((count = input.read(data)) != -1) {
|
||||
if (cancel) { break; }
|
||||
|
||||
total += count;
|
||||
progressBar.setValue((int)(100 * total / contentLength));
|
||||
output.write(data, 0, count);
|
||||
}
|
||||
|
||||
output.flush();
|
||||
output.close();
|
||||
input.close();
|
||||
|
||||
if (cancel) {
|
||||
new File(destFile).delete();
|
||||
return null;
|
||||
}
|
||||
return destFile;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
Log.error("Downloading " + desc, "Error downloading " + desc, ex);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
GuiBase.getInterface().preventSystemSleep(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected void copyInputStream(final InputStream in, final String outPath) throws IOException{
|
||||
final byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
final BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outPath));
|
||||
|
||||
while((len = in.read(buffer)) >= 0) {
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
package forge.download;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.GuiBase;
|
||||
import forge.interfaces.IProgressBar;
|
||||
import forge.util.FileUtil;
|
||||
|
||||
public class GuiDownloadZipService extends GuiDownloadService {
|
||||
private final String name, desc, sourceUrl, destFolder, deleteFolder;
|
||||
private int filesExtracted;
|
||||
|
||||
public GuiDownloadZipService(final String name0, final String desc0, final String sourceUrl0, final String destFolder0, final String deleteFolder0, final IProgressBar progressBar0) {
|
||||
name = name0;
|
||||
desc = desc0;
|
||||
sourceUrl = sourceUrl0;
|
||||
destFolder = destFolder0;
|
||||
deleteFolder = deleteFolder0;
|
||||
progressBar = progressBar0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Download " + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getStartOverrideDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Map<String, String> getNeededFiles() {
|
||||
final Map<String, String> files = new HashMap<String, String>();
|
||||
files.put("_", "_");
|
||||
return files; //not needed by zip service, so just return map of size 1
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
downloadAndUnzip();
|
||||
if (!cancel) {
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.setDescription(filesExtracted + " " + desc + " extracted");
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadAndUnzip() {
|
||||
filesExtracted = 0;
|
||||
String zipFilename = download("temp.zip");
|
||||
if (zipFilename == null) { return; }
|
||||
|
||||
//if assets.zip downloaded successfully, unzip into destination folder
|
||||
try {
|
||||
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while unzipping
|
||||
|
||||
if (deleteFolder != null) {
|
||||
final File deleteDir = new File(deleteFolder);
|
||||
if (deleteDir.exists()) {
|
||||
//attempt to delete previous res directory if to be rebuilt
|
||||
progressBar.reset();
|
||||
progressBar.setDescription("Deleting old " + desc + "...");
|
||||
if (deleteFolder.equals(destFolder)) { //move zip file to prevent deleting it
|
||||
final String oldZipFilename = zipFilename;
|
||||
zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip";
|
||||
Files.move(new File(oldZipFilename), new File(zipFilename));
|
||||
}
|
||||
FileUtil.deleteDirectory(deleteDir);
|
||||
}
|
||||
}
|
||||
|
||||
final ZipFile zipFile = new ZipFile(zipFilename);
|
||||
final Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
|
||||
progressBar.reset();
|
||||
progressBar.setPercentMode(true);
|
||||
progressBar.setDescription("Extracting " + desc);
|
||||
progressBar.setMaximum(zipFile.size());
|
||||
|
||||
FileUtil.ensureDirectoryExists(destFolder);
|
||||
|
||||
int count = 0;
|
||||
int failedCount = 0;
|
||||
while (entries.hasMoreElements()) {
|
||||
if (cancel) { break; }
|
||||
|
||||
try {
|
||||
final ZipEntry entry = entries.nextElement();
|
||||
|
||||
final String path = destFolder + entry.getName();
|
||||
if (entry.isDirectory()) {
|
||||
new File(path).mkdir();
|
||||
progressBar.setValue(++count);
|
||||
continue;
|
||||
}
|
||||
copyInputStream(zipFile.getInputStream(entry), path);
|
||||
progressBar.setValue(++count);
|
||||
filesExtracted++;
|
||||
}
|
||||
catch (final Exception e) { //don't quit out completely if an entry is not UTF-8
|
||||
progressBar.setValue(++count);
|
||||
failedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (failedCount > 0) {
|
||||
Log.error("Downloading " + desc, failedCount + " " + desc + " could not be extracted");
|
||||
}
|
||||
|
||||
zipFile.close();
|
||||
new File(zipFilename).delete();
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
GuiBase.getInterface().preventSystemSleep(false);
|
||||
}
|
||||
}
|
||||
|
||||
public String download(final String filename) {
|
||||
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while downloading
|
||||
|
||||
progressBar.reset();
|
||||
progressBar.setPercentMode(true);
|
||||
progressBar.setDescription("Downloading " + desc);
|
||||
|
||||
try {
|
||||
final URL url = new URL(sourceUrl);
|
||||
final HttpURLConnection conn = (HttpURLConnection) url.openConnection(getProxy());
|
||||
|
||||
if (url.getPath().endsWith(".php")) {
|
||||
//ensure file can be downloaded if returned from PHP script
|
||||
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT)");
|
||||
}
|
||||
|
||||
conn.connect();
|
||||
|
||||
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final long contentLength = conn.getContentLength();
|
||||
if (contentLength == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
progressBar.setMaximum(100);
|
||||
|
||||
// input stream to read file - with 8k buffer
|
||||
final InputStream input = new BufferedInputStream(conn.getInputStream(), 8192);
|
||||
|
||||
FileUtil.ensureDirectoryExists(destFolder);
|
||||
|
||||
// output stream to write file
|
||||
final String destFile = destFolder + filename;
|
||||
final OutputStream output = new FileOutputStream(destFile);
|
||||
|
||||
int count;
|
||||
long total = 0;
|
||||
final byte data[] = new byte[1024];
|
||||
|
||||
while ((count = input.read(data)) != -1) {
|
||||
if (cancel) { break; }
|
||||
|
||||
total += count;
|
||||
progressBar.setValue((int)(100 * total / contentLength));
|
||||
output.write(data, 0, count);
|
||||
}
|
||||
|
||||
output.flush();
|
||||
output.close();
|
||||
input.close();
|
||||
|
||||
if (cancel) {
|
||||
new File(destFile).delete();
|
||||
return null;
|
||||
}
|
||||
return destFile;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
Log.error("Downloading " + desc, "Error downloading " + desc, ex);
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
GuiBase.getInterface().preventSystemSleep(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected void copyInputStream(final InputStream in, final String outPath) throws IOException{
|
||||
final byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
final BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outPath));
|
||||
|
||||
while((len = in.read(buffer)) >= 0) {
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,195 +1,195 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.error;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.GuiBase;
|
||||
import forge.util.BuildInfo;
|
||||
import forge.util.gui.SOptionPane;
|
||||
|
||||
/**
|
||||
* The class ErrorViewer. Enables showing and saving error messages that
|
||||
* occurred in forge.
|
||||
*
|
||||
* @author Clemens Koza
|
||||
* @version V1.0 02.08.2009
|
||||
*/
|
||||
public class BugReporter {
|
||||
private static final int STACK_OVERFLOW_MAX_MESSAGE_LEN = 16 * 1024;
|
||||
|
||||
public static final String REPORT = "Report";
|
||||
public static final String SAVE = "Save";
|
||||
public static final String CONTINUE = "Continue";
|
||||
public static final String EXIT = "Exit";
|
||||
|
||||
public static final String HELP_TEXT = String.format(
|
||||
"A template for a post in the bug reports forum topic is shown below. Just select '%s' "
|
||||
+ "and the template will be copied to your system clipboard and the forum page will open in your browser. "
|
||||
+ "Then all you have to do is paste the text into a forum post and edit the description line.", REPORT);
|
||||
public static final String HELP_URL_LABEL =
|
||||
"Reporting bugs in Forge is very important. We sincerely thank you for your time."
|
||||
+ " For help writing a solid bug report, please see:";
|
||||
public static final String HELP_URL =
|
||||
"http://www.slightlymagic.net/forum/viewtopic.php?f=26&p=109925#p109925";
|
||||
private static final String FORUM_URL;
|
||||
|
||||
static {
|
||||
if (BuildInfo.isDevelopmentVersion()) {
|
||||
FORUM_URL = "http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=6333&start=54564487645#bottom";
|
||||
} else {
|
||||
FORUM_URL = "http://www.slightlymagic.net/forum/viewforum.php?f=26";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows exception information in a format ready to post to the forum as a
|
||||
* crash report. Uses the exception's message as the reason if message is
|
||||
* null.
|
||||
*/
|
||||
public static void reportException(final Throwable ex, final String message) {
|
||||
if (ex == null) {
|
||||
return;
|
||||
}
|
||||
if (message != null) {
|
||||
System.err.printf("%s > %s%n", FThreads.debugGetCurrThreadId(), message);
|
||||
}
|
||||
System.err.print(FThreads.debugGetCurrThreadId() + " > ");
|
||||
ex.printStackTrace();
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Description: [describe what you were doing when the crash occurred]\n\n");
|
||||
buildSpoilerHeader(sb, ex.getClass().getSimpleName());
|
||||
sb.append("\n\n");
|
||||
if (null != message && !message.isEmpty()) {
|
||||
sb.append(FThreads.debugGetCurrThreadId()).append(" > ").append(message).append("\n");
|
||||
}
|
||||
|
||||
final StringWriter sw = new StringWriter();
|
||||
final PrintWriter pw = new PrintWriter(sw);
|
||||
ex.printStackTrace(pw);
|
||||
|
||||
final String swStr = sw.toString();
|
||||
if (ex instanceof StackOverflowError && swStr.length() >= STACK_OVERFLOW_MAX_MESSAGE_LEN) {
|
||||
// most likely a cycle. only take first portion so the message
|
||||
// doesn't grow too large to post
|
||||
sb.append(swStr, 0, STACK_OVERFLOW_MAX_MESSAGE_LEN);
|
||||
sb.append("\n... (truncated)");
|
||||
}
|
||||
else {
|
||||
sb.append(swStr);
|
||||
}
|
||||
|
||||
buildSpoilerFooter(sb);
|
||||
|
||||
GuiBase.getInterface().showBugReportDialog("Report a crash", sb.toString(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for reportException(ex, null).
|
||||
*/
|
||||
public static void reportException(final Throwable ex) {
|
||||
reportException(ex, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for reportException(ex, String.format(format, args)).
|
||||
*/
|
||||
public static void reportException(final Throwable ex, final String format, final Object... args) {
|
||||
reportException(ex, String.format(format, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a forum post template for reporting a bug.
|
||||
*/
|
||||
public static void reportBug(final String details) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Description: [describe the problem]\n\n");
|
||||
buildSpoilerHeader(sb, "General bug report");
|
||||
if (null != details && !details.isEmpty()) {
|
||||
sb.append("\n\n");
|
||||
sb.append(details);
|
||||
}
|
||||
buildSpoilerFooter(sb);
|
||||
|
||||
GuiBase.getInterface().showBugReportDialog("Report a bug", sb.toString(), false);
|
||||
}
|
||||
|
||||
private static StringBuilder buildSpoilerHeader(final StringBuilder sb, final String reportTitle) {
|
||||
sb.append("[spoiler=").append(reportTitle).append("][code]");
|
||||
sb.append("\nForge Version: ").append(GuiBase.getInterface().getCurrentVersion());
|
||||
sb.append("\nOperating System: ").append(System.getProperty("os.name"))
|
||||
.append(" ").append(System.getProperty("os.version"))
|
||||
.append(" ").append(System.getProperty("os.arch"));
|
||||
sb.append("\nJava Version: ").append(System.getProperty("java.version"))
|
||||
.append(" ").append(System.getProperty("java.vendor"));
|
||||
return sb;
|
||||
}
|
||||
|
||||
private static StringBuilder buildSpoilerFooter(final StringBuilder sb) {
|
||||
sb.append("[/code][/spoiler]");
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static void copyAndGoToForums(final String text) {
|
||||
try {
|
||||
// copy text to clipboard
|
||||
GuiBase.getInterface().copyToClipboard(text);
|
||||
GuiBase.getInterface().browseToUrl(FORUM_URL);
|
||||
} catch (final Exception ex) {
|
||||
SOptionPane.showMessageDialog("Sorry, a problem occurred while opening the forum in your default browser.",
|
||||
"A problem occurred", SOptionPane.ERROR_ICON);
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveToFile(final String text) {
|
||||
File f;
|
||||
final long curTime = System.currentTimeMillis();
|
||||
for (int i = 0;; i++) {
|
||||
final String name = String.format("%TF-%02d.txt", curTime, i);
|
||||
f = new File(name);
|
||||
if (!f.exists()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
f = GuiBase.getInterface().getSaveFile(f);
|
||||
|
||||
try {
|
||||
final BufferedWriter bw = new BufferedWriter(new FileWriter(f));
|
||||
bw.write(text);
|
||||
bw.close();
|
||||
}
|
||||
catch (final IOException ex) {
|
||||
SOptionPane.showMessageDialog("There was an error during saving. Sorry!\n" + ex,
|
||||
"Error saving file", SOptionPane.ERROR_ICON);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private BugReporter() {
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.error;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.GuiBase;
|
||||
import forge.util.BuildInfo;
|
||||
import forge.util.gui.SOptionPane;
|
||||
|
||||
/**
|
||||
* The class ErrorViewer. Enables showing and saving error messages that
|
||||
* occurred in forge.
|
||||
*
|
||||
* @author Clemens Koza
|
||||
* @version V1.0 02.08.2009
|
||||
*/
|
||||
public class BugReporter {
|
||||
private static final int STACK_OVERFLOW_MAX_MESSAGE_LEN = 16 * 1024;
|
||||
|
||||
public static final String REPORT = "Report";
|
||||
public static final String SAVE = "Save";
|
||||
public static final String CONTINUE = "Continue";
|
||||
public static final String EXIT = "Exit";
|
||||
|
||||
public static final String HELP_TEXT = String.format(
|
||||
"A template for a post in the bug reports forum topic is shown below. Just select '%s' "
|
||||
+ "and the template will be copied to your system clipboard and the forum page will open in your browser. "
|
||||
+ "Then all you have to do is paste the text into a forum post and edit the description line.", REPORT);
|
||||
public static final String HELP_URL_LABEL =
|
||||
"Reporting bugs in Forge is very important. We sincerely thank you for your time."
|
||||
+ " For help writing a solid bug report, please see:";
|
||||
public static final String HELP_URL =
|
||||
"http://www.slightlymagic.net/forum/viewtopic.php?f=26&p=109925#p109925";
|
||||
private static final String FORUM_URL;
|
||||
|
||||
static {
|
||||
if (BuildInfo.isDevelopmentVersion()) {
|
||||
FORUM_URL = "http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=6333&start=54564487645#bottom";
|
||||
} else {
|
||||
FORUM_URL = "http://www.slightlymagic.net/forum/viewforum.php?f=26";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows exception information in a format ready to post to the forum as a
|
||||
* crash report. Uses the exception's message as the reason if message is
|
||||
* null.
|
||||
*/
|
||||
public static void reportException(final Throwable ex, final String message) {
|
||||
if (ex == null) {
|
||||
return;
|
||||
}
|
||||
if (message != null) {
|
||||
System.err.printf("%s > %s%n", FThreads.debugGetCurrThreadId(), message);
|
||||
}
|
||||
System.err.print(FThreads.debugGetCurrThreadId() + " > ");
|
||||
ex.printStackTrace();
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Description: [describe what you were doing when the crash occurred]\n\n");
|
||||
buildSpoilerHeader(sb, ex.getClass().getSimpleName());
|
||||
sb.append("\n\n");
|
||||
if (null != message && !message.isEmpty()) {
|
||||
sb.append(FThreads.debugGetCurrThreadId()).append(" > ").append(message).append("\n");
|
||||
}
|
||||
|
||||
final StringWriter sw = new StringWriter();
|
||||
final PrintWriter pw = new PrintWriter(sw);
|
||||
ex.printStackTrace(pw);
|
||||
|
||||
final String swStr = sw.toString();
|
||||
if (ex instanceof StackOverflowError && swStr.length() >= STACK_OVERFLOW_MAX_MESSAGE_LEN) {
|
||||
// most likely a cycle. only take first portion so the message
|
||||
// doesn't grow too large to post
|
||||
sb.append(swStr, 0, STACK_OVERFLOW_MAX_MESSAGE_LEN);
|
||||
sb.append("\n... (truncated)");
|
||||
}
|
||||
else {
|
||||
sb.append(swStr);
|
||||
}
|
||||
|
||||
buildSpoilerFooter(sb);
|
||||
|
||||
GuiBase.getInterface().showBugReportDialog("Report a crash", sb.toString(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for reportException(ex, null).
|
||||
*/
|
||||
public static void reportException(final Throwable ex) {
|
||||
reportException(ex, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for reportException(ex, String.format(format, args)).
|
||||
*/
|
||||
public static void reportException(final Throwable ex, final String format, final Object... args) {
|
||||
reportException(ex, String.format(format, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a forum post template for reporting a bug.
|
||||
*/
|
||||
public static void reportBug(final String details) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Description: [describe the problem]\n\n");
|
||||
buildSpoilerHeader(sb, "General bug report");
|
||||
if (null != details && !details.isEmpty()) {
|
||||
sb.append("\n\n");
|
||||
sb.append(details);
|
||||
}
|
||||
buildSpoilerFooter(sb);
|
||||
|
||||
GuiBase.getInterface().showBugReportDialog("Report a bug", sb.toString(), false);
|
||||
}
|
||||
|
||||
private static StringBuilder buildSpoilerHeader(final StringBuilder sb, final String reportTitle) {
|
||||
sb.append("[spoiler=").append(reportTitle).append("][code]");
|
||||
sb.append("\nForge Version: ").append(GuiBase.getInterface().getCurrentVersion());
|
||||
sb.append("\nOperating System: ").append(System.getProperty("os.name"))
|
||||
.append(" ").append(System.getProperty("os.version"))
|
||||
.append(" ").append(System.getProperty("os.arch"));
|
||||
sb.append("\nJava Version: ").append(System.getProperty("java.version"))
|
||||
.append(" ").append(System.getProperty("java.vendor"));
|
||||
return sb;
|
||||
}
|
||||
|
||||
private static StringBuilder buildSpoilerFooter(final StringBuilder sb) {
|
||||
sb.append("[/code][/spoiler]");
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static void copyAndGoToForums(final String text) {
|
||||
try {
|
||||
// copy text to clipboard
|
||||
GuiBase.getInterface().copyToClipboard(text);
|
||||
GuiBase.getInterface().browseToUrl(FORUM_URL);
|
||||
} catch (final Exception ex) {
|
||||
SOptionPane.showMessageDialog("Sorry, a problem occurred while opening the forum in your default browser.",
|
||||
"A problem occurred", SOptionPane.ERROR_ICON);
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveToFile(final String text) {
|
||||
File f;
|
||||
final long curTime = System.currentTimeMillis();
|
||||
for (int i = 0;; i++) {
|
||||
final String name = String.format("%TF-%02d.txt", curTime, i);
|
||||
f = new File(name);
|
||||
if (!f.exists()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
f = GuiBase.getInterface().getSaveFile(f);
|
||||
|
||||
try {
|
||||
final BufferedWriter bw = new BufferedWriter(new FileWriter(f));
|
||||
bw.write(text);
|
||||
bw.close();
|
||||
}
|
||||
catch (final IOException ex) {
|
||||
SOptionPane.showMessageDialog("There was an error during saving. Sorry!\n" + ex,
|
||||
"Error saving file", SOptionPane.ERROR_ICON);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation.
|
||||
*/
|
||||
private BugReporter() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package forge.events;
|
||||
|
||||
public interface IUiEventVisitor<T> {
|
||||
T visit(UiEventBlockerAssigned event);
|
||||
T visit(UiEventAttackerDeclared event);
|
||||
T visit(UiEventNextGameDecision event);
|
||||
package forge.events;
|
||||
|
||||
public interface IUiEventVisitor<T> {
|
||||
T visit(UiEventBlockerAssigned event);
|
||||
T visit(UiEventAttackerDeclared event);
|
||||
T visit(UiEventNextGameDecision event);
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package forge.events;
|
||||
|
||||
import forge.game.event.Event;
|
||||
|
||||
public abstract class UiEvent extends Event {
|
||||
|
||||
public abstract <T> T visit(IUiEventVisitor<T> visitor);
|
||||
package forge.events;
|
||||
|
||||
import forge.game.event.Event;
|
||||
|
||||
public abstract class UiEvent extends Event {
|
||||
|
||||
public abstract <T> T visit(IUiEventVisitor<T> visitor);
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
package forge.events;
|
||||
|
||||
import forge.game.GameEntityView;
|
||||
import forge.game.card.CardView;
|
||||
|
||||
public class UiEventAttackerDeclared extends UiEvent {
|
||||
public final CardView attacker;
|
||||
public final GameEntityView defender;
|
||||
|
||||
public UiEventAttackerDeclared(final CardView card, final GameEntityView currentDefender) {
|
||||
attacker = card;
|
||||
defender = currentDefender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T visit(final IUiEventVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return attacker.toString() + ( defender == null ? " removed from combat" : " declared to attack " + defender );
|
||||
}
|
||||
}
|
||||
package forge.events;
|
||||
|
||||
import forge.game.GameEntityView;
|
||||
import forge.game.card.CardView;
|
||||
|
||||
public class UiEventAttackerDeclared extends UiEvent {
|
||||
public final CardView attacker;
|
||||
public final GameEntityView defender;
|
||||
|
||||
public UiEventAttackerDeclared(final CardView card, final GameEntityView currentDefender) {
|
||||
attacker = card;
|
||||
defender = currentDefender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T visit(final IUiEventVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return attacker.toString() + ( defender == null ? " removed from combat" : " declared to attack " + defender );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package forge.events;
|
||||
|
||||
import forge.game.card.CardView;
|
||||
|
||||
public class UiEventBlockerAssigned extends UiEvent {
|
||||
public final CardView blocker;
|
||||
public final CardView attackerBeingBlocked;
|
||||
|
||||
public UiEventBlockerAssigned(final CardView card, final CardView currentAttacker) {
|
||||
blocker = card;
|
||||
attackerBeingBlocked = currentAttacker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T visit(final IUiEventVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
package forge.events;
|
||||
|
||||
import forge.game.card.CardView;
|
||||
|
||||
public class UiEventBlockerAssigned extends UiEvent {
|
||||
public final CardView blocker;
|
||||
public final CardView attackerBeingBlocked;
|
||||
|
||||
public UiEventBlockerAssigned(final CardView card, final CardView currentAttacker) {
|
||||
blocker = card;
|
||||
attackerBeingBlocked = currentAttacker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T visit(final IUiEventVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
}
|
||||
@@ -1,155 +1,155 @@
|
||||
package forge.gauntlet;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.deck.Deck;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
import forge.match.HostedMatch;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Handles layout saving and loading.
|
||||
*
|
||||
* <br><br><i>(S at beginning of class name denotes a static factory.)</i>
|
||||
*/
|
||||
public final class GauntletData {
|
||||
@XStreamOmitField
|
||||
private String name; // set based on the the filename on load
|
||||
|
||||
private transient HostedMatch hostedMatch = null;
|
||||
|
||||
private int completed;
|
||||
private String timestamp;
|
||||
private List<String> eventRecords = new ArrayList<String>();
|
||||
private List<String> eventNames = new ArrayList<String>();
|
||||
private Deck userDeck;
|
||||
private List<Deck> decks;
|
||||
|
||||
public GauntletData() {
|
||||
}
|
||||
|
||||
public void setName(String name0) {
|
||||
name = name0;
|
||||
}
|
||||
|
||||
public void rename(final String newName) {
|
||||
File newpath = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, newName + ".dat");
|
||||
File oldpath = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, name + ".dat");
|
||||
oldpath.renameTo(newpath);
|
||||
|
||||
name = newName;
|
||||
GauntletIO.saveGauntlet(this);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
if (name.startsWith(GauntletIO.PREFIX_LOCKED)) { //trim locked prefix if needed
|
||||
return name.substring(GauntletIO.PREFIX_LOCKED.length());
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public void stamp() {
|
||||
final DateFormat dateFormat = new SimpleDateFormat("MM-dd-yy, H:m");
|
||||
timestamp = dateFormat.format(new Date()).toString();
|
||||
}
|
||||
|
||||
/** Resets a gauntlet data to an unplayed state, then stamps and saves. */
|
||||
public void reset() {
|
||||
completed = 0;
|
||||
stamp();
|
||||
eventRecords.clear();
|
||||
|
||||
for (int i = 0; i < decks.size(); i++) {
|
||||
eventRecords.add("");
|
||||
}
|
||||
|
||||
GauntletIO.saveGauntlet(this);
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setCompleted(final int i0) {
|
||||
completed = i0;
|
||||
}
|
||||
|
||||
public int getCompleted() {
|
||||
return completed;
|
||||
}
|
||||
|
||||
public void setUserDeck(final Deck d0) {
|
||||
userDeck = d0;
|
||||
}
|
||||
|
||||
public Deck getUserDeck() {
|
||||
return userDeck;
|
||||
}
|
||||
|
||||
public List<String> getDeckNames() {
|
||||
final List<String> names = new ArrayList<String>();
|
||||
for (final Deck d : decks) { names.add(d.getName()); }
|
||||
return names;
|
||||
}
|
||||
|
||||
public void setEventRecords(final List<String> records0) {
|
||||
eventRecords = records0;
|
||||
}
|
||||
|
||||
public List<String> getEventRecords() {
|
||||
return eventRecords;
|
||||
}
|
||||
|
||||
public void setEventNames(final List<String> names0) {
|
||||
eventNames = names0;
|
||||
}
|
||||
|
||||
public List<String> getEventNames() {
|
||||
return eventNames;
|
||||
}
|
||||
|
||||
public void setDecks(final List<Deck> decks0) {
|
||||
decks = decks0;
|
||||
}
|
||||
|
||||
public List<Deck> getDecks() {
|
||||
return decks;
|
||||
}
|
||||
|
||||
public void startRound(final List<RegisteredPlayer> players, final RegisteredPlayer human) {
|
||||
hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.startMatch(GameType.Gauntlet, null, players, human, GuiBase.getInterface().getNewGuiGame());
|
||||
}
|
||||
|
||||
public void nextRound(final List<RegisteredPlayer> players, final RegisteredPlayer human) {
|
||||
if (hostedMatch == null) {
|
||||
throw new IllegalStateException("Cannot advance round when no match has been hosted.");
|
||||
}
|
||||
|
||||
hostedMatch.endCurrentGame();
|
||||
startRound(players, human);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String str = getDisplayName();
|
||||
if (decks != null) {
|
||||
str += " (" + decks.size() + " opponents)";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
package forge.gauntlet;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.deck.Deck;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
import forge.match.HostedMatch;
|
||||
import forge.properties.ForgeConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Handles layout saving and loading.
|
||||
*
|
||||
* <br><br><i>(S at beginning of class name denotes a static factory.)</i>
|
||||
*/
|
||||
public final class GauntletData {
|
||||
@XStreamOmitField
|
||||
private String name; // set based on the the filename on load
|
||||
|
||||
private transient HostedMatch hostedMatch = null;
|
||||
|
||||
private int completed;
|
||||
private String timestamp;
|
||||
private List<String> eventRecords = new ArrayList<String>();
|
||||
private List<String> eventNames = new ArrayList<String>();
|
||||
private Deck userDeck;
|
||||
private List<Deck> decks;
|
||||
|
||||
public GauntletData() {
|
||||
}
|
||||
|
||||
public void setName(String name0) {
|
||||
name = name0;
|
||||
}
|
||||
|
||||
public void rename(final String newName) {
|
||||
File newpath = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, newName + ".dat");
|
||||
File oldpath = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, name + ".dat");
|
||||
oldpath.renameTo(newpath);
|
||||
|
||||
name = newName;
|
||||
GauntletIO.saveGauntlet(this);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
if (name.startsWith(GauntletIO.PREFIX_LOCKED)) { //trim locked prefix if needed
|
||||
return name.substring(GauntletIO.PREFIX_LOCKED.length());
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public void stamp() {
|
||||
final DateFormat dateFormat = new SimpleDateFormat("MM-dd-yy, H:m");
|
||||
timestamp = dateFormat.format(new Date()).toString();
|
||||
}
|
||||
|
||||
/** Resets a gauntlet data to an unplayed state, then stamps and saves. */
|
||||
public void reset() {
|
||||
completed = 0;
|
||||
stamp();
|
||||
eventRecords.clear();
|
||||
|
||||
for (int i = 0; i < decks.size(); i++) {
|
||||
eventRecords.add("");
|
||||
}
|
||||
|
||||
GauntletIO.saveGauntlet(this);
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setCompleted(final int i0) {
|
||||
completed = i0;
|
||||
}
|
||||
|
||||
public int getCompleted() {
|
||||
return completed;
|
||||
}
|
||||
|
||||
public void setUserDeck(final Deck d0) {
|
||||
userDeck = d0;
|
||||
}
|
||||
|
||||
public Deck getUserDeck() {
|
||||
return userDeck;
|
||||
}
|
||||
|
||||
public List<String> getDeckNames() {
|
||||
final List<String> names = new ArrayList<String>();
|
||||
for (final Deck d : decks) { names.add(d.getName()); }
|
||||
return names;
|
||||
}
|
||||
|
||||
public void setEventRecords(final List<String> records0) {
|
||||
eventRecords = records0;
|
||||
}
|
||||
|
||||
public List<String> getEventRecords() {
|
||||
return eventRecords;
|
||||
}
|
||||
|
||||
public void setEventNames(final List<String> names0) {
|
||||
eventNames = names0;
|
||||
}
|
||||
|
||||
public List<String> getEventNames() {
|
||||
return eventNames;
|
||||
}
|
||||
|
||||
public void setDecks(final List<Deck> decks0) {
|
||||
decks = decks0;
|
||||
}
|
||||
|
||||
public List<Deck> getDecks() {
|
||||
return decks;
|
||||
}
|
||||
|
||||
public void startRound(final List<RegisteredPlayer> players, final RegisteredPlayer human) {
|
||||
hostedMatch = GuiBase.getInterface().hostMatch();
|
||||
hostedMatch.startMatch(GameType.Gauntlet, null, players, human, GuiBase.getInterface().getNewGuiGame());
|
||||
}
|
||||
|
||||
public void nextRound(final List<RegisteredPlayer> players, final RegisteredPlayer human) {
|
||||
if (hostedMatch == null) {
|
||||
throw new IllegalStateException("Cannot advance round when no match has been hosted.");
|
||||
}
|
||||
|
||||
hostedMatch.endCurrentGame();
|
||||
startRound(players, human);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String str = getDisplayName();
|
||||
if (decks != null) {
|
||||
str += " (" + decks.size() + " opponents)";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,195 +1,195 @@
|
||||
package forge.gauntlet;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.converters.Converter;
|
||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
|
||||
import forge.deck.CardPool;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.IgnoringXStream;
|
||||
|
||||
public class GauntletIO {
|
||||
/** Prompt in text field for new (unsaved) built gauntlets. */
|
||||
public static final String TXF_PROMPT = "[New Gauntlet]";
|
||||
/** suffix for all gauntlet data files */
|
||||
public static final String SUFFIX_DATA = ".dat";
|
||||
/** Prefix for quick gauntlet save files. */
|
||||
public static final String PREFIX_QUICK = "Quick_";
|
||||
/** Prefix for custom gauntlet save files. */
|
||||
public static final String PREFIX_CUSTOM = "Custom_";
|
||||
/** Regex for locked gauntlet save files. */
|
||||
public static final String PREFIX_LOCKED = "LOCKED_";
|
||||
|
||||
protected static XStream getSerializer(final boolean isIgnoring) {
|
||||
final XStream xStream = isIgnoring ? new IgnoringXStream() : new XStream();
|
||||
xStream.registerConverter(new DeckSectionToXml());
|
||||
xStream.autodetectAnnotations(true);
|
||||
return xStream;
|
||||
}
|
||||
|
||||
public static File getGauntletFile(final String name) {
|
||||
return new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, name + SUFFIX_DATA);
|
||||
}
|
||||
|
||||
public static File getGauntletFile(final GauntletData gd) {
|
||||
return getGauntletFile(gd.getName());
|
||||
}
|
||||
|
||||
public static File[] getGauntletFilesUnlocked(final String prefix) {
|
||||
final FilenameFilter filter = new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(final File dir, final String name) {
|
||||
return ((prefix == null || name.startsWith(prefix)) && name.endsWith(SUFFIX_DATA));
|
||||
}
|
||||
};
|
||||
|
||||
final File folder = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc);
|
||||
return folder.listFiles(filter);
|
||||
}
|
||||
|
||||
public static File[] getGauntletFilesLocked() {
|
||||
final FilenameFilter filter = new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(final File dir, final String name) {
|
||||
return (name.startsWith(PREFIX_LOCKED) && name.endsWith(SUFFIX_DATA));
|
||||
}
|
||||
};
|
||||
|
||||
final File folder = new File(ForgeConstants.GAUNTLET_DIR.defaultLoc);
|
||||
return folder.listFiles(filter);
|
||||
}
|
||||
|
||||
public static GauntletData loadGauntlet(final File xmlSaveFile) {
|
||||
GZIPInputStream zin = null;
|
||||
boolean isCorrupt = false;
|
||||
try {
|
||||
zin = new GZIPInputStream(new FileInputStream(xmlSaveFile));
|
||||
final InputStreamReader reader = new InputStreamReader(zin);
|
||||
|
||||
final GauntletData data = (GauntletData)GauntletIO.getSerializer(true).fromXML(reader);
|
||||
|
||||
final String filename = xmlSaveFile.getName();
|
||||
data.setName(filename.substring(0, filename.length() - SUFFIX_DATA.length()));
|
||||
return data;
|
||||
}
|
||||
catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (final Exception e) { //if there's a non-IO exception, delete the corrupt file
|
||||
e.printStackTrace();
|
||||
isCorrupt = true;
|
||||
}
|
||||
finally {
|
||||
if (zin != null) {
|
||||
try {
|
||||
zin.close();
|
||||
} catch (final IOException e) {
|
||||
System.out.println("error closing gauntlet data reader: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isCorrupt) {
|
||||
try {
|
||||
xmlSaveFile.delete();
|
||||
} catch (final Exception e) {
|
||||
System.out.println("error delete corrupt gauntlet file: " + e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void saveGauntlet(final GauntletData gd0) {
|
||||
try {
|
||||
final XStream xStream = GauntletIO.getSerializer(false);
|
||||
GauntletIO.savePacked(xStream, gd0);
|
||||
} catch (final Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void savePacked(final XStream xStream0, final GauntletData gd0) throws IOException {
|
||||
final BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(getGauntletFile(gd0)));
|
||||
final GZIPOutputStream zout = new GZIPOutputStream(bout);
|
||||
xStream0.toXML(gd0, zout);
|
||||
zout.flush();
|
||||
zout.close();
|
||||
}
|
||||
|
||||
private static class DeckSectionToXml implements Converter {
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean canConvert(final Class clasz) {
|
||||
return clasz.equals(CardPool.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
|
||||
for (final Entry<PaperCard, Integer> e : (CardPool) source) {
|
||||
writeCardPrinted(e.getKey(), e.getValue(), writer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
|
||||
final CardPool result = new CardPool();
|
||||
while (reader.hasMoreChildren()) {
|
||||
reader.moveDown();
|
||||
final String sCnt = reader.getAttribute("n");
|
||||
final int cnt = StringUtils.isNumeric(sCnt) ? Integer.parseInt(sCnt) : 1;
|
||||
final String nodename = reader.getNodeName();
|
||||
|
||||
if ("string".equals(nodename)) {
|
||||
result.add(FModel.getMagicDb().getCommonCards().getCard(reader.getValue()));
|
||||
} else if ("card".equals(nodename)) { // new format
|
||||
result.add(readCardPrinted(reader), cnt);
|
||||
}
|
||||
reader.moveUp();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void writeCardPrinted(final PaperCard cref, final Integer count, final HierarchicalStreamWriter writer) {
|
||||
writer.startNode("card");
|
||||
writer.addAttribute("c", cref.getName());
|
||||
writer.addAttribute("s", cref.getEdition());
|
||||
if (cref.isFoil()) {
|
||||
writer.addAttribute("foil", "1");
|
||||
}
|
||||
writer.addAttribute("i", Integer.toString(cref.getArtIndex()));
|
||||
writer.addAttribute("n", count.toString());
|
||||
writer.endNode();
|
||||
}
|
||||
|
||||
private static PaperCard readCardPrinted(final HierarchicalStreamReader reader) {
|
||||
final String name = reader.getAttribute("c");
|
||||
final String set = reader.getAttribute("s");
|
||||
final String sIndex = reader.getAttribute("i");
|
||||
final short index = StringUtils.isNumeric(sIndex) ? Short.parseShort(sIndex) : 0;
|
||||
final boolean foil = "1".equals(reader.getAttribute("foil"));
|
||||
PaperCard card = FModel.getMagicDb().getOrLoadCommonCard(name, set, index, foil);
|
||||
if (null == card) {
|
||||
throw new RuntimeException("Unsupported card found in quest save: " + name + " from edition " + set);
|
||||
}
|
||||
return card;
|
||||
}
|
||||
}
|
||||
}
|
||||
package forge.gauntlet;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.converters.Converter;
|
||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
|
||||
import forge.deck.CardPool;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.IgnoringXStream;
|
||||
|
||||
public class GauntletIO {
|
||||
/** Prompt in text field for new (unsaved) built gauntlets. */
|
||||
public static final String TXF_PROMPT = "[New Gauntlet]";
|
||||
/** suffix for all gauntlet data files */
|
||||
public static final String SUFFIX_DATA = ".dat";
|
||||
/** Prefix for quick gauntlet save files. */
|
||||
public static final String PREFIX_QUICK = "Quick_";
|
||||
/** Prefix for custom gauntlet save files. */
|
||||
public static final String PREFIX_CUSTOM = "Custom_";
|
||||
/** Regex for locked gauntlet save files. */
|
||||
public static final String PREFIX_LOCKED = "LOCKED_";
|
||||
|
||||
protected static XStream getSerializer(final boolean isIgnoring) {
|
||||
final XStream xStream = isIgnoring ? new IgnoringXStream() : new XStream();
|
||||
xStream.registerConverter(new DeckSectionToXml());
|
||||
xStream.autodetectAnnotations(true);
|
||||
return xStream;
|
||||
}
|
||||
|
||||
public static File getGauntletFile(final String name) {
|
||||
return new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc, name + SUFFIX_DATA);
|
||||
}
|
||||
|
||||
public static File getGauntletFile(final GauntletData gd) {
|
||||
return getGauntletFile(gd.getName());
|
||||
}
|
||||
|
||||
public static File[] getGauntletFilesUnlocked(final String prefix) {
|
||||
final FilenameFilter filter = new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(final File dir, final String name) {
|
||||
return ((prefix == null || name.startsWith(prefix)) && name.endsWith(SUFFIX_DATA));
|
||||
}
|
||||
};
|
||||
|
||||
final File folder = new File(ForgeConstants.GAUNTLET_DIR.userPrefLoc);
|
||||
return folder.listFiles(filter);
|
||||
}
|
||||
|
||||
public static File[] getGauntletFilesLocked() {
|
||||
final FilenameFilter filter = new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(final File dir, final String name) {
|
||||
return (name.startsWith(PREFIX_LOCKED) && name.endsWith(SUFFIX_DATA));
|
||||
}
|
||||
};
|
||||
|
||||
final File folder = new File(ForgeConstants.GAUNTLET_DIR.defaultLoc);
|
||||
return folder.listFiles(filter);
|
||||
}
|
||||
|
||||
public static GauntletData loadGauntlet(final File xmlSaveFile) {
|
||||
GZIPInputStream zin = null;
|
||||
boolean isCorrupt = false;
|
||||
try {
|
||||
zin = new GZIPInputStream(new FileInputStream(xmlSaveFile));
|
||||
final InputStreamReader reader = new InputStreamReader(zin);
|
||||
|
||||
final GauntletData data = (GauntletData)GauntletIO.getSerializer(true).fromXML(reader);
|
||||
|
||||
final String filename = xmlSaveFile.getName();
|
||||
data.setName(filename.substring(0, filename.length() - SUFFIX_DATA.length()));
|
||||
return data;
|
||||
}
|
||||
catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (final Exception e) { //if there's a non-IO exception, delete the corrupt file
|
||||
e.printStackTrace();
|
||||
isCorrupt = true;
|
||||
}
|
||||
finally {
|
||||
if (zin != null) {
|
||||
try {
|
||||
zin.close();
|
||||
} catch (final IOException e) {
|
||||
System.out.println("error closing gauntlet data reader: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isCorrupt) {
|
||||
try {
|
||||
xmlSaveFile.delete();
|
||||
} catch (final Exception e) {
|
||||
System.out.println("error delete corrupt gauntlet file: " + e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void saveGauntlet(final GauntletData gd0) {
|
||||
try {
|
||||
final XStream xStream = GauntletIO.getSerializer(false);
|
||||
GauntletIO.savePacked(xStream, gd0);
|
||||
} catch (final Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void savePacked(final XStream xStream0, final GauntletData gd0) throws IOException {
|
||||
final BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(getGauntletFile(gd0)));
|
||||
final GZIPOutputStream zout = new GZIPOutputStream(bout);
|
||||
xStream0.toXML(gd0, zout);
|
||||
zout.flush();
|
||||
zout.close();
|
||||
}
|
||||
|
||||
private static class DeckSectionToXml implements Converter {
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean canConvert(final Class clasz) {
|
||||
return clasz.equals(CardPool.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
|
||||
for (final Entry<PaperCard, Integer> e : (CardPool) source) {
|
||||
writeCardPrinted(e.getKey(), e.getValue(), writer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
|
||||
final CardPool result = new CardPool();
|
||||
while (reader.hasMoreChildren()) {
|
||||
reader.moveDown();
|
||||
final String sCnt = reader.getAttribute("n");
|
||||
final int cnt = StringUtils.isNumeric(sCnt) ? Integer.parseInt(sCnt) : 1;
|
||||
final String nodename = reader.getNodeName();
|
||||
|
||||
if ("string".equals(nodename)) {
|
||||
result.add(FModel.getMagicDb().getCommonCards().getCard(reader.getValue()));
|
||||
} else if ("card".equals(nodename)) { // new format
|
||||
result.add(readCardPrinted(reader), cnt);
|
||||
}
|
||||
reader.moveUp();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void writeCardPrinted(final PaperCard cref, final Integer count, final HierarchicalStreamWriter writer) {
|
||||
writer.startNode("card");
|
||||
writer.addAttribute("c", cref.getName());
|
||||
writer.addAttribute("s", cref.getEdition());
|
||||
if (cref.isFoil()) {
|
||||
writer.addAttribute("foil", "1");
|
||||
}
|
||||
writer.addAttribute("i", Integer.toString(cref.getArtIndex()));
|
||||
writer.addAttribute("n", count.toString());
|
||||
writer.endNode();
|
||||
}
|
||||
|
||||
private static PaperCard readCardPrinted(final HierarchicalStreamReader reader) {
|
||||
final String name = reader.getAttribute("c");
|
||||
final String set = reader.getAttribute("s");
|
||||
final String sIndex = reader.getAttribute("i");
|
||||
final short index = StringUtils.isNumeric(sIndex) ? Short.parseShort(sIndex) : 0;
|
||||
final boolean foil = "1".equals(reader.getAttribute("foil"));
|
||||
PaperCard card = FModel.getMagicDb().getOrLoadCommonCard(name, set, index, foil);
|
||||
if (null == card) {
|
||||
throw new RuntimeException("Unsupported card found in quest save: " + name + " from edition " + set);
|
||||
}
|
||||
return card;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,88 +1,88 @@
|
||||
package forge.gauntlet;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckType;
|
||||
import forge.deck.DeckgenUtil;
|
||||
import forge.model.FModel;
|
||||
|
||||
public class GauntletUtil {
|
||||
public static GauntletData createQuickGauntlet(final Deck userDeck, final int numOpponents, final List<DeckType> allowedDeckTypes) {
|
||||
GauntletData gauntlet = new GauntletData();
|
||||
setDefaultGauntletName(gauntlet, GauntletIO.PREFIX_QUICK);
|
||||
FModel.setGauntletData(gauntlet);
|
||||
|
||||
// Generate gauntlet decks
|
||||
Deck deck;
|
||||
final List<String> eventNames = new ArrayList<String>();
|
||||
final List<Deck> decks = new ArrayList<Deck>();
|
||||
|
||||
for (int i = 0; i < numOpponents; i++) {
|
||||
int randType = (int)Math.floor(Math.random() * allowedDeckTypes.size());
|
||||
switch (allowedDeckTypes.get(randType)) {
|
||||
case COLOR_DECK:
|
||||
deck = DeckgenUtil.getRandomColorDeck(true);
|
||||
eventNames.add("Random colors deck");
|
||||
break;
|
||||
case STANDARD_COLOR_DECK:
|
||||
deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getStandard().getFilterPrinted(),true);
|
||||
break;
|
||||
case STANDARD_CARDGEN_DECK:
|
||||
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getStandard(),true);
|
||||
break;
|
||||
case MODERN_CARDGEN_DECK:
|
||||
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getModern(),true);
|
||||
break;
|
||||
case MODERN_COLOR_DECK:
|
||||
deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getModern().getFilterPrinted(),true);
|
||||
break;
|
||||
case CUSTOM_DECK:
|
||||
deck = DeckgenUtil.getRandomCustomDeck();
|
||||
eventNames.add(deck.getName());
|
||||
break;
|
||||
case PRECONSTRUCTED_DECK:
|
||||
deck = DeckgenUtil.getRandomPreconDeck();
|
||||
eventNames.add(deck.getName());
|
||||
break;
|
||||
case QUEST_OPPONENT_DECK:
|
||||
deck = DeckgenUtil.getRandomQuestDeck();
|
||||
eventNames.add(deck.getName());
|
||||
break;
|
||||
case THEME_DECK:
|
||||
deck = DeckgenUtil.getRandomThemeDeck();
|
||||
eventNames.add(deck.getName());
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
decks.add(deck);
|
||||
}
|
||||
|
||||
gauntlet.setDecks(decks);
|
||||
gauntlet.setEventNames(eventNames);
|
||||
gauntlet.setUserDeck(userDeck);
|
||||
|
||||
// Reset all variable fields to 0, stamps and saves automatically.
|
||||
gauntlet.reset();
|
||||
return gauntlet;
|
||||
}
|
||||
|
||||
public static void setDefaultGauntletName(GauntletData gauntlet, String prefix) {
|
||||
final File[] arrFiles = GauntletIO.getGauntletFilesUnlocked(prefix);
|
||||
final Set<String> setNames = new HashSet<String>();
|
||||
for (File f : arrFiles) {
|
||||
setNames.add(f.getName());
|
||||
}
|
||||
|
||||
int num = 1;
|
||||
while (setNames.contains(prefix + num + GauntletIO.SUFFIX_DATA)) {
|
||||
num++;
|
||||
}
|
||||
gauntlet.setName(prefix + num);
|
||||
}
|
||||
}
|
||||
package forge.gauntlet;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckType;
|
||||
import forge.deck.DeckgenUtil;
|
||||
import forge.model.FModel;
|
||||
|
||||
public class GauntletUtil {
|
||||
public static GauntletData createQuickGauntlet(final Deck userDeck, final int numOpponents, final List<DeckType> allowedDeckTypes) {
|
||||
GauntletData gauntlet = new GauntletData();
|
||||
setDefaultGauntletName(gauntlet, GauntletIO.PREFIX_QUICK);
|
||||
FModel.setGauntletData(gauntlet);
|
||||
|
||||
// Generate gauntlet decks
|
||||
Deck deck;
|
||||
final List<String> eventNames = new ArrayList<String>();
|
||||
final List<Deck> decks = new ArrayList<Deck>();
|
||||
|
||||
for (int i = 0; i < numOpponents; i++) {
|
||||
int randType = (int)Math.floor(Math.random() * allowedDeckTypes.size());
|
||||
switch (allowedDeckTypes.get(randType)) {
|
||||
case COLOR_DECK:
|
||||
deck = DeckgenUtil.getRandomColorDeck(true);
|
||||
eventNames.add("Random colors deck");
|
||||
break;
|
||||
case STANDARD_COLOR_DECK:
|
||||
deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getStandard().getFilterPrinted(),true);
|
||||
break;
|
||||
case STANDARD_CARDGEN_DECK:
|
||||
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getStandard(),true);
|
||||
break;
|
||||
case MODERN_CARDGEN_DECK:
|
||||
deck = DeckgenUtil.buildCardGenDeck(FModel.getFormats().getModern(),true);
|
||||
break;
|
||||
case MODERN_COLOR_DECK:
|
||||
deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getModern().getFilterPrinted(),true);
|
||||
break;
|
||||
case CUSTOM_DECK:
|
||||
deck = DeckgenUtil.getRandomCustomDeck();
|
||||
eventNames.add(deck.getName());
|
||||
break;
|
||||
case PRECONSTRUCTED_DECK:
|
||||
deck = DeckgenUtil.getRandomPreconDeck();
|
||||
eventNames.add(deck.getName());
|
||||
break;
|
||||
case QUEST_OPPONENT_DECK:
|
||||
deck = DeckgenUtil.getRandomQuestDeck();
|
||||
eventNames.add(deck.getName());
|
||||
break;
|
||||
case THEME_DECK:
|
||||
deck = DeckgenUtil.getRandomThemeDeck();
|
||||
eventNames.add(deck.getName());
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
decks.add(deck);
|
||||
}
|
||||
|
||||
gauntlet.setDecks(decks);
|
||||
gauntlet.setEventNames(eventNames);
|
||||
gauntlet.setUserDeck(userDeck);
|
||||
|
||||
// Reset all variable fields to 0, stamps and saves automatically.
|
||||
gauntlet.reset();
|
||||
return gauntlet;
|
||||
}
|
||||
|
||||
public static void setDefaultGauntletName(GauntletData gauntlet, String prefix) {
|
||||
final File[] arrFiles = GauntletIO.getGauntletFilesUnlocked(prefix);
|
||||
final Set<String> setNames = new HashSet<String>();
|
||||
for (File f : arrFiles) {
|
||||
setNames.add(f.getName());
|
||||
}
|
||||
|
||||
int num = 1;
|
||||
while (setNames.contains(prefix + num + GauntletIO.SUFFIX_DATA)) {
|
||||
num++;
|
||||
}
|
||||
gauntlet.setName(prefix + num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,141 +1,141 @@
|
||||
package forge.gauntlet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.deck.Deck;
|
||||
import forge.game.GameView;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
import forge.interfaces.IButton;
|
||||
import forge.interfaces.IWinLoseView;
|
||||
import forge.model.FModel;
|
||||
import forge.player.GamePlayerUtil;
|
||||
|
||||
public abstract class GauntletWinLoseController {
|
||||
private static final String SAVE_AND_QUIT = "Save and Quit";
|
||||
|
||||
private final IWinLoseView<? extends IButton> view;
|
||||
private final GameView lastGame;
|
||||
|
||||
public GauntletWinLoseController(IWinLoseView<? extends IButton> view0, final GameView game0) {
|
||||
view = view0;
|
||||
lastGame = game0;
|
||||
}
|
||||
|
||||
public void showOutcome() {
|
||||
final GauntletData gd = FModel.getGauntletData();
|
||||
final List<String> lstEventNames = gd.getEventNames();
|
||||
final List<Deck> lstDecks = gd.getDecks();
|
||||
final List<String> lstEventRecords = gd.getEventRecords();
|
||||
final int len = lstEventNames.size();
|
||||
final int num = gd.getCompleted();
|
||||
FSkinProp icon = null;
|
||||
String message1 = null;
|
||||
String message2 = null;
|
||||
|
||||
// No restarts.
|
||||
view.getBtnRestart().setVisible(false);
|
||||
|
||||
// Generic event record.
|
||||
lstEventRecords.set(gd.getCompleted(), "Ongoing");
|
||||
|
||||
// Match won't be saved until it is over. This opens up a cheat
|
||||
// or failsafe mechanism (depending on your perspective) in which
|
||||
// the player can restart Forge to replay a match.
|
||||
// Pretty sure this can't be fixed until in-game states can be
|
||||
// saved. Doublestrike 07-10-12
|
||||
LobbyPlayer questPlayer = GamePlayerUtil.getGuiPlayer();
|
||||
|
||||
// In all cases, update stats.
|
||||
lstEventRecords.set(gd.getCompleted(), lastGame.getGamesWonBy(questPlayer) + " - "
|
||||
+ (lastGame.getNumPlayedGamesInMatch() - lastGame.getGamesWonBy(questPlayer) + 1));
|
||||
|
||||
boolean isMatchOver = lastGame.isMatchOver();
|
||||
if (isMatchOver) {
|
||||
gd.setCompleted(gd.getCompleted() + 1);
|
||||
|
||||
// Win match case
|
||||
if (lastGame.isMatchWonBy(questPlayer)) {
|
||||
// Gauntlet complete: Remove save file
|
||||
if (gd.getCompleted() == lstDecks.size()) {
|
||||
icon = FSkinProp.ICO_QUEST_COIN;
|
||||
message1 = "CONGRATULATIONS!";
|
||||
message2 = "You made it through the gauntlet!";
|
||||
|
||||
view.getBtnContinue().setVisible(false);
|
||||
view.getBtnQuit().setText("OK");
|
||||
|
||||
// Remove save file if it's a quickie, or just reset it.
|
||||
if (gd.getName().startsWith(GauntletIO.PREFIX_QUICK)) {
|
||||
GauntletIO.getGauntletFile(gd).delete();
|
||||
}
|
||||
else {
|
||||
gd.reset();
|
||||
}
|
||||
}
|
||||
// Or, save and move to next game
|
||||
else {
|
||||
gd.stamp();
|
||||
GauntletIO.saveGauntlet(gd);
|
||||
|
||||
view.getBtnContinue().setText("Next Round (" + (gd.getCompleted() + 1)
|
||||
+ "/" + len + ")");
|
||||
view.getBtnContinue().setVisible(true);
|
||||
view.getBtnContinue().setEnabled(true);
|
||||
view.getBtnQuit().setText("Save and Quit");
|
||||
}
|
||||
}
|
||||
// Lose match case; stop gauntlet.
|
||||
else {
|
||||
icon = FSkinProp.ICO_QUEST_HEART;
|
||||
message1 = "DEFEATED!";
|
||||
message2 = "You have failed to pass the gauntlet.";
|
||||
|
||||
view.getBtnContinue().setVisible(false);
|
||||
|
||||
// Remove save file if it's a quickie, or just reset it.
|
||||
if (gd.getName().startsWith(GauntletIO.PREFIX_QUICK)) {
|
||||
GauntletIO.getGauntletFile(gd).delete();
|
||||
}
|
||||
else {
|
||||
gd.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gd.setEventRecords(lstEventRecords);
|
||||
|
||||
showOutcome(isMatchOver, message1, message2, icon, lstEventNames, lstEventRecords, len, num);
|
||||
}
|
||||
|
||||
public final boolean actionOnContinue() {
|
||||
if (lastGame.isMatchOver()) {
|
||||
// To change the AI deck, we have to create a new match.
|
||||
final GauntletData gd = FModel.getGauntletData();
|
||||
final RegisteredPlayer human = new RegisteredPlayer(gd.getUserDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
final Deck aiDeck = gd.getDecks().get(gd.getCompleted());
|
||||
final List<RegisteredPlayer> players = Lists.newArrayList();
|
||||
players.add(human);
|
||||
players.add(new RegisteredPlayer(aiDeck).setPlayer(GamePlayerUtil.createAiPlayer()));
|
||||
|
||||
view.hide();
|
||||
saveOptions();
|
||||
gd.nextRound(players, human);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final void actionOnQuit() {
|
||||
if (!SAVE_AND_QUIT.equals(view.getBtnQuit().getText())) {
|
||||
// Quitting mid-match abandons the gauntlet.
|
||||
FModel.getGauntletData().reset();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void showOutcome(boolean isMatchOver, String message1, String message2, FSkinProp icon, List<String> lstEventNames, List<String> lstEventRecords, int len, int num);
|
||||
protected abstract void saveOptions();
|
||||
}
|
||||
package forge.gauntlet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.deck.Deck;
|
||||
import forge.game.GameView;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
import forge.interfaces.IButton;
|
||||
import forge.interfaces.IWinLoseView;
|
||||
import forge.model.FModel;
|
||||
import forge.player.GamePlayerUtil;
|
||||
|
||||
public abstract class GauntletWinLoseController {
|
||||
private static final String SAVE_AND_QUIT = "Save and Quit";
|
||||
|
||||
private final IWinLoseView<? extends IButton> view;
|
||||
private final GameView lastGame;
|
||||
|
||||
public GauntletWinLoseController(IWinLoseView<? extends IButton> view0, final GameView game0) {
|
||||
view = view0;
|
||||
lastGame = game0;
|
||||
}
|
||||
|
||||
public void showOutcome() {
|
||||
final GauntletData gd = FModel.getGauntletData();
|
||||
final List<String> lstEventNames = gd.getEventNames();
|
||||
final List<Deck> lstDecks = gd.getDecks();
|
||||
final List<String> lstEventRecords = gd.getEventRecords();
|
||||
final int len = lstEventNames.size();
|
||||
final int num = gd.getCompleted();
|
||||
FSkinProp icon = null;
|
||||
String message1 = null;
|
||||
String message2 = null;
|
||||
|
||||
// No restarts.
|
||||
view.getBtnRestart().setVisible(false);
|
||||
|
||||
// Generic event record.
|
||||
lstEventRecords.set(gd.getCompleted(), "Ongoing");
|
||||
|
||||
// Match won't be saved until it is over. This opens up a cheat
|
||||
// or failsafe mechanism (depending on your perspective) in which
|
||||
// the player can restart Forge to replay a match.
|
||||
// Pretty sure this can't be fixed until in-game states can be
|
||||
// saved. Doublestrike 07-10-12
|
||||
LobbyPlayer questPlayer = GamePlayerUtil.getGuiPlayer();
|
||||
|
||||
// In all cases, update stats.
|
||||
lstEventRecords.set(gd.getCompleted(), lastGame.getGamesWonBy(questPlayer) + " - "
|
||||
+ (lastGame.getNumPlayedGamesInMatch() - lastGame.getGamesWonBy(questPlayer) + 1));
|
||||
|
||||
boolean isMatchOver = lastGame.isMatchOver();
|
||||
if (isMatchOver) {
|
||||
gd.setCompleted(gd.getCompleted() + 1);
|
||||
|
||||
// Win match case
|
||||
if (lastGame.isMatchWonBy(questPlayer)) {
|
||||
// Gauntlet complete: Remove save file
|
||||
if (gd.getCompleted() == lstDecks.size()) {
|
||||
icon = FSkinProp.ICO_QUEST_COIN;
|
||||
message1 = "CONGRATULATIONS!";
|
||||
message2 = "You made it through the gauntlet!";
|
||||
|
||||
view.getBtnContinue().setVisible(false);
|
||||
view.getBtnQuit().setText("OK");
|
||||
|
||||
// Remove save file if it's a quickie, or just reset it.
|
||||
if (gd.getName().startsWith(GauntletIO.PREFIX_QUICK)) {
|
||||
GauntletIO.getGauntletFile(gd).delete();
|
||||
}
|
||||
else {
|
||||
gd.reset();
|
||||
}
|
||||
}
|
||||
// Or, save and move to next game
|
||||
else {
|
||||
gd.stamp();
|
||||
GauntletIO.saveGauntlet(gd);
|
||||
|
||||
view.getBtnContinue().setText("Next Round (" + (gd.getCompleted() + 1)
|
||||
+ "/" + len + ")");
|
||||
view.getBtnContinue().setVisible(true);
|
||||
view.getBtnContinue().setEnabled(true);
|
||||
view.getBtnQuit().setText("Save and Quit");
|
||||
}
|
||||
}
|
||||
// Lose match case; stop gauntlet.
|
||||
else {
|
||||
icon = FSkinProp.ICO_QUEST_HEART;
|
||||
message1 = "DEFEATED!";
|
||||
message2 = "You have failed to pass the gauntlet.";
|
||||
|
||||
view.getBtnContinue().setVisible(false);
|
||||
|
||||
// Remove save file if it's a quickie, or just reset it.
|
||||
if (gd.getName().startsWith(GauntletIO.PREFIX_QUICK)) {
|
||||
GauntletIO.getGauntletFile(gd).delete();
|
||||
}
|
||||
else {
|
||||
gd.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gd.setEventRecords(lstEventRecords);
|
||||
|
||||
showOutcome(isMatchOver, message1, message2, icon, lstEventNames, lstEventRecords, len, num);
|
||||
}
|
||||
|
||||
public final boolean actionOnContinue() {
|
||||
if (lastGame.isMatchOver()) {
|
||||
// To change the AI deck, we have to create a new match.
|
||||
final GauntletData gd = FModel.getGauntletData();
|
||||
final RegisteredPlayer human = new RegisteredPlayer(gd.getUserDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||
final Deck aiDeck = gd.getDecks().get(gd.getCompleted());
|
||||
final List<RegisteredPlayer> players = Lists.newArrayList();
|
||||
players.add(human);
|
||||
players.add(new RegisteredPlayer(aiDeck).setPlayer(GamePlayerUtil.createAiPlayer()));
|
||||
|
||||
view.hide();
|
||||
saveOptions();
|
||||
gd.nextRound(players, human);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final void actionOnQuit() {
|
||||
if (!SAVE_AND_QUIT.equals(view.getBtnQuit().getText())) {
|
||||
// Quitting mid-match abandons the gauntlet.
|
||||
FModel.getGauntletData().reset();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void showOutcome(boolean isMatchOver, String message1, String message2, FSkinProp icon, List<String> lstEventNames, List<String> lstEventRecords, int len, int num);
|
||||
protected abstract void saveOptions();
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package forge.interfaces;
|
||||
|
||||
import forge.UiCommand;
|
||||
import forge.assets.FSkinProp;
|
||||
|
||||
public interface IButton extends ITextComponent {
|
||||
boolean isSelected();
|
||||
void setSelected(boolean b0);
|
||||
boolean requestFocusInWindow();
|
||||
void setCommand(UiCommand command0);
|
||||
void setImage(FSkinProp color);
|
||||
void setTextColor(int r, int g, int b);
|
||||
}
|
||||
package forge.interfaces;
|
||||
|
||||
import forge.UiCommand;
|
||||
import forge.assets.FSkinProp;
|
||||
|
||||
public interface IButton extends ITextComponent {
|
||||
boolean isSelected();
|
||||
void setSelected(boolean b0);
|
||||
boolean requestFocusInWindow();
|
||||
void setCommand(UiCommand command0);
|
||||
void setImage(FSkinProp color);
|
||||
void setTextColor(int r, int g, int b);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package forge.interfaces;
|
||||
|
||||
public interface ICheckBox extends IComponent {
|
||||
boolean isSelected();
|
||||
void setSelected(boolean b0);
|
||||
}
|
||||
package forge.interfaces;
|
||||
|
||||
public interface ICheckBox extends IComponent {
|
||||
boolean isSelected();
|
||||
void setSelected(boolean b0);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package forge.interfaces;
|
||||
|
||||
public interface IComboBox<E> extends IComponent {
|
||||
void setSelectedItem(E item);
|
||||
void setSelectedIndex(int index);
|
||||
void addItem(E item);
|
||||
void removeAllItems();
|
||||
int getSelectedIndex();
|
||||
E getSelectedItem();
|
||||
}
|
||||
package forge.interfaces;
|
||||
|
||||
public interface IComboBox<E> extends IComponent {
|
||||
void setSelectedItem(E item);
|
||||
void setSelectedIndex(int index);
|
||||
void addItem(E item);
|
||||
void removeAllItems();
|
||||
int getSelectedIndex();
|
||||
E getSelectedItem();
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package forge.interfaces;
|
||||
|
||||
public interface IDeviceAdapter {
|
||||
boolean isConnectedToInternet();
|
||||
boolean isConnectedToWifi();
|
||||
boolean isTablet();
|
||||
String getDownloadsDir();
|
||||
boolean openFile(String filename);
|
||||
void setLandscapeMode(boolean landscapeMode);
|
||||
void preventSystemSleep(boolean preventSleep);
|
||||
void restart();
|
||||
void exit();
|
||||
}
|
||||
package forge.interfaces;
|
||||
|
||||
public interface IDeviceAdapter {
|
||||
boolean isConnectedToInternet();
|
||||
boolean isConnectedToWifi();
|
||||
boolean isTablet();
|
||||
String getDownloadsDir();
|
||||
boolean openFile(String filename);
|
||||
void setLandscapeMode(boolean landscapeMode);
|
||||
void preventSystemSleep(boolean preventSleep);
|
||||
void restart();
|
||||
void exit();
|
||||
}
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
package forge.interfaces;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.assets.ISkinImage;
|
||||
import forge.download.GuiDownloadService;
|
||||
import forge.item.PaperCard;
|
||||
import forge.match.HostedMatch;
|
||||
import forge.sound.IAudioClip;
|
||||
import forge.sound.IAudioMusic;
|
||||
import forge.util.Callback;
|
||||
|
||||
public interface IGuiBase {
|
||||
boolean isRunningOnDesktop();
|
||||
boolean isLibgdxPort();
|
||||
String getCurrentVersion();
|
||||
String getAssetsDir();
|
||||
void invokeInEdtNow(Runnable runnable);
|
||||
void invokeInEdtLater(Runnable runnable);
|
||||
void invokeInEdtAndWait(Runnable proc);
|
||||
boolean isGuiThread();
|
||||
ISkinImage getSkinIcon(FSkinProp skinProp);
|
||||
ISkinImage getUnskinnedIcon(String path);
|
||||
ISkinImage getCardArt(PaperCard card);
|
||||
ISkinImage createLayeredImage(FSkinProp background, String overlayFilename, float opacity);
|
||||
void showBugReportDialog(String title, String text, boolean showExitAppBtn);
|
||||
void showImageDialog(ISkinImage image, String message, String title);
|
||||
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
|
||||
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions);
|
||||
<T> List<T> getChoices(String message, int min, int max, Collection<T> choices, T selected, Function<T, String> display);
|
||||
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices);
|
||||
String showFileDialog(String title, String defaultDir);
|
||||
File getSaveFile(File defaultFile);
|
||||
void download(GuiDownloadService service, Callback<Boolean> callback);
|
||||
void showCardList(String title, String message, List<PaperCard> list);
|
||||
boolean showBoxedProduct(String title, String message, List<PaperCard> list);
|
||||
PaperCard chooseCard(String title, String message, List<PaperCard> list);
|
||||
int getAvatarCount();
|
||||
void copyToClipboard(String text);
|
||||
void browseToUrl(String url) throws IOException, URISyntaxException;
|
||||
IAudioClip createAudioClip(String filename);
|
||||
IAudioMusic createAudioMusic(String filename);
|
||||
void startAltSoundSystem(String filename, boolean isSynchronized);
|
||||
void clearImageCache();
|
||||
void showSpellShop();
|
||||
void showBazaar();
|
||||
IGuiGame getNewGuiGame();
|
||||
HostedMatch hostMatch();
|
||||
void runBackgroundTask(String message, Runnable task);
|
||||
String encodeSymbols(String str, boolean formatReminderText);
|
||||
void preventSystemSleep(boolean preventSleep);
|
||||
package forge.interfaces;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.assets.ISkinImage;
|
||||
import forge.download.GuiDownloadService;
|
||||
import forge.item.PaperCard;
|
||||
import forge.match.HostedMatch;
|
||||
import forge.sound.IAudioClip;
|
||||
import forge.sound.IAudioMusic;
|
||||
import forge.util.Callback;
|
||||
|
||||
public interface IGuiBase {
|
||||
boolean isRunningOnDesktop();
|
||||
boolean isLibgdxPort();
|
||||
String getCurrentVersion();
|
||||
String getAssetsDir();
|
||||
void invokeInEdtNow(Runnable runnable);
|
||||
void invokeInEdtLater(Runnable runnable);
|
||||
void invokeInEdtAndWait(Runnable proc);
|
||||
boolean isGuiThread();
|
||||
ISkinImage getSkinIcon(FSkinProp skinProp);
|
||||
ISkinImage getUnskinnedIcon(String path);
|
||||
ISkinImage getCardArt(PaperCard card);
|
||||
ISkinImage createLayeredImage(FSkinProp background, String overlayFilename, float opacity);
|
||||
void showBugReportDialog(String title, String text, boolean showExitAppBtn);
|
||||
void showImageDialog(ISkinImage image, String message, String title);
|
||||
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
|
||||
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions);
|
||||
<T> List<T> getChoices(String message, int min, int max, Collection<T> choices, T selected, Function<T, String> display);
|
||||
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices);
|
||||
String showFileDialog(String title, String defaultDir);
|
||||
File getSaveFile(File defaultFile);
|
||||
void download(GuiDownloadService service, Callback<Boolean> callback);
|
||||
void showCardList(String title, String message, List<PaperCard> list);
|
||||
boolean showBoxedProduct(String title, String message, List<PaperCard> list);
|
||||
PaperCard chooseCard(String title, String message, List<PaperCard> list);
|
||||
int getAvatarCount();
|
||||
void copyToClipboard(String text);
|
||||
void browseToUrl(String url) throws IOException, URISyntaxException;
|
||||
IAudioClip createAudioClip(String filename);
|
||||
IAudioMusic createAudioMusic(String filename);
|
||||
void startAltSoundSystem(String filename, boolean isSynchronized);
|
||||
void clearImageCache();
|
||||
void showSpellShop();
|
||||
void showBazaar();
|
||||
IGuiGame getNewGuiGame();
|
||||
HostedMatch hostMatch();
|
||||
void runBackgroundTask(String message, Runnable task);
|
||||
String encodeSymbols(String str, boolean formatReminderText);
|
||||
void preventSystemSleep(boolean preventSleep);
|
||||
}
|
||||
@@ -1,169 +1,169 @@
|
||||
package forge.interfaces;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.deck.CardPool;
|
||||
import forge.game.GameEntityView;
|
||||
import forge.game.GameView;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.IHasIcon;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.spellability.SpellAbilityView;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.item.PaperCard;
|
||||
import forge.player.PlayerZoneUpdate;
|
||||
import forge.trackable.TrackableCollection;
|
||||
import forge.util.ITriggerEvent;
|
||||
|
||||
public interface IGuiGame {
|
||||
void setGameView(GameView gameView);
|
||||
void setOriginalGameController(PlayerView view, IGameController gameController);
|
||||
void setGameController(PlayerView player, IGameController gameController);
|
||||
void setSpectator(IGameController spectator);
|
||||
void openView(TrackableCollection<PlayerView> myPlayers);
|
||||
void afterGameEnd();
|
||||
void showCombat();
|
||||
void showPromptMessage(PlayerView playerView, String message);
|
||||
void showPromptMessage(PlayerView playerView, String message, CardView card);
|
||||
void updateButtons(PlayerView owner, boolean okEnabled, boolean cancelEnabled, boolean focusOk);
|
||||
void updateButtons(PlayerView owner, String label1, String label2, boolean enable1, boolean enable2, boolean focus1);
|
||||
void flashIncorrectAction();
|
||||
void updatePhase();
|
||||
void updateTurn(PlayerView player);
|
||||
void updatePlayerControl();
|
||||
void enableOverlay();
|
||||
void disableOverlay();
|
||||
void finishGame();
|
||||
void showManaPool(PlayerView player);
|
||||
void hideManaPool(PlayerView player);
|
||||
void updateStack();
|
||||
void updateZones(Iterable<PlayerZoneUpdate> zonesToUpdate);
|
||||
void updateSingleCard(CardView card);
|
||||
void updateCards(Iterable<CardView> cards);
|
||||
void refreshCardDetails(Iterable<CardView> cards);
|
||||
void updateManaPool(Iterable<PlayerView> manaPoolUpdate);
|
||||
void updateLives(Iterable<PlayerView> livesUpdate);
|
||||
void setPanelSelection(CardView hostCard);
|
||||
SpellAbilityView getAbilityToPlay(CardView hostCard, List<SpellAbilityView> abilities, ITriggerEvent triggerEvent);
|
||||
Map<CardView, Integer> assignDamage(CardView attacker, List<CardView> blockers, int damage, GameEntityView defender, boolean overrideOrder);
|
||||
|
||||
void message(String message);
|
||||
void message(String message, String title);
|
||||
|
||||
void showErrorDialog(String message);
|
||||
void showErrorDialog(String message, String title);
|
||||
|
||||
boolean showConfirmDialog(String message, String title);
|
||||
boolean showConfirmDialog(String message, String title, boolean defaultYes);
|
||||
boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText);
|
||||
boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText, boolean defaultYes);
|
||||
|
||||
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
|
||||
|
||||
String showInputDialog(String message, String title);
|
||||
String showInputDialog(String message, String title, FSkinProp icon);
|
||||
String showInputDialog(String message, String title, FSkinProp icon, String initialInput);
|
||||
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions);
|
||||
|
||||
boolean confirm(CardView c, String question);
|
||||
boolean confirm(CardView c, String question, List<String> options);
|
||||
boolean confirm(CardView c, String question, boolean defaultIsYes, List<String> options);
|
||||
|
||||
<T> List<T> getChoices(String message, int min, int max, List<T> choices);
|
||||
<T> List<T> getChoices(String message, int min, int max, List<T> choices, T selected, Function<T, String> display);
|
||||
|
||||
// Get Integer in range
|
||||
Integer getInteger(String message, int min);
|
||||
Integer getInteger(String message, int min, int max);
|
||||
Integer getInteger(String message, int min, int max, boolean sortDesc);
|
||||
Integer getInteger(String message, int min, int max, int cutoff);
|
||||
|
||||
/**
|
||||
* Convenience for getChoices(message, 0, 1, choices).
|
||||
*
|
||||
* @param <T>
|
||||
* is automatically inferred.
|
||||
* @param message
|
||||
* a {@link java.lang.String} object.
|
||||
* @param choices
|
||||
* a T object.
|
||||
* @return null if choices is missing, empty, or if the users' choices are
|
||||
* empty; otherwise, returns the first item in the List returned by
|
||||
* getChoices.
|
||||
* @see #getChoices(String, int, int, Object...)
|
||||
*/
|
||||
<T> T oneOrNone(String message, List<T> choices);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getChoice.
|
||||
* </p>
|
||||
*
|
||||
* @param <T>
|
||||
* a T object.
|
||||
* @param message
|
||||
* a {@link java.lang.String} object.
|
||||
* @param choices
|
||||
* a T object.
|
||||
* @return One of {@code choices}. Can only be {@code null} if {@code choices} is empty.
|
||||
*/
|
||||
<T> T one(String message, List<T> choices);
|
||||
|
||||
<T> void reveal(String message, List<T> items);
|
||||
|
||||
<T> List<T> many(String title, String topCaption, int cnt, List<T> sourceChoices, CardView c);
|
||||
<T> List<T> many(String title, String topCaption, int min, int max, List<T> sourceChoices, CardView c);
|
||||
|
||||
<T> List<T> order(String title, String top, List<T> sourceChoices, CardView c);
|
||||
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices, CardView referenceCard, boolean sideboardingMode);
|
||||
|
||||
/**
|
||||
* Ask the user to insert an object into a list of other objects. The
|
||||
* current implementation requires the user to cancel in order to get the
|
||||
* new item to be the first item in the resulting list.
|
||||
*
|
||||
* @param title
|
||||
* the dialog title.
|
||||
* @param newItem
|
||||
* the object to insert.
|
||||
* @param oldItems
|
||||
* the list of objects.
|
||||
* @return A shallow copy of the list of objects, with newItem inserted.
|
||||
*/
|
||||
<T> List<T> insertInList(String title, T newItem, List<T> oldItems);
|
||||
|
||||
List<PaperCard> sideboard(CardPool sideboard, CardPool main);
|
||||
GameEntityView chooseSingleEntityForEffect(String title, List<? extends GameEntityView> optionList, DelayedReveal delayedReveal, boolean isOptional); void setCard(CardView card);
|
||||
void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi);
|
||||
boolean openZones(Collection<ZoneType> zones, Map<PlayerView, Object> players);
|
||||
void restoreOldZones(Map<PlayerView, Object> playersToRestoreZonesFor);
|
||||
void setHighlighted(PlayerView pv, boolean b);
|
||||
void setUsedToPay(CardView card, boolean value);
|
||||
|
||||
void awaitNextInput();
|
||||
void cancelAwaitNextInput();
|
||||
|
||||
boolean isUiSetToSkipPhase(PlayerView playerTurn, PhaseType phase);
|
||||
void autoPassUntilEndOfTurn(PlayerView player);
|
||||
boolean mayAutoPass(PlayerView player);
|
||||
void autoPassCancel(PlayerView player);
|
||||
void updateAutoPassPrompt();
|
||||
boolean shouldAutoYield(String key);
|
||||
void setShouldAutoYield(String key, boolean autoYield);
|
||||
boolean shouldAlwaysAcceptTrigger(int trigger);
|
||||
boolean shouldAlwaysDeclineTrigger(int trigger);
|
||||
void setShouldAlwaysAcceptTrigger(int trigger);
|
||||
void setShouldAlwaysDeclineTrigger(int trigger);
|
||||
void setShouldAlwaysAskTrigger(int trigger);
|
||||
void clearAutoYields();
|
||||
|
||||
void setCurrentPlayer(PlayerView player);
|
||||
}
|
||||
package forge.interfaces;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.deck.CardPool;
|
||||
import forge.game.GameEntityView;
|
||||
import forge.game.GameView;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.IHasIcon;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.spellability.SpellAbilityView;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.item.PaperCard;
|
||||
import forge.player.PlayerZoneUpdate;
|
||||
import forge.trackable.TrackableCollection;
|
||||
import forge.util.ITriggerEvent;
|
||||
|
||||
public interface IGuiGame {
|
||||
void setGameView(GameView gameView);
|
||||
void setOriginalGameController(PlayerView view, IGameController gameController);
|
||||
void setGameController(PlayerView player, IGameController gameController);
|
||||
void setSpectator(IGameController spectator);
|
||||
void openView(TrackableCollection<PlayerView> myPlayers);
|
||||
void afterGameEnd();
|
||||
void showCombat();
|
||||
void showPromptMessage(PlayerView playerView, String message);
|
||||
void showPromptMessage(PlayerView playerView, String message, CardView card);
|
||||
void updateButtons(PlayerView owner, boolean okEnabled, boolean cancelEnabled, boolean focusOk);
|
||||
void updateButtons(PlayerView owner, String label1, String label2, boolean enable1, boolean enable2, boolean focus1);
|
||||
void flashIncorrectAction();
|
||||
void updatePhase();
|
||||
void updateTurn(PlayerView player);
|
||||
void updatePlayerControl();
|
||||
void enableOverlay();
|
||||
void disableOverlay();
|
||||
void finishGame();
|
||||
void showManaPool(PlayerView player);
|
||||
void hideManaPool(PlayerView player);
|
||||
void updateStack();
|
||||
void updateZones(Iterable<PlayerZoneUpdate> zonesToUpdate);
|
||||
void updateSingleCard(CardView card);
|
||||
void updateCards(Iterable<CardView> cards);
|
||||
void refreshCardDetails(Iterable<CardView> cards);
|
||||
void updateManaPool(Iterable<PlayerView> manaPoolUpdate);
|
||||
void updateLives(Iterable<PlayerView> livesUpdate);
|
||||
void setPanelSelection(CardView hostCard);
|
||||
SpellAbilityView getAbilityToPlay(CardView hostCard, List<SpellAbilityView> abilities, ITriggerEvent triggerEvent);
|
||||
Map<CardView, Integer> assignDamage(CardView attacker, List<CardView> blockers, int damage, GameEntityView defender, boolean overrideOrder);
|
||||
|
||||
void message(String message);
|
||||
void message(String message, String title);
|
||||
|
||||
void showErrorDialog(String message);
|
||||
void showErrorDialog(String message, String title);
|
||||
|
||||
boolean showConfirmDialog(String message, String title);
|
||||
boolean showConfirmDialog(String message, String title, boolean defaultYes);
|
||||
boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText);
|
||||
boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText, boolean defaultYes);
|
||||
|
||||
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
|
||||
|
||||
String showInputDialog(String message, String title);
|
||||
String showInputDialog(String message, String title, FSkinProp icon);
|
||||
String showInputDialog(String message, String title, FSkinProp icon, String initialInput);
|
||||
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions);
|
||||
|
||||
boolean confirm(CardView c, String question);
|
||||
boolean confirm(CardView c, String question, List<String> options);
|
||||
boolean confirm(CardView c, String question, boolean defaultIsYes, List<String> options);
|
||||
|
||||
<T> List<T> getChoices(String message, int min, int max, List<T> choices);
|
||||
<T> List<T> getChoices(String message, int min, int max, List<T> choices, T selected, Function<T, String> display);
|
||||
|
||||
// Get Integer in range
|
||||
Integer getInteger(String message, int min);
|
||||
Integer getInteger(String message, int min, int max);
|
||||
Integer getInteger(String message, int min, int max, boolean sortDesc);
|
||||
Integer getInteger(String message, int min, int max, int cutoff);
|
||||
|
||||
/**
|
||||
* Convenience for getChoices(message, 0, 1, choices).
|
||||
*
|
||||
* @param <T>
|
||||
* is automatically inferred.
|
||||
* @param message
|
||||
* a {@link java.lang.String} object.
|
||||
* @param choices
|
||||
* a T object.
|
||||
* @return null if choices is missing, empty, or if the users' choices are
|
||||
* empty; otherwise, returns the first item in the List returned by
|
||||
* getChoices.
|
||||
* @see #getChoices(String, int, int, Object...)
|
||||
*/
|
||||
<T> T oneOrNone(String message, List<T> choices);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getChoice.
|
||||
* </p>
|
||||
*
|
||||
* @param <T>
|
||||
* a T object.
|
||||
* @param message
|
||||
* a {@link java.lang.String} object.
|
||||
* @param choices
|
||||
* a T object.
|
||||
* @return One of {@code choices}. Can only be {@code null} if {@code choices} is empty.
|
||||
*/
|
||||
<T> T one(String message, List<T> choices);
|
||||
|
||||
<T> void reveal(String message, List<T> items);
|
||||
|
||||
<T> List<T> many(String title, String topCaption, int cnt, List<T> sourceChoices, CardView c);
|
||||
<T> List<T> many(String title, String topCaption, int min, int max, List<T> sourceChoices, CardView c);
|
||||
|
||||
<T> List<T> order(String title, String top, List<T> sourceChoices, CardView c);
|
||||
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices, CardView referenceCard, boolean sideboardingMode);
|
||||
|
||||
/**
|
||||
* Ask the user to insert an object into a list of other objects. The
|
||||
* current implementation requires the user to cancel in order to get the
|
||||
* new item to be the first item in the resulting list.
|
||||
*
|
||||
* @param title
|
||||
* the dialog title.
|
||||
* @param newItem
|
||||
* the object to insert.
|
||||
* @param oldItems
|
||||
* the list of objects.
|
||||
* @return A shallow copy of the list of objects, with newItem inserted.
|
||||
*/
|
||||
<T> List<T> insertInList(String title, T newItem, List<T> oldItems);
|
||||
|
||||
List<PaperCard> sideboard(CardPool sideboard, CardPool main);
|
||||
GameEntityView chooseSingleEntityForEffect(String title, List<? extends GameEntityView> optionList, DelayedReveal delayedReveal, boolean isOptional); void setCard(CardView card);
|
||||
void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi);
|
||||
boolean openZones(Collection<ZoneType> zones, Map<PlayerView, Object> players);
|
||||
void restoreOldZones(Map<PlayerView, Object> playersToRestoreZonesFor);
|
||||
void setHighlighted(PlayerView pv, boolean b);
|
||||
void setUsedToPay(CardView card, boolean value);
|
||||
|
||||
void awaitNextInput();
|
||||
void cancelAwaitNextInput();
|
||||
|
||||
boolean isUiSetToSkipPhase(PlayerView playerTurn, PhaseType phase);
|
||||
void autoPassUntilEndOfTurn(PlayerView player);
|
||||
boolean mayAutoPass(PlayerView player);
|
||||
void autoPassCancel(PlayerView player);
|
||||
void updateAutoPassPrompt();
|
||||
boolean shouldAutoYield(String key);
|
||||
void setShouldAutoYield(String key, boolean autoYield);
|
||||
boolean shouldAlwaysAcceptTrigger(int trigger);
|
||||
boolean shouldAlwaysDeclineTrigger(int trigger);
|
||||
void setShouldAlwaysAcceptTrigger(int trigger);
|
||||
void setShouldAlwaysDeclineTrigger(int trigger);
|
||||
void setShouldAlwaysAskTrigger(int trigger);
|
||||
void clearAutoYields();
|
||||
|
||||
void setCurrentPlayer(PlayerView player);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package forge.interfaces;
|
||||
|
||||
public interface ILobbyView extends IUpdateable {
|
||||
void setPlayerChangeListener(IPlayerChangeListener iPlayerChangeListener);
|
||||
}
|
||||
package forge.interfaces;
|
||||
|
||||
public interface ILobbyView extends IUpdateable {
|
||||
void setPlayerChangeListener(IPlayerChangeListener iPlayerChangeListener);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package forge.interfaces;
|
||||
|
||||
public interface IProgressBar {
|
||||
void setDescription(String s0);
|
||||
void setValue(int progress);
|
||||
void reset();
|
||||
void setShowETA(boolean b0);
|
||||
void setShowCount(boolean b0);
|
||||
void setPercentMode(boolean percentMode0);
|
||||
int getMaximum();
|
||||
void setMaximum(int maximum0);
|
||||
}
|
||||
package forge.interfaces;
|
||||
|
||||
public interface IProgressBar {
|
||||
void setDescription(String s0);
|
||||
void setValue(int progress);
|
||||
void reset();
|
||||
void setShowETA(boolean b0);
|
||||
void setShowCount(boolean b0);
|
||||
void setPercentMode(boolean percentMode0);
|
||||
int getMaximum();
|
||||
void setMaximum(int maximum0);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package forge.interfaces;
|
||||
|
||||
public interface ITextField extends ITextComponent {
|
||||
boolean requestFocusInWindow();
|
||||
}
|
||||
package forge.interfaces;
|
||||
|
||||
public interface ITextField extends ITextComponent {
|
||||
boolean requestFocusInWindow();
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package forge.interfaces;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.item.PaperCard;
|
||||
|
||||
public interface IWinLoseView<T extends IButton> {
|
||||
T getBtnContinue();
|
||||
T getBtnRestart();
|
||||
T getBtnQuit();
|
||||
void hide();
|
||||
|
||||
void showRewards(Runnable runnable);
|
||||
void showCards(String title, List<PaperCard> cards);
|
||||
void showMessage(String message, String title, FSkinProp icon);
|
||||
}
|
||||
package forge.interfaces;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.item.PaperCard;
|
||||
|
||||
public interface IWinLoseView<T extends IButton> {
|
||||
T getBtnContinue();
|
||||
T getBtnRestart();
|
||||
T getBtnQuit();
|
||||
void hide();
|
||||
|
||||
void showRewards(Runnable runnable);
|
||||
void showCards(String title, List<PaperCard> cards);
|
||||
void showMessage(String message, String title, FSkinProp icon);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,171 +1,171 @@
|
||||
package forge.itemmanager;
|
||||
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.util.PredicateString.StringOp;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class BooleanExpression {
|
||||
private Stack<Operator> operators = new Stack<>();
|
||||
private Stack<Predicate<CardRules>> operands = new Stack<>();
|
||||
|
||||
private StringTokenizer expression;
|
||||
|
||||
private boolean inName, inType, inText, inCost;
|
||||
|
||||
public enum Operator {
|
||||
AND("&", 0), OR("|", 0), NOT("!", 1), OPEN_PAREN("(", 2), CLOSE_PAREN(")", 2), ESCAPE("\\", -1);
|
||||
|
||||
private final String token;
|
||||
private final int precedence;
|
||||
|
||||
Operator(final String token, final int precedence) {
|
||||
this.token = token;
|
||||
this.precedence = precedence;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.token;
|
||||
}
|
||||
}
|
||||
|
||||
public BooleanExpression(final String expression, final boolean inName, final boolean inType, final boolean inText, final boolean inCost) {
|
||||
this.expression = new StringTokenizer(expression);
|
||||
this.inName = inName;
|
||||
this.inType = inType;
|
||||
this.inText = inText;
|
||||
this.inCost = inCost;
|
||||
}
|
||||
|
||||
public Predicate<CardRules> evaluate() {
|
||||
|
||||
String currentValue = "";
|
||||
boolean escapeNext = false;
|
||||
|
||||
while (expression.hasNext()) {
|
||||
|
||||
String token = expression.next();
|
||||
Operator operator = null;
|
||||
|
||||
if (token.equals(Operator.AND.token)) {
|
||||
operator = Operator.AND;
|
||||
} else if (token.equals(Operator.OR.token)) {
|
||||
operator = Operator.OR;
|
||||
} else if (token.equals(Operator.OPEN_PAREN.token)) {
|
||||
operator = Operator.OPEN_PAREN;
|
||||
} else if (token.equals(Operator.CLOSE_PAREN.token)) {
|
||||
operator = Operator.CLOSE_PAREN;
|
||||
} else if (token.equals(Operator.NOT.token) && currentValue.trim().isEmpty()) { //Ignore ! operators that aren't the first token in a search term (Don't use '!' in 'Kaboom!')
|
||||
operator = Operator.NOT;
|
||||
} else if (token.equals(Operator.ESCAPE.token)) {
|
||||
escapeNext = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (operator == null) {
|
||||
currentValue += token;
|
||||
} else {
|
||||
|
||||
if (escapeNext) {
|
||||
escapeNext = false;
|
||||
currentValue += token;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!currentValue.trim().isEmpty()) {
|
||||
operands.push(valueOf(currentValue.trim()));
|
||||
}
|
||||
|
||||
currentValue = "";
|
||||
|
||||
if (!operators.isEmpty() && operator.precedence < operators.peek().precedence) {
|
||||
resolve(true);
|
||||
} else if (!operators.isEmpty() && operator == Operator.CLOSE_PAREN) {
|
||||
|
||||
while (!operators.isEmpty() && operators.peek() != Operator.OPEN_PAREN) {
|
||||
resolve(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
operators.push(operator);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!currentValue.trim().isEmpty()) {
|
||||
operands.push(valueOf(currentValue.trim()));
|
||||
}
|
||||
|
||||
while (!operators.isEmpty()) {
|
||||
resolve(true);
|
||||
}
|
||||
|
||||
return operands.get(0);
|
||||
|
||||
}
|
||||
|
||||
private void resolve(final boolean alwaysPopOperator) {
|
||||
|
||||
Predicate<CardRules> right;
|
||||
Predicate<CardRules> left;
|
||||
|
||||
switch (operators.peek()) {
|
||||
case AND:
|
||||
operators.pop();
|
||||
right = operands.pop();
|
||||
left = operands.pop();
|
||||
operands.push(Predicates.and(left, right));
|
||||
break;
|
||||
case OR:
|
||||
operators.pop();
|
||||
right = operands.pop();
|
||||
left = operands.pop();
|
||||
operands.push(Predicates.or(left, right));
|
||||
break;
|
||||
case NOT:
|
||||
operators.pop();
|
||||
left = operands.pop();
|
||||
operands.push(Predicates.not(left));
|
||||
break;
|
||||
default:
|
||||
if (alwaysPopOperator) {
|
||||
operators.pop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Predicate<CardRules> valueOf(final String value) {
|
||||
|
||||
List<Predicate<CardRules>> predicates = new ArrayList<>();
|
||||
if (inName) {
|
||||
predicates.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, value));
|
||||
}
|
||||
if (inType) {
|
||||
predicates.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, value));
|
||||
}
|
||||
if (inText) {
|
||||
predicates.add(CardRulesPredicates.rules(StringOp.CONTAINS_IC, value));
|
||||
}
|
||||
if (inCost) {
|
||||
predicates.add(CardRulesPredicates.cost(StringOp.CONTAINS_IC, value));
|
||||
}
|
||||
if (!predicates.isEmpty()) {
|
||||
return Predicates.or(predicates);
|
||||
}
|
||||
return Predicates.alwaysTrue();
|
||||
|
||||
}
|
||||
|
||||
public static boolean isExpression(final String string) {
|
||||
return string.contains(Operator.AND.token) || string.contains(Operator.OR.token) || string.trim().startsWith(Operator.NOT.token);
|
||||
}
|
||||
|
||||
}
|
||||
package forge.itemmanager;
|
||||
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.util.PredicateString.StringOp;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class BooleanExpression {
|
||||
private Stack<Operator> operators = new Stack<>();
|
||||
private Stack<Predicate<CardRules>> operands = new Stack<>();
|
||||
|
||||
private StringTokenizer expression;
|
||||
|
||||
private boolean inName, inType, inText, inCost;
|
||||
|
||||
public enum Operator {
|
||||
AND("&", 0), OR("|", 0), NOT("!", 1), OPEN_PAREN("(", 2), CLOSE_PAREN(")", 2), ESCAPE("\\", -1);
|
||||
|
||||
private final String token;
|
||||
private final int precedence;
|
||||
|
||||
Operator(final String token, final int precedence) {
|
||||
this.token = token;
|
||||
this.precedence = precedence;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.token;
|
||||
}
|
||||
}
|
||||
|
||||
public BooleanExpression(final String expression, final boolean inName, final boolean inType, final boolean inText, final boolean inCost) {
|
||||
this.expression = new StringTokenizer(expression);
|
||||
this.inName = inName;
|
||||
this.inType = inType;
|
||||
this.inText = inText;
|
||||
this.inCost = inCost;
|
||||
}
|
||||
|
||||
public Predicate<CardRules> evaluate() {
|
||||
|
||||
String currentValue = "";
|
||||
boolean escapeNext = false;
|
||||
|
||||
while (expression.hasNext()) {
|
||||
|
||||
String token = expression.next();
|
||||
Operator operator = null;
|
||||
|
||||
if (token.equals(Operator.AND.token)) {
|
||||
operator = Operator.AND;
|
||||
} else if (token.equals(Operator.OR.token)) {
|
||||
operator = Operator.OR;
|
||||
} else if (token.equals(Operator.OPEN_PAREN.token)) {
|
||||
operator = Operator.OPEN_PAREN;
|
||||
} else if (token.equals(Operator.CLOSE_PAREN.token)) {
|
||||
operator = Operator.CLOSE_PAREN;
|
||||
} else if (token.equals(Operator.NOT.token) && currentValue.trim().isEmpty()) { //Ignore ! operators that aren't the first token in a search term (Don't use '!' in 'Kaboom!')
|
||||
operator = Operator.NOT;
|
||||
} else if (token.equals(Operator.ESCAPE.token)) {
|
||||
escapeNext = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (operator == null) {
|
||||
currentValue += token;
|
||||
} else {
|
||||
|
||||
if (escapeNext) {
|
||||
escapeNext = false;
|
||||
currentValue += token;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!currentValue.trim().isEmpty()) {
|
||||
operands.push(valueOf(currentValue.trim()));
|
||||
}
|
||||
|
||||
currentValue = "";
|
||||
|
||||
if (!operators.isEmpty() && operator.precedence < operators.peek().precedence) {
|
||||
resolve(true);
|
||||
} else if (!operators.isEmpty() && operator == Operator.CLOSE_PAREN) {
|
||||
|
||||
while (!operators.isEmpty() && operators.peek() != Operator.OPEN_PAREN) {
|
||||
resolve(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
operators.push(operator);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!currentValue.trim().isEmpty()) {
|
||||
operands.push(valueOf(currentValue.trim()));
|
||||
}
|
||||
|
||||
while (!operators.isEmpty()) {
|
||||
resolve(true);
|
||||
}
|
||||
|
||||
return operands.get(0);
|
||||
|
||||
}
|
||||
|
||||
private void resolve(final boolean alwaysPopOperator) {
|
||||
|
||||
Predicate<CardRules> right;
|
||||
Predicate<CardRules> left;
|
||||
|
||||
switch (operators.peek()) {
|
||||
case AND:
|
||||
operators.pop();
|
||||
right = operands.pop();
|
||||
left = operands.pop();
|
||||
operands.push(Predicates.and(left, right));
|
||||
break;
|
||||
case OR:
|
||||
operators.pop();
|
||||
right = operands.pop();
|
||||
left = operands.pop();
|
||||
operands.push(Predicates.or(left, right));
|
||||
break;
|
||||
case NOT:
|
||||
operators.pop();
|
||||
left = operands.pop();
|
||||
operands.push(Predicates.not(left));
|
||||
break;
|
||||
default:
|
||||
if (alwaysPopOperator) {
|
||||
operators.pop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Predicate<CardRules> valueOf(final String value) {
|
||||
|
||||
List<Predicate<CardRules>> predicates = new ArrayList<>();
|
||||
if (inName) {
|
||||
predicates.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, value));
|
||||
}
|
||||
if (inType) {
|
||||
predicates.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, value));
|
||||
}
|
||||
if (inText) {
|
||||
predicates.add(CardRulesPredicates.rules(StringOp.CONTAINS_IC, value));
|
||||
}
|
||||
if (inCost) {
|
||||
predicates.add(CardRulesPredicates.cost(StringOp.CONTAINS_IC, value));
|
||||
}
|
||||
if (!predicates.isEmpty()) {
|
||||
return Predicates.or(predicates);
|
||||
}
|
||||
return Predicates.alwaysTrue();
|
||||
|
||||
}
|
||||
|
||||
public static boolean isExpression(final String string) {
|
||||
return string.contains(Operator.AND.token) || string.contains(Operator.OR.token) || string.trim().startsWith(Operator.NOT.token);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,275 +1,275 @@
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardType;
|
||||
import forge.card.ColorSet;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
|
||||
public enum GroupDef {
|
||||
COLOR("Color", getColorGroups(),
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
return getColorGroup(((PaperCard) item).getRules().getColor());
|
||||
}
|
||||
else if (item instanceof DeckProxy) {
|
||||
return getColorGroup(((DeckProxy) item).getColor());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}),
|
||||
COLOR_IDENTITY("Color Identity", getColorGroups(),
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
return getColorGroup(((PaperCard) item).getRules().getColorIdentity());
|
||||
}
|
||||
else if (item instanceof DeckProxy) {
|
||||
return getColorGroup(((DeckProxy) item).getColorIdentity());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}),
|
||||
SET("Set", getSetGroups(),
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
return getSetGroup(((PaperCard) item).getEdition());
|
||||
}
|
||||
else if (item instanceof DeckProxy) {
|
||||
return getSetGroup(((DeckProxy) item).getEdition().getCode());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}),
|
||||
DEFAULT("Default",
|
||||
new String[] { "Creatures", "Spells", "Lands" },
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
if (groupIndex == 2) {
|
||||
return ColumnDef.NAME; //pile lands by name regardless
|
||||
}
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
CardType type = ((PaperCard) item).getRules().getType();
|
||||
if (type.isCreature()) {
|
||||
return 0;
|
||||
}
|
||||
if (type.isLand()) { //make Artifact Lands appear in Lands group
|
||||
return 2;
|
||||
}
|
||||
if (type.isArtifact() || type.isEnchantment() || type.isPlaneswalker() || type.isInstant() || type.isSorcery()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}),
|
||||
CARD_TYPE("Type",
|
||||
new String[] { "Creatures", "Artifacts", "Enchantments", "Planeswalkers", "Instants", "Sorceries", "Lands" },
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
if (groupIndex == 6) {
|
||||
return ColumnDef.NAME; //pile lands by name regardless
|
||||
}
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
CardType type = ((PaperCard) item).getRules().getType();
|
||||
if (type.isCreature()) { //make Artifact and Land Creatures appear in Creatures group
|
||||
return 0;
|
||||
}
|
||||
if (type.isLand()) { //make Artifact Lands appear in Lands group
|
||||
return 6;
|
||||
}
|
||||
if (type.isArtifact()) {
|
||||
return 1;
|
||||
}
|
||||
if (type.isEnchantment()) {
|
||||
return 2;
|
||||
}
|
||||
if (type.isPlaneswalker()) {
|
||||
return 3;
|
||||
}
|
||||
if (type.isInstant()) {
|
||||
return 4;
|
||||
}
|
||||
if (type.isSorcery()) {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}),
|
||||
CARD_RARITY("Rarity",
|
||||
new String[] { "Mythic Rares", "Rares", "Uncommons", "Commons", "Basic Lands" },
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
switch (((PaperCard) item).getRarity()) {
|
||||
case MythicRare:
|
||||
return 0;
|
||||
case Rare:
|
||||
return 1;
|
||||
case Uncommon:
|
||||
return 2;
|
||||
case Common:
|
||||
return 3;
|
||||
case BasicLand:
|
||||
return 4;
|
||||
default:
|
||||
return -1; //show Special and Unknown in "Other" group
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
|
||||
GroupDef(String name0, String[] groups0, Function<Integer, ColumnDef> fnGetPileByOverride0, Function<InventoryItem, Integer> fnGroupItem0) {
|
||||
this.name = name0;
|
||||
this.groups = groups0;
|
||||
this.fnGetPileByOverride = fnGetPileByOverride0;
|
||||
this.fnGroupItem = fnGroupItem0;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final String[] groups;
|
||||
private final Function<Integer, ColumnDef> fnGetPileByOverride;
|
||||
private final Function<InventoryItem, Integer> fnGroupItem;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String[] getGroups() {
|
||||
return this.groups;
|
||||
}
|
||||
|
||||
public ColumnDef getGroupPileBy(int groupIndex, ColumnDef defaultPileBy) {
|
||||
ColumnDef pileBy = this.fnGetPileByOverride.apply(groupIndex);
|
||||
if (pileBy == null) {
|
||||
return defaultPileBy;
|
||||
}
|
||||
return pileBy;
|
||||
}
|
||||
|
||||
public int getItemGroupIndex(InventoryItem item) {
|
||||
return this.fnGroupItem.apply(item);
|
||||
}
|
||||
|
||||
private static String[] getColorGroups() {
|
||||
//TODO: Support breaking up Multicolor into separate groups for each color combination
|
||||
return new String[] { "White", "Blue", "Black", "Red", "Green", "Multicolor", "Colorless" };
|
||||
}
|
||||
|
||||
private static Integer getColorGroup(ColorSet color) {
|
||||
if (color == null) {
|
||||
return -1;
|
||||
}
|
||||
if (color.isColorless()) {
|
||||
return 6;
|
||||
}
|
||||
if (color.isMulticolor()) {
|
||||
return 5;
|
||||
}
|
||||
if (color.hasWhite()) {
|
||||
return 0;
|
||||
}
|
||||
if (color.hasBlue()) {
|
||||
return 1;
|
||||
}
|
||||
if (color.hasBlack()) {
|
||||
return 2;
|
||||
}
|
||||
if (color.hasRed()) {
|
||||
return 3;
|
||||
}
|
||||
if (color.hasGreen()) {
|
||||
return 4;
|
||||
}
|
||||
return -1; //shouldn't happen
|
||||
}
|
||||
|
||||
private static Map<String, Integer> setGroupMap;
|
||||
|
||||
private static String[] getSetGroups() {
|
||||
setGroupMap = new HashMap<String, Integer>(); //cache mappings to make lookup quicker later
|
||||
|
||||
//build sorted list of sets
|
||||
List<CardEdition> sortedSets = Lists.newArrayList(FModel.getMagicDb().getEditions());
|
||||
Collections.sort(sortedSets);
|
||||
Collections.reverse(sortedSets);
|
||||
|
||||
int groupNum = 0;
|
||||
String[] setGroups = new String[sortedSets.size()];
|
||||
for (CardEdition set : sortedSets) {
|
||||
setGroups[groupNum] = set.getName();
|
||||
setGroupMap.put(set.getCode(), groupNum);
|
||||
groupNum++;
|
||||
}
|
||||
return setGroups;
|
||||
}
|
||||
|
||||
private static Integer getSetGroup(String set) {
|
||||
Integer groupNum = setGroupMap.get(set);
|
||||
if (groupNum == null) {
|
||||
groupNum = -1;
|
||||
}
|
||||
return groupNum;
|
||||
}
|
||||
}
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardType;
|
||||
import forge.card.ColorSet;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
|
||||
public enum GroupDef {
|
||||
COLOR("Color", getColorGroups(),
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
return getColorGroup(((PaperCard) item).getRules().getColor());
|
||||
}
|
||||
else if (item instanceof DeckProxy) {
|
||||
return getColorGroup(((DeckProxy) item).getColor());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}),
|
||||
COLOR_IDENTITY("Color Identity", getColorGroups(),
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
return getColorGroup(((PaperCard) item).getRules().getColorIdentity());
|
||||
}
|
||||
else if (item instanceof DeckProxy) {
|
||||
return getColorGroup(((DeckProxy) item).getColorIdentity());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}),
|
||||
SET("Set", getSetGroups(),
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
return getSetGroup(((PaperCard) item).getEdition());
|
||||
}
|
||||
else if (item instanceof DeckProxy) {
|
||||
return getSetGroup(((DeckProxy) item).getEdition().getCode());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}),
|
||||
DEFAULT("Default",
|
||||
new String[] { "Creatures", "Spells", "Lands" },
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
if (groupIndex == 2) {
|
||||
return ColumnDef.NAME; //pile lands by name regardless
|
||||
}
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
CardType type = ((PaperCard) item).getRules().getType();
|
||||
if (type.isCreature()) {
|
||||
return 0;
|
||||
}
|
||||
if (type.isLand()) { //make Artifact Lands appear in Lands group
|
||||
return 2;
|
||||
}
|
||||
if (type.isArtifact() || type.isEnchantment() || type.isPlaneswalker() || type.isInstant() || type.isSorcery()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}),
|
||||
CARD_TYPE("Type",
|
||||
new String[] { "Creatures", "Artifacts", "Enchantments", "Planeswalkers", "Instants", "Sorceries", "Lands" },
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
if (groupIndex == 6) {
|
||||
return ColumnDef.NAME; //pile lands by name regardless
|
||||
}
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
CardType type = ((PaperCard) item).getRules().getType();
|
||||
if (type.isCreature()) { //make Artifact and Land Creatures appear in Creatures group
|
||||
return 0;
|
||||
}
|
||||
if (type.isLand()) { //make Artifact Lands appear in Lands group
|
||||
return 6;
|
||||
}
|
||||
if (type.isArtifact()) {
|
||||
return 1;
|
||||
}
|
||||
if (type.isEnchantment()) {
|
||||
return 2;
|
||||
}
|
||||
if (type.isPlaneswalker()) {
|
||||
return 3;
|
||||
}
|
||||
if (type.isInstant()) {
|
||||
return 4;
|
||||
}
|
||||
if (type.isSorcery()) {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}),
|
||||
CARD_RARITY("Rarity",
|
||||
new String[] { "Mythic Rares", "Rares", "Uncommons", "Commons", "Basic Lands" },
|
||||
new Function<Integer, ColumnDef>() {
|
||||
@Override
|
||||
public ColumnDef apply(final Integer groupIndex) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
new Function<InventoryItem, Integer>() {
|
||||
@Override
|
||||
public Integer apply(final InventoryItem item) {
|
||||
if (item instanceof PaperCard) {
|
||||
switch (((PaperCard) item).getRarity()) {
|
||||
case MythicRare:
|
||||
return 0;
|
||||
case Rare:
|
||||
return 1;
|
||||
case Uncommon:
|
||||
return 2;
|
||||
case Common:
|
||||
return 3;
|
||||
case BasicLand:
|
||||
return 4;
|
||||
default:
|
||||
return -1; //show Special and Unknown in "Other" group
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
|
||||
GroupDef(String name0, String[] groups0, Function<Integer, ColumnDef> fnGetPileByOverride0, Function<InventoryItem, Integer> fnGroupItem0) {
|
||||
this.name = name0;
|
||||
this.groups = groups0;
|
||||
this.fnGetPileByOverride = fnGetPileByOverride0;
|
||||
this.fnGroupItem = fnGroupItem0;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final String[] groups;
|
||||
private final Function<Integer, ColumnDef> fnGetPileByOverride;
|
||||
private final Function<InventoryItem, Integer> fnGroupItem;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String[] getGroups() {
|
||||
return this.groups;
|
||||
}
|
||||
|
||||
public ColumnDef getGroupPileBy(int groupIndex, ColumnDef defaultPileBy) {
|
||||
ColumnDef pileBy = this.fnGetPileByOverride.apply(groupIndex);
|
||||
if (pileBy == null) {
|
||||
return defaultPileBy;
|
||||
}
|
||||
return pileBy;
|
||||
}
|
||||
|
||||
public int getItemGroupIndex(InventoryItem item) {
|
||||
return this.fnGroupItem.apply(item);
|
||||
}
|
||||
|
||||
private static String[] getColorGroups() {
|
||||
//TODO: Support breaking up Multicolor into separate groups for each color combination
|
||||
return new String[] { "White", "Blue", "Black", "Red", "Green", "Multicolor", "Colorless" };
|
||||
}
|
||||
|
||||
private static Integer getColorGroup(ColorSet color) {
|
||||
if (color == null) {
|
||||
return -1;
|
||||
}
|
||||
if (color.isColorless()) {
|
||||
return 6;
|
||||
}
|
||||
if (color.isMulticolor()) {
|
||||
return 5;
|
||||
}
|
||||
if (color.hasWhite()) {
|
||||
return 0;
|
||||
}
|
||||
if (color.hasBlue()) {
|
||||
return 1;
|
||||
}
|
||||
if (color.hasBlack()) {
|
||||
return 2;
|
||||
}
|
||||
if (color.hasRed()) {
|
||||
return 3;
|
||||
}
|
||||
if (color.hasGreen()) {
|
||||
return 4;
|
||||
}
|
||||
return -1; //shouldn't happen
|
||||
}
|
||||
|
||||
private static Map<String, Integer> setGroupMap;
|
||||
|
||||
private static String[] getSetGroups() {
|
||||
setGroupMap = new HashMap<String, Integer>(); //cache mappings to make lookup quicker later
|
||||
|
||||
//build sorted list of sets
|
||||
List<CardEdition> sortedSets = Lists.newArrayList(FModel.getMagicDb().getEditions());
|
||||
Collections.sort(sortedSets);
|
||||
Collections.reverse(sortedSets);
|
||||
|
||||
int groupNum = 0;
|
||||
String[] setGroups = new String[sortedSets.size()];
|
||||
for (CardEdition set : sortedSets) {
|
||||
setGroups[groupNum] = set.getName();
|
||||
setGroupMap.put(set.getCode(), groupNum);
|
||||
groupNum++;
|
||||
}
|
||||
return setGroups;
|
||||
}
|
||||
|
||||
private static Integer getSetGroup(String set) {
|
||||
Integer groupNum = setGroupMap.get(set);
|
||||
if (groupNum == null) {
|
||||
groupNum = -1;
|
||||
}
|
||||
return groupNum;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
import forge.util.ItemPool;
|
||||
|
||||
public interface IItemManager<T extends InventoryItem> {
|
||||
ItemManagerConfig getConfig();
|
||||
void setup(ItemManagerConfig config0);
|
||||
Class<T> getGenericType();
|
||||
String getCaption();
|
||||
void setCaption(String caption);
|
||||
ItemPool<T> getPool();
|
||||
void setPool(final Iterable<T> items);
|
||||
void setPool(final ItemPool<T> poolView, boolean infinite);
|
||||
void setPool(final ItemPool<T> pool0);
|
||||
int getItemCount();
|
||||
int getSelectionCount();
|
||||
T getSelectedItem();
|
||||
Collection<T> getSelectedItems();
|
||||
ItemPool<T> getSelectedItemPool();
|
||||
boolean setSelectedItem(T item);
|
||||
boolean setSelectedItems(Iterable<T> items);
|
||||
T stringToItem(String str);
|
||||
boolean setSelectedString(String str);
|
||||
boolean setSelectedStrings(Iterable<String> strings);
|
||||
boolean selectItemEntrys(Iterable<Entry<T, Integer>> itemEntrys);
|
||||
void selectAll();
|
||||
int getSelectedIndex();
|
||||
Iterable<Integer> getSelectedIndices();
|
||||
void setSelectedIndex(int index);
|
||||
void setSelectedIndices(Integer[] indices);
|
||||
void setSelectedIndices(Iterable<Integer> indices);
|
||||
void addItem(final T item, int qty);
|
||||
void addItems(Iterable<Entry<T, Integer>> itemsToAdd);
|
||||
void removeItem(final T item, int qty);
|
||||
void removeItems(Iterable<Map.Entry<T, Integer>> itemsToRemove);
|
||||
void removeAllItems();
|
||||
void scrollSelectionIntoView();
|
||||
int getItemCount(final T item);
|
||||
ItemPool<T> getFilteredItems();
|
||||
boolean applyFilters();
|
||||
}
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
import forge.util.ItemPool;
|
||||
|
||||
public interface IItemManager<T extends InventoryItem> {
|
||||
ItemManagerConfig getConfig();
|
||||
void setup(ItemManagerConfig config0);
|
||||
Class<T> getGenericType();
|
||||
String getCaption();
|
||||
void setCaption(String caption);
|
||||
ItemPool<T> getPool();
|
||||
void setPool(final Iterable<T> items);
|
||||
void setPool(final ItemPool<T> poolView, boolean infinite);
|
||||
void setPool(final ItemPool<T> pool0);
|
||||
int getItemCount();
|
||||
int getSelectionCount();
|
||||
T getSelectedItem();
|
||||
Collection<T> getSelectedItems();
|
||||
ItemPool<T> getSelectedItemPool();
|
||||
boolean setSelectedItem(T item);
|
||||
boolean setSelectedItems(Iterable<T> items);
|
||||
T stringToItem(String str);
|
||||
boolean setSelectedString(String str);
|
||||
boolean setSelectedStrings(Iterable<String> strings);
|
||||
boolean selectItemEntrys(Iterable<Entry<T, Integer>> itemEntrys);
|
||||
void selectAll();
|
||||
int getSelectedIndex();
|
||||
Iterable<Integer> getSelectedIndices();
|
||||
void setSelectedIndex(int index);
|
||||
void setSelectedIndices(Integer[] indices);
|
||||
void setSelectedIndices(Iterable<Integer> indices);
|
||||
void addItem(final T item, int qty);
|
||||
void addItems(Iterable<Entry<T, Integer>> itemsToAdd);
|
||||
void removeItem(final T item, int qty);
|
||||
void removeItems(Iterable<Map.Entry<T, Integer>> itemsToRemove);
|
||||
void removeAllItems();
|
||||
void scrollSelectionIntoView();
|
||||
int getItemCount(final T item);
|
||||
ItemPool<T> getFilteredItems();
|
||||
boolean applyFilters();
|
||||
}
|
||||
|
||||
@@ -1,122 +1,122 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.itemmanager;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
import forge.itemmanager.ItemColumnConfig.SortState;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
|
||||
public class ItemColumn {
|
||||
private final ItemColumnConfig config;
|
||||
private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort;
|
||||
private final Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay;
|
||||
|
||||
public ItemColumn(ItemColumnConfig config0) {
|
||||
this(config0, config0.getFnSort(), config0.getFnDisplay());
|
||||
}
|
||||
public ItemColumn(ItemColumnConfig config0,
|
||||
Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort0,
|
||||
Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay0) {
|
||||
if (fnSort0 == null) {
|
||||
throw new NullPointerException("A sort function hasn't been set for column " + config0.getLongName());
|
||||
}
|
||||
if (fnDisplay0 == null) {
|
||||
throw new NullPointerException("A display function hasn't been set for column " + config0.getLongName());
|
||||
}
|
||||
|
||||
config = config0;
|
||||
fnSort = fnSort0;
|
||||
fnDisplay = fnDisplay0;
|
||||
}
|
||||
|
||||
public ItemColumnConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return config.getShortName();
|
||||
}
|
||||
|
||||
public String getLongName() {
|
||||
return config.getLongName();
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return config.getIndex();
|
||||
}
|
||||
|
||||
public void setIndex(final int index0) {
|
||||
config.setIndex(index0);
|
||||
}
|
||||
|
||||
public int getSortPriority() {
|
||||
return config.getSortPriority();
|
||||
}
|
||||
|
||||
public void setSortPriority(final int sortPriority0) {
|
||||
config.setSortPriority(sortPriority0);
|
||||
}
|
||||
|
||||
public SortState getSortState() {
|
||||
return config.getSortState();
|
||||
}
|
||||
|
||||
public void setSortState(final SortState state0) {
|
||||
config.setSortState(state0);
|
||||
}
|
||||
|
||||
public SortState getDefaultSortState() {
|
||||
return config.getDefaultSortState();
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return config.isVisible();
|
||||
}
|
||||
|
||||
public void setVisible(boolean visible0) {
|
||||
config.setVisible(visible0);
|
||||
}
|
||||
|
||||
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnSort() {
|
||||
return fnSort;
|
||||
}
|
||||
|
||||
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnDisplay() {
|
||||
return fnDisplay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return config.getLongName();
|
||||
}
|
||||
|
||||
public static void addColOverride(ItemManagerConfig config, Map<ColumnDef, ItemColumn> colOverrides, ColumnDef colDef) {
|
||||
ItemColumnConfig colConfig = config.getCols().get(colDef);
|
||||
addColOverride(config, colOverrides, colDef, colConfig.getFnSort(), colConfig.getFnDisplay());
|
||||
}
|
||||
public static void addColOverride(ItemManagerConfig config, Map<ColumnDef, ItemColumn> colOverrides, ColumnDef colDef,
|
||||
Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort0,
|
||||
Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay0) {
|
||||
colOverrides.put(colDef, new ItemColumn(config.getCols().get(colDef), fnSort0, fnDisplay0));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.itemmanager;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
import forge.itemmanager.ItemColumnConfig.SortState;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
|
||||
public class ItemColumn {
|
||||
private final ItemColumnConfig config;
|
||||
private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort;
|
||||
private final Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay;
|
||||
|
||||
public ItemColumn(ItemColumnConfig config0) {
|
||||
this(config0, config0.getFnSort(), config0.getFnDisplay());
|
||||
}
|
||||
public ItemColumn(ItemColumnConfig config0,
|
||||
Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort0,
|
||||
Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay0) {
|
||||
if (fnSort0 == null) {
|
||||
throw new NullPointerException("A sort function hasn't been set for column " + config0.getLongName());
|
||||
}
|
||||
if (fnDisplay0 == null) {
|
||||
throw new NullPointerException("A display function hasn't been set for column " + config0.getLongName());
|
||||
}
|
||||
|
||||
config = config0;
|
||||
fnSort = fnSort0;
|
||||
fnDisplay = fnDisplay0;
|
||||
}
|
||||
|
||||
public ItemColumnConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return config.getShortName();
|
||||
}
|
||||
|
||||
public String getLongName() {
|
||||
return config.getLongName();
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return config.getIndex();
|
||||
}
|
||||
|
||||
public void setIndex(final int index0) {
|
||||
config.setIndex(index0);
|
||||
}
|
||||
|
||||
public int getSortPriority() {
|
||||
return config.getSortPriority();
|
||||
}
|
||||
|
||||
public void setSortPriority(final int sortPriority0) {
|
||||
config.setSortPriority(sortPriority0);
|
||||
}
|
||||
|
||||
public SortState getSortState() {
|
||||
return config.getSortState();
|
||||
}
|
||||
|
||||
public void setSortState(final SortState state0) {
|
||||
config.setSortState(state0);
|
||||
}
|
||||
|
||||
public SortState getDefaultSortState() {
|
||||
return config.getDefaultSortState();
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return config.isVisible();
|
||||
}
|
||||
|
||||
public void setVisible(boolean visible0) {
|
||||
config.setVisible(visible0);
|
||||
}
|
||||
|
||||
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnSort() {
|
||||
return fnSort;
|
||||
}
|
||||
|
||||
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnDisplay() {
|
||||
return fnDisplay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return config.getLongName();
|
||||
}
|
||||
|
||||
public static void addColOverride(ItemManagerConfig config, Map<ColumnDef, ItemColumn> colOverrides, ColumnDef colDef) {
|
||||
ItemColumnConfig colConfig = config.getCols().get(colDef);
|
||||
addColOverride(config, colOverrides, colDef, colConfig.getFnSort(), colConfig.getFnDisplay());
|
||||
}
|
||||
public static void addColOverride(ItemManagerConfig config, Map<ColumnDef, ItemColumn> colOverrides, ColumnDef colDef,
|
||||
Function<Entry<InventoryItem, Integer>, Comparable<?>> fnSort0,
|
||||
Function<Entry<? extends InventoryItem, Integer>, Object> fnDisplay0) {
|
||||
colOverrides.put(colDef, new ItemColumn(config.getCols().get(colDef), fnSort0, fnDisplay0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,120 +1,120 @@
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
|
||||
public class ItemColumnConfig {
|
||||
public static enum SortState {
|
||||
NONE,
|
||||
ASC,
|
||||
DESC
|
||||
}
|
||||
|
||||
private final ColumnDef def;
|
||||
private SortState sortState = SortState.NONE;
|
||||
private int preferredWidth;
|
||||
private int sortPriority = 0;
|
||||
private boolean visible = true;
|
||||
private int index = 0;
|
||||
private ItemColumnConfig defaults;
|
||||
|
||||
public ItemColumnConfig(ColumnDef def0) {
|
||||
this.def = def0;
|
||||
this.preferredWidth = def0.preferredWidth;
|
||||
}
|
||||
private ItemColumnConfig(ItemColumnConfig from) {
|
||||
this.def = from.def;
|
||||
this.sortState = from.sortState;
|
||||
this.preferredWidth = from.preferredWidth;
|
||||
this.sortPriority = from.sortPriority;
|
||||
this.visible = from.visible;
|
||||
this.index = from.index;
|
||||
}
|
||||
|
||||
public ColumnDef getDef() {
|
||||
return this.def;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return this.def.shortName;
|
||||
}
|
||||
|
||||
public String getLongName() {
|
||||
return this.def.longName;
|
||||
}
|
||||
|
||||
public int getPreferredWidth() {
|
||||
return this.preferredWidth;
|
||||
}
|
||||
|
||||
public void setPreferredWidth(int preferredWidth0) {
|
||||
this.preferredWidth = preferredWidth0;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
public void setIndex(final int index0) {
|
||||
this.index = index0;
|
||||
}
|
||||
|
||||
public int getSortPriority() {
|
||||
return sortPriority;
|
||||
}
|
||||
|
||||
public void setSortPriority(final int sortPriority0) {
|
||||
int oldSortPriority = this.sortPriority;
|
||||
this.sortPriority = sortPriority0;
|
||||
if (sortPriority0 == 0) {
|
||||
this.sortState = SortState.NONE;
|
||||
}
|
||||
else if (oldSortPriority == 0) {
|
||||
this.sortState = def.sortState;
|
||||
}
|
||||
}
|
||||
|
||||
public SortState getSortState() {
|
||||
return this.sortState;
|
||||
}
|
||||
|
||||
public void setSortState(final SortState state0) {
|
||||
this.sortState = state0;
|
||||
}
|
||||
|
||||
public SortState getDefaultSortState() {
|
||||
return this.def.sortState;
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return this.visible;
|
||||
}
|
||||
|
||||
public void setVisible(boolean visible0) {
|
||||
this.visible = visible0;
|
||||
}
|
||||
|
||||
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnSort() {
|
||||
return this.def.fnSort;
|
||||
}
|
||||
|
||||
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnDisplay() {
|
||||
return this.def.fnDisplay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getLongName();
|
||||
}
|
||||
|
||||
public void establishDefaults() {
|
||||
this.defaults = new ItemColumnConfig(this);
|
||||
}
|
||||
|
||||
public ItemColumnConfig getDefaults() {
|
||||
return this.defaults;
|
||||
}
|
||||
}
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
|
||||
public class ItemColumnConfig {
|
||||
public static enum SortState {
|
||||
NONE,
|
||||
ASC,
|
||||
DESC
|
||||
}
|
||||
|
||||
private final ColumnDef def;
|
||||
private SortState sortState = SortState.NONE;
|
||||
private int preferredWidth;
|
||||
private int sortPriority = 0;
|
||||
private boolean visible = true;
|
||||
private int index = 0;
|
||||
private ItemColumnConfig defaults;
|
||||
|
||||
public ItemColumnConfig(ColumnDef def0) {
|
||||
this.def = def0;
|
||||
this.preferredWidth = def0.preferredWidth;
|
||||
}
|
||||
private ItemColumnConfig(ItemColumnConfig from) {
|
||||
this.def = from.def;
|
||||
this.sortState = from.sortState;
|
||||
this.preferredWidth = from.preferredWidth;
|
||||
this.sortPriority = from.sortPriority;
|
||||
this.visible = from.visible;
|
||||
this.index = from.index;
|
||||
}
|
||||
|
||||
public ColumnDef getDef() {
|
||||
return this.def;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return this.def.shortName;
|
||||
}
|
||||
|
||||
public String getLongName() {
|
||||
return this.def.longName;
|
||||
}
|
||||
|
||||
public int getPreferredWidth() {
|
||||
return this.preferredWidth;
|
||||
}
|
||||
|
||||
public void setPreferredWidth(int preferredWidth0) {
|
||||
this.preferredWidth = preferredWidth0;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
public void setIndex(final int index0) {
|
||||
this.index = index0;
|
||||
}
|
||||
|
||||
public int getSortPriority() {
|
||||
return sortPriority;
|
||||
}
|
||||
|
||||
public void setSortPriority(final int sortPriority0) {
|
||||
int oldSortPriority = this.sortPriority;
|
||||
this.sortPriority = sortPriority0;
|
||||
if (sortPriority0 == 0) {
|
||||
this.sortState = SortState.NONE;
|
||||
}
|
||||
else if (oldSortPriority == 0) {
|
||||
this.sortState = def.sortState;
|
||||
}
|
||||
}
|
||||
|
||||
public SortState getSortState() {
|
||||
return this.sortState;
|
||||
}
|
||||
|
||||
public void setSortState(final SortState state0) {
|
||||
this.sortState = state0;
|
||||
}
|
||||
|
||||
public SortState getDefaultSortState() {
|
||||
return this.def.sortState;
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return this.visible;
|
||||
}
|
||||
|
||||
public void setVisible(boolean visible0) {
|
||||
this.visible = visible0;
|
||||
}
|
||||
|
||||
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnSort() {
|
||||
return this.def.fnSort;
|
||||
}
|
||||
|
||||
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnDisplay() {
|
||||
return this.def.fnDisplay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getLongName();
|
||||
}
|
||||
|
||||
public void establishDefaults() {
|
||||
this.defaults = new ItemColumnConfig(this);
|
||||
}
|
||||
|
||||
public ItemColumnConfig getDefaults() {
|
||||
return this.defaults;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,352 +1,352 @@
|
||||
package forge.itemmanager;
|
||||
|
||||
import forge.itemmanager.ItemColumnConfig.SortState;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Preferences associated with individual cards
|
||||
*
|
||||
*/
|
||||
public enum ItemManagerConfig {
|
||||
STRING_ONLY(SColumnUtil.getStringColumn(), false, false, true,
|
||||
null, null, 1, 0),
|
||||
CARD_CATALOG(SColumnUtil.getCatalogDefaultColumns(true), true, true, false,
|
||||
null, null, 4, 0),
|
||||
DECK_EDITOR(SColumnUtil.getDeckEditorDefaultColumns(), false, false, true,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
DRAFT_PACK(SColumnUtil.getDraftPackDefaultColumns(), false, false, true,
|
||||
null, null, 4, 1),
|
||||
DRAFT_POOL(SColumnUtil.getCatalogDefaultColumns(false), false, false, false,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
DRAFT_CONSPIRACY(SColumnUtil.getSpecialCardPoolDefaultColumns(), false, false, true,
|
||||
null, null, 4, 0),
|
||||
SEALED_POOL(SColumnUtil.getCatalogDefaultColumns(false), false, false, false,
|
||||
GroupDef.COLOR, ColumnDef.CMC, 4, 1),
|
||||
SPELL_SHOP(SColumnUtil.getSpellShopDefaultColumns(), false, false, false,
|
||||
null, null, 4, 0),
|
||||
QUEST_INVENTORY(SColumnUtil.getQuestInventoryDefaultColumns(), false, false, false,
|
||||
null, null, 4, 0),
|
||||
QUEST_EDITOR_POOL(SColumnUtil.getQuestEditorPoolDefaultColumns(), false, false, false,
|
||||
null, null, 4, 0),
|
||||
QUEST_DECK_EDITOR(SColumnUtil.getQuestDeckEditorDefaultColumns(), false, false, false,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
QUEST_DRAFT_DECK_VIEWER(SColumnUtil.getDeckViewerDefaultColumns(), false, false, true,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
CONQUEST_AETHER(SColumnUtil.getConquestAEtherDefaultColumns(), false, false, false,
|
||||
null, null, 4, 0),
|
||||
CONQUEST_COMMANDERS(SColumnUtil.getConquestCommandersDefaultColumns(), false, false, false,
|
||||
null, null, 3, 0),
|
||||
CONQUEST_COLLECTION(SColumnUtil.getConquestCollectionDefaultColumns(), false, false, false,
|
||||
null, null, 4, 0),
|
||||
CONQUEST_DECK_EDITOR(SColumnUtil.getConquestDeckEditorDefaultColumns(), false, false, false,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
AVATAR_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, false,
|
||||
null, null, 4, 0),
|
||||
SCHEME_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
|
||||
null, null, 4, 0),
|
||||
CONSPIRACY_DECKS(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
|
||||
null, null, 4, 0),
|
||||
SCHEME_DECK_EDITOR(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
|
||||
null, null, 4, 0),
|
||||
PLANAR_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
|
||||
null, null, 4, 0),
|
||||
PLANAR_DECK_EDITOR(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
|
||||
null, null, 4, 0),
|
||||
COMMANDER_POOL(SColumnUtil.getCatalogDefaultColumns(true), true, false, false,
|
||||
null, null, 4, 0),
|
||||
COMMANDER_SECTION(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
|
||||
null, null, 1, 1),
|
||||
WORKSHOP_CATALOG(SColumnUtil.getCatalogDefaultColumns(true), true, true, false,
|
||||
null, null, 4, 0),
|
||||
DECK_VIEWER(SColumnUtil.getDeckViewerDefaultColumns(), false, false, false,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
CONSTRUCTED_DECKS(SColumnUtil.getDecksDefaultColumns(true, true), false, false, false,
|
||||
null, null, 3, 0),
|
||||
COMMANDER_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
PLANAR_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
SCHEME_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
VANGUARDS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, true,
|
||||
null, null, 3, 0),
|
||||
DRAFT_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
SEALED_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
WINSTON_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
QUEST_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
PRECON_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
QUEST_EVENT_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
NET_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
SIDEBOARD(SColumnUtil.getDeckEditorDefaultColumns(), false, false, true,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 3, 0);
|
||||
|
||||
private Map<ColumnDef, ItemColumnConfig> cols;
|
||||
private boolean showUniqueCardsOption;
|
||||
|
||||
private Prop<Boolean> uniqueCardsOnly;
|
||||
private Prop<Boolean> hideFilters;
|
||||
private Prop<Boolean> compactListView;
|
||||
private Prop<GroupDef> groupBy;
|
||||
private Prop<ColumnDef> pileBy;
|
||||
private Prop<Integer> imageColumnCount;
|
||||
private Prop<Integer> viewIndex;
|
||||
|
||||
private ItemManagerConfig(final Map<ColumnDef, ItemColumnConfig> cols0, boolean showUniqueCardsOption0, boolean uniqueCardsOnly0, boolean hideFilters0, GroupDef groupBy0, ColumnDef pileBy0, int imageColumnCount0, int viewIndex0) {
|
||||
cols = cols0;
|
||||
for (ItemColumnConfig colConfig : cols.values()) {
|
||||
colConfig.establishDefaults();
|
||||
}
|
||||
showUniqueCardsOption = showUniqueCardsOption0;
|
||||
|
||||
uniqueCardsOnly = new Prop<Boolean>(uniqueCardsOnly0);
|
||||
hideFilters = new Prop<Boolean>(hideFilters0);
|
||||
compactListView = new Prop<Boolean>(FModel.getPreferences().getPrefBoolean(FPref.UI_COMPACT_LIST_ITEMS)); //use main setting to determine default
|
||||
groupBy = new Prop<GroupDef>(groupBy0);
|
||||
pileBy = new Prop<ColumnDef>(pileBy0);
|
||||
imageColumnCount = new Prop<Integer>(imageColumnCount0);
|
||||
viewIndex = new Prop<Integer>(viewIndex0);
|
||||
}
|
||||
|
||||
private class Prop<T> {
|
||||
private T value;
|
||||
private T defaultValue;
|
||||
|
||||
private Prop(T defaultValue0) {
|
||||
value = defaultValue0;
|
||||
defaultValue = defaultValue0;
|
||||
}
|
||||
|
||||
private T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
private void setValue(T value0) {
|
||||
if (value == value0) { return; }
|
||||
value = value0;
|
||||
save();
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void writeValue(final Element el, String localName) {
|
||||
if (value == null) {
|
||||
if (defaultValue != null) {
|
||||
el.setAttribute(localName, "");
|
||||
}
|
||||
}
|
||||
else if (!value.equals(defaultValue)) {
|
||||
if (value instanceof Enum) { //use Enum.name to prevent issues with toString() overrides
|
||||
el.setAttribute(localName, ((Enum)value).name());
|
||||
}
|
||||
else {
|
||||
el.setAttribute(localName, String.valueOf(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<ColumnDef, ItemColumnConfig> getCols() {
|
||||
return cols;
|
||||
}
|
||||
|
||||
public boolean getShowUniqueCardsOption() {
|
||||
return showUniqueCardsOption;
|
||||
}
|
||||
|
||||
public boolean getUniqueCardsOnly() {
|
||||
return uniqueCardsOnly.getValue();
|
||||
}
|
||||
public void setUniqueCardsOnly(boolean value0) {
|
||||
uniqueCardsOnly.setValue(value0);
|
||||
}
|
||||
|
||||
public boolean getHideFilters() {
|
||||
return hideFilters.getValue();
|
||||
}
|
||||
public void setHideFilters(boolean value0) {
|
||||
hideFilters.setValue(value0);
|
||||
}
|
||||
|
||||
public boolean getCompactListView() {
|
||||
return compactListView.getValue();
|
||||
}
|
||||
public void setCompactListView(boolean value0) {
|
||||
compactListView.setValue(value0);
|
||||
}
|
||||
|
||||
public GroupDef getGroupBy() {
|
||||
return groupBy.getValue();
|
||||
}
|
||||
public void setGroupBy(GroupDef value0) {
|
||||
groupBy.setValue(value0);
|
||||
}
|
||||
|
||||
public ColumnDef getPileBy() {
|
||||
return pileBy.getValue();
|
||||
}
|
||||
public void setPileBy(ColumnDef value0) {
|
||||
pileBy.setValue(value0);
|
||||
}
|
||||
|
||||
public int getImageColumnCount() {
|
||||
return imageColumnCount.getValue();
|
||||
}
|
||||
public void setImageColumnCount(int value0) {
|
||||
imageColumnCount.setValue(value0);
|
||||
}
|
||||
|
||||
public int getViewIndex() {
|
||||
return viewIndex.getValue();
|
||||
}
|
||||
public void setViewIndex(int value0) {
|
||||
viewIndex.setValue(value0);
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final Document document = builder.parse(new File(ForgeConstants.ITEM_VIEW_PREFS_FILE));
|
||||
final NodeList configs = document.getElementsByTagName("config");
|
||||
for (int i = 0; i < configs.getLength(); i++) {
|
||||
try { //capture enum parse errors without losing other preferences
|
||||
final Element el = (Element)configs.item(i);
|
||||
final ItemManagerConfig config = Enum.valueOf(ItemManagerConfig.class, el.getAttribute("name"));
|
||||
if (el.hasAttribute("uniqueCardsOnly")) {
|
||||
config.uniqueCardsOnly.value = Boolean.parseBoolean(el.getAttribute("uniqueCardsOnly"));
|
||||
}
|
||||
if (el.hasAttribute("hideFilters")) {
|
||||
config.hideFilters.value = Boolean.parseBoolean(el.getAttribute("hideFilters"));
|
||||
}
|
||||
if (el.hasAttribute("compactListView")) {
|
||||
config.compactListView.value = Boolean.parseBoolean(el.getAttribute("compactListView"));
|
||||
}
|
||||
if (el.hasAttribute("groupBy")) {
|
||||
String value = el.getAttribute("groupBy");
|
||||
if (value.isEmpty()) {
|
||||
config.groupBy.value = null;
|
||||
}
|
||||
else {
|
||||
config.groupBy.value = Enum.valueOf(GroupDef.class, value);
|
||||
}
|
||||
}
|
||||
if (el.hasAttribute("pileBy")) {
|
||||
String value = el.getAttribute("pileBy");
|
||||
if (value.isEmpty()) {
|
||||
config.pileBy.value = null;
|
||||
}
|
||||
else {
|
||||
config.pileBy.value = Enum.valueOf(ColumnDef.class, value);
|
||||
}
|
||||
}
|
||||
if (el.hasAttribute("imageColumnCount")) {
|
||||
config.imageColumnCount.value = Integer.parseInt(el.getAttribute("imageColumnCount"));
|
||||
}
|
||||
if (el.hasAttribute("viewIndex")) {
|
||||
config.viewIndex.value = Integer.parseInt(el.getAttribute("viewIndex"));
|
||||
}
|
||||
final NodeList cols = el.getElementsByTagName("col");
|
||||
for (int j = 0; j < cols.getLength(); j++) {
|
||||
try { //capture enum parse errors without losing other column preferences
|
||||
final Element colEl = (Element)cols.item(j);
|
||||
ItemColumnConfig colConfig = config.cols.get(Enum.valueOf(ColumnDef.class, colEl.getAttribute("name")));
|
||||
if (colEl.hasAttribute("width")) {
|
||||
colConfig.setPreferredWidth(Integer.parseInt(colEl.getAttribute("width")));
|
||||
}
|
||||
if (colEl.hasAttribute("sortPriority")) {
|
||||
colConfig.setSortPriority(Integer.parseInt(colEl.getAttribute("sortPriority")));
|
||||
}
|
||||
if (colEl.hasAttribute("sortState")) {
|
||||
colConfig.setSortState(Enum.valueOf(SortState.class, colEl.getAttribute("sortState")));
|
||||
}
|
||||
if (colEl.hasAttribute("index")) {
|
||||
colConfig.setIndex(Integer.parseInt(colEl.getAttribute("index")));
|
||||
}
|
||||
if (colEl.hasAttribute("visible")) {
|
||||
colConfig.setVisible(Boolean.parseBoolean(colEl.getAttribute("visible")));
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
//ok if file not found
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
Element root = document.createElement("preferences");
|
||||
root.setAttribute("type", "item_view");
|
||||
document.appendChild(root);
|
||||
|
||||
for (ItemManagerConfig config : ItemManagerConfig.values()) {
|
||||
Element el = document.createElement("config");
|
||||
el.setAttribute("name", config.name());
|
||||
config.uniqueCardsOnly.writeValue(el, "uniqueCardsOnly");
|
||||
config.hideFilters.writeValue(el, "hideFilters");
|
||||
config.compactListView.writeValue(el, "compactListView");
|
||||
config.groupBy.writeValue(el, "groupBy");
|
||||
config.pileBy.writeValue(el, "pileBy");
|
||||
config.imageColumnCount.writeValue(el, "imageColumnCount");
|
||||
config.viewIndex.writeValue(el, "viewIndex");
|
||||
for (ItemColumnConfig colConfig : config.cols.values()) {
|
||||
Element colEl = document.createElement("col");
|
||||
colEl.setAttribute("name", colConfig.getDef().name());
|
||||
if (colConfig.getPreferredWidth() != colConfig.getDefaults().getPreferredWidth()) {
|
||||
colEl.setAttribute("width", String.valueOf(colConfig.getPreferredWidth()));
|
||||
}
|
||||
if (colConfig.getSortPriority() != colConfig.getDefaults().getSortPriority()) {
|
||||
colEl.setAttribute("sortPriority", String.valueOf(colConfig.getSortPriority()));
|
||||
}
|
||||
if (colConfig.getSortState() != colConfig.getDefaults().getSortState()) {
|
||||
colEl.setAttribute("sortState", String.valueOf(colConfig.getSortState()));
|
||||
}
|
||||
if (colConfig.getIndex() != colConfig.getDefaults().getIndex()) {
|
||||
colEl.setAttribute("index", String.valueOf(colConfig.getIndex()));
|
||||
}
|
||||
if (colConfig.isVisible() != colConfig.getDefaults().isVisible()) {
|
||||
colEl.setAttribute("visible", String.valueOf(colConfig.isVisible()));
|
||||
}
|
||||
el.appendChild(colEl);
|
||||
}
|
||||
root.appendChild(el);
|
||||
}
|
||||
XmlUtil.saveDocument(document, ForgeConstants.ITEM_VIEW_PREFS_FILE);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
package forge.itemmanager;
|
||||
|
||||
import forge.itemmanager.ItemColumnConfig.SortState;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.util.XmlUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Preferences associated with individual cards
|
||||
*
|
||||
*/
|
||||
public enum ItemManagerConfig {
|
||||
STRING_ONLY(SColumnUtil.getStringColumn(), false, false, true,
|
||||
null, null, 1, 0),
|
||||
CARD_CATALOG(SColumnUtil.getCatalogDefaultColumns(true), true, true, false,
|
||||
null, null, 4, 0),
|
||||
DECK_EDITOR(SColumnUtil.getDeckEditorDefaultColumns(), false, false, true,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
DRAFT_PACK(SColumnUtil.getDraftPackDefaultColumns(), false, false, true,
|
||||
null, null, 4, 1),
|
||||
DRAFT_POOL(SColumnUtil.getCatalogDefaultColumns(false), false, false, false,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
DRAFT_CONSPIRACY(SColumnUtil.getSpecialCardPoolDefaultColumns(), false, false, true,
|
||||
null, null, 4, 0),
|
||||
SEALED_POOL(SColumnUtil.getCatalogDefaultColumns(false), false, false, false,
|
||||
GroupDef.COLOR, ColumnDef.CMC, 4, 1),
|
||||
SPELL_SHOP(SColumnUtil.getSpellShopDefaultColumns(), false, false, false,
|
||||
null, null, 4, 0),
|
||||
QUEST_INVENTORY(SColumnUtil.getQuestInventoryDefaultColumns(), false, false, false,
|
||||
null, null, 4, 0),
|
||||
QUEST_EDITOR_POOL(SColumnUtil.getQuestEditorPoolDefaultColumns(), false, false, false,
|
||||
null, null, 4, 0),
|
||||
QUEST_DECK_EDITOR(SColumnUtil.getQuestDeckEditorDefaultColumns(), false, false, false,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
QUEST_DRAFT_DECK_VIEWER(SColumnUtil.getDeckViewerDefaultColumns(), false, false, true,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
CONQUEST_AETHER(SColumnUtil.getConquestAEtherDefaultColumns(), false, false, false,
|
||||
null, null, 4, 0),
|
||||
CONQUEST_COMMANDERS(SColumnUtil.getConquestCommandersDefaultColumns(), false, false, false,
|
||||
null, null, 3, 0),
|
||||
CONQUEST_COLLECTION(SColumnUtil.getConquestCollectionDefaultColumns(), false, false, false,
|
||||
null, null, 4, 0),
|
||||
CONQUEST_DECK_EDITOR(SColumnUtil.getConquestDeckEditorDefaultColumns(), false, false, false,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
AVATAR_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, false,
|
||||
null, null, 4, 0),
|
||||
SCHEME_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
|
||||
null, null, 4, 0),
|
||||
CONSPIRACY_DECKS(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
|
||||
null, null, 4, 0),
|
||||
SCHEME_DECK_EDITOR(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
|
||||
null, null, 4, 0),
|
||||
PLANAR_POOL(SColumnUtil.getSpecialCardPoolDefaultColumns(), true, false, true,
|
||||
null, null, 4, 0),
|
||||
PLANAR_DECK_EDITOR(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
|
||||
null, null, 4, 0),
|
||||
COMMANDER_POOL(SColumnUtil.getCatalogDefaultColumns(true), true, false, false,
|
||||
null, null, 4, 0),
|
||||
COMMANDER_SECTION(SColumnUtil.getCatalogDefaultColumns(true), true, false, true,
|
||||
null, null, 1, 1),
|
||||
WORKSHOP_CATALOG(SColumnUtil.getCatalogDefaultColumns(true), true, true, false,
|
||||
null, null, 4, 0),
|
||||
DECK_VIEWER(SColumnUtil.getDeckViewerDefaultColumns(), false, false, false,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 4, 1),
|
||||
CONSTRUCTED_DECKS(SColumnUtil.getDecksDefaultColumns(true, true), false, false, false,
|
||||
null, null, 3, 0),
|
||||
COMMANDER_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
PLANAR_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
SCHEME_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
VANGUARDS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, true,
|
||||
null, null, 3, 0),
|
||||
DRAFT_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
SEALED_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
WINSTON_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
QUEST_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
PRECON_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
QUEST_EVENT_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
NET_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false,
|
||||
null, null, 3, 0),
|
||||
SIDEBOARD(SColumnUtil.getDeckEditorDefaultColumns(), false, false, true,
|
||||
GroupDef.DEFAULT, ColumnDef.CMC, 3, 0);
|
||||
|
||||
private Map<ColumnDef, ItemColumnConfig> cols;
|
||||
private boolean showUniqueCardsOption;
|
||||
|
||||
private Prop<Boolean> uniqueCardsOnly;
|
||||
private Prop<Boolean> hideFilters;
|
||||
private Prop<Boolean> compactListView;
|
||||
private Prop<GroupDef> groupBy;
|
||||
private Prop<ColumnDef> pileBy;
|
||||
private Prop<Integer> imageColumnCount;
|
||||
private Prop<Integer> viewIndex;
|
||||
|
||||
private ItemManagerConfig(final Map<ColumnDef, ItemColumnConfig> cols0, boolean showUniqueCardsOption0, boolean uniqueCardsOnly0, boolean hideFilters0, GroupDef groupBy0, ColumnDef pileBy0, int imageColumnCount0, int viewIndex0) {
|
||||
cols = cols0;
|
||||
for (ItemColumnConfig colConfig : cols.values()) {
|
||||
colConfig.establishDefaults();
|
||||
}
|
||||
showUniqueCardsOption = showUniqueCardsOption0;
|
||||
|
||||
uniqueCardsOnly = new Prop<Boolean>(uniqueCardsOnly0);
|
||||
hideFilters = new Prop<Boolean>(hideFilters0);
|
||||
compactListView = new Prop<Boolean>(FModel.getPreferences().getPrefBoolean(FPref.UI_COMPACT_LIST_ITEMS)); //use main setting to determine default
|
||||
groupBy = new Prop<GroupDef>(groupBy0);
|
||||
pileBy = new Prop<ColumnDef>(pileBy0);
|
||||
imageColumnCount = new Prop<Integer>(imageColumnCount0);
|
||||
viewIndex = new Prop<Integer>(viewIndex0);
|
||||
}
|
||||
|
||||
private class Prop<T> {
|
||||
private T value;
|
||||
private T defaultValue;
|
||||
|
||||
private Prop(T defaultValue0) {
|
||||
value = defaultValue0;
|
||||
defaultValue = defaultValue0;
|
||||
}
|
||||
|
||||
private T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
private void setValue(T value0) {
|
||||
if (value == value0) { return; }
|
||||
value = value0;
|
||||
save();
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void writeValue(final Element el, String localName) {
|
||||
if (value == null) {
|
||||
if (defaultValue != null) {
|
||||
el.setAttribute(localName, "");
|
||||
}
|
||||
}
|
||||
else if (!value.equals(defaultValue)) {
|
||||
if (value instanceof Enum) { //use Enum.name to prevent issues with toString() overrides
|
||||
el.setAttribute(localName, ((Enum)value).name());
|
||||
}
|
||||
else {
|
||||
el.setAttribute(localName, String.valueOf(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<ColumnDef, ItemColumnConfig> getCols() {
|
||||
return cols;
|
||||
}
|
||||
|
||||
public boolean getShowUniqueCardsOption() {
|
||||
return showUniqueCardsOption;
|
||||
}
|
||||
|
||||
public boolean getUniqueCardsOnly() {
|
||||
return uniqueCardsOnly.getValue();
|
||||
}
|
||||
public void setUniqueCardsOnly(boolean value0) {
|
||||
uniqueCardsOnly.setValue(value0);
|
||||
}
|
||||
|
||||
public boolean getHideFilters() {
|
||||
return hideFilters.getValue();
|
||||
}
|
||||
public void setHideFilters(boolean value0) {
|
||||
hideFilters.setValue(value0);
|
||||
}
|
||||
|
||||
public boolean getCompactListView() {
|
||||
return compactListView.getValue();
|
||||
}
|
||||
public void setCompactListView(boolean value0) {
|
||||
compactListView.setValue(value0);
|
||||
}
|
||||
|
||||
public GroupDef getGroupBy() {
|
||||
return groupBy.getValue();
|
||||
}
|
||||
public void setGroupBy(GroupDef value0) {
|
||||
groupBy.setValue(value0);
|
||||
}
|
||||
|
||||
public ColumnDef getPileBy() {
|
||||
return pileBy.getValue();
|
||||
}
|
||||
public void setPileBy(ColumnDef value0) {
|
||||
pileBy.setValue(value0);
|
||||
}
|
||||
|
||||
public int getImageColumnCount() {
|
||||
return imageColumnCount.getValue();
|
||||
}
|
||||
public void setImageColumnCount(int value0) {
|
||||
imageColumnCount.setValue(value0);
|
||||
}
|
||||
|
||||
public int getViewIndex() {
|
||||
return viewIndex.getValue();
|
||||
}
|
||||
public void setViewIndex(int value0) {
|
||||
viewIndex.setValue(value0);
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final Document document = builder.parse(new File(ForgeConstants.ITEM_VIEW_PREFS_FILE));
|
||||
final NodeList configs = document.getElementsByTagName("config");
|
||||
for (int i = 0; i < configs.getLength(); i++) {
|
||||
try { //capture enum parse errors without losing other preferences
|
||||
final Element el = (Element)configs.item(i);
|
||||
final ItemManagerConfig config = Enum.valueOf(ItemManagerConfig.class, el.getAttribute("name"));
|
||||
if (el.hasAttribute("uniqueCardsOnly")) {
|
||||
config.uniqueCardsOnly.value = Boolean.parseBoolean(el.getAttribute("uniqueCardsOnly"));
|
||||
}
|
||||
if (el.hasAttribute("hideFilters")) {
|
||||
config.hideFilters.value = Boolean.parseBoolean(el.getAttribute("hideFilters"));
|
||||
}
|
||||
if (el.hasAttribute("compactListView")) {
|
||||
config.compactListView.value = Boolean.parseBoolean(el.getAttribute("compactListView"));
|
||||
}
|
||||
if (el.hasAttribute("groupBy")) {
|
||||
String value = el.getAttribute("groupBy");
|
||||
if (value.isEmpty()) {
|
||||
config.groupBy.value = null;
|
||||
}
|
||||
else {
|
||||
config.groupBy.value = Enum.valueOf(GroupDef.class, value);
|
||||
}
|
||||
}
|
||||
if (el.hasAttribute("pileBy")) {
|
||||
String value = el.getAttribute("pileBy");
|
||||
if (value.isEmpty()) {
|
||||
config.pileBy.value = null;
|
||||
}
|
||||
else {
|
||||
config.pileBy.value = Enum.valueOf(ColumnDef.class, value);
|
||||
}
|
||||
}
|
||||
if (el.hasAttribute("imageColumnCount")) {
|
||||
config.imageColumnCount.value = Integer.parseInt(el.getAttribute("imageColumnCount"));
|
||||
}
|
||||
if (el.hasAttribute("viewIndex")) {
|
||||
config.viewIndex.value = Integer.parseInt(el.getAttribute("viewIndex"));
|
||||
}
|
||||
final NodeList cols = el.getElementsByTagName("col");
|
||||
for (int j = 0; j < cols.getLength(); j++) {
|
||||
try { //capture enum parse errors without losing other column preferences
|
||||
final Element colEl = (Element)cols.item(j);
|
||||
ItemColumnConfig colConfig = config.cols.get(Enum.valueOf(ColumnDef.class, colEl.getAttribute("name")));
|
||||
if (colEl.hasAttribute("width")) {
|
||||
colConfig.setPreferredWidth(Integer.parseInt(colEl.getAttribute("width")));
|
||||
}
|
||||
if (colEl.hasAttribute("sortPriority")) {
|
||||
colConfig.setSortPriority(Integer.parseInt(colEl.getAttribute("sortPriority")));
|
||||
}
|
||||
if (colEl.hasAttribute("sortState")) {
|
||||
colConfig.setSortState(Enum.valueOf(SortState.class, colEl.getAttribute("sortState")));
|
||||
}
|
||||
if (colEl.hasAttribute("index")) {
|
||||
colConfig.setIndex(Integer.parseInt(colEl.getAttribute("index")));
|
||||
}
|
||||
if (colEl.hasAttribute("visible")) {
|
||||
colConfig.setVisible(Boolean.parseBoolean(colEl.getAttribute("visible")));
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
//ok if file not found
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
try {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
Element root = document.createElement("preferences");
|
||||
root.setAttribute("type", "item_view");
|
||||
document.appendChild(root);
|
||||
|
||||
for (ItemManagerConfig config : ItemManagerConfig.values()) {
|
||||
Element el = document.createElement("config");
|
||||
el.setAttribute("name", config.name());
|
||||
config.uniqueCardsOnly.writeValue(el, "uniqueCardsOnly");
|
||||
config.hideFilters.writeValue(el, "hideFilters");
|
||||
config.compactListView.writeValue(el, "compactListView");
|
||||
config.groupBy.writeValue(el, "groupBy");
|
||||
config.pileBy.writeValue(el, "pileBy");
|
||||
config.imageColumnCount.writeValue(el, "imageColumnCount");
|
||||
config.viewIndex.writeValue(el, "viewIndex");
|
||||
for (ItemColumnConfig colConfig : config.cols.values()) {
|
||||
Element colEl = document.createElement("col");
|
||||
colEl.setAttribute("name", colConfig.getDef().name());
|
||||
if (colConfig.getPreferredWidth() != colConfig.getDefaults().getPreferredWidth()) {
|
||||
colEl.setAttribute("width", String.valueOf(colConfig.getPreferredWidth()));
|
||||
}
|
||||
if (colConfig.getSortPriority() != colConfig.getDefaults().getSortPriority()) {
|
||||
colEl.setAttribute("sortPriority", String.valueOf(colConfig.getSortPriority()));
|
||||
}
|
||||
if (colConfig.getSortState() != colConfig.getDefaults().getSortState()) {
|
||||
colEl.setAttribute("sortState", String.valueOf(colConfig.getSortState()));
|
||||
}
|
||||
if (colConfig.getIndex() != colConfig.getDefaults().getIndex()) {
|
||||
colEl.setAttribute("index", String.valueOf(colConfig.getIndex()));
|
||||
}
|
||||
if (colConfig.isVisible() != colConfig.getDefaults().isVisible()) {
|
||||
colEl.setAttribute("visible", String.valueOf(colConfig.isVisible()));
|
||||
}
|
||||
el.appendChild(colEl);
|
||||
}
|
||||
root.appendChild(el);
|
||||
}
|
||||
XmlUtil.saveDocument(document, ForgeConstants.ITEM_VIEW_PREFS_FILE);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,232 +1,232 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
import forge.itemmanager.ItemColumnConfig.SortState;
|
||||
import forge.util.ItemPool;
|
||||
import forge.util.ItemPoolSorter;
|
||||
|
||||
|
||||
public final class ItemManagerModel<T extends InventoryItem> {
|
||||
private static final int maxSortDepth = 3;
|
||||
|
||||
private final ItemPool<T> data;
|
||||
private boolean infiniteSupply;
|
||||
private final CascadeManager cascadeManager = new CascadeManager();
|
||||
|
||||
public ItemManagerModel(final Class<T> genericType0) {
|
||||
data = new ItemPool<T>(genericType0);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
// same thing as above, it was copied to provide sorting (needed by table
|
||||
// views in deck editors)
|
||||
private final transient List<Entry<T, Integer>> itemsOrdered = new ArrayList<Map.Entry<T, Integer>>();
|
||||
|
||||
protected transient boolean isListInSync = false;
|
||||
|
||||
public List<Entry<T, Integer>> getOrderedList() {
|
||||
if (!isListInSync) {
|
||||
rebuildOrderedList();
|
||||
}
|
||||
return itemsOrdered;
|
||||
}
|
||||
|
||||
private void rebuildOrderedList() {
|
||||
itemsOrdered.clear();
|
||||
if (data != null) {
|
||||
for (final Entry<T, Integer> e : data) {
|
||||
itemsOrdered.add(e);
|
||||
}
|
||||
}
|
||||
isListInSync = true;
|
||||
}
|
||||
|
||||
public int countDistinct() {
|
||||
return data.countDistinct();
|
||||
}
|
||||
|
||||
public ItemPool<T> getItems() {
|
||||
return data.getView();
|
||||
}
|
||||
|
||||
public void removeItem(final T item0, final int qty) {
|
||||
if (data.count(item0) > 0) {
|
||||
if (isInfinite()) {
|
||||
data.removeAll(item0);
|
||||
}
|
||||
else {
|
||||
data.remove(item0, qty);
|
||||
}
|
||||
isListInSync = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void replaceAll(final T item0, final T replacement0) {
|
||||
final int count = data.count(item0);
|
||||
if (count > 0) {
|
||||
data.removeAll(item0);
|
||||
data.add(replacement0, count);
|
||||
isListInSync = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void addItem(final T item0, final int qty) {
|
||||
data.add(item0, qty);
|
||||
isListInSync = false;
|
||||
}
|
||||
|
||||
public void addItems(final Iterable<Entry<T, Integer>> items0) {
|
||||
data.addAll(items0);
|
||||
isListInSync = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this table's pool of items is in infinite supply. If false,
|
||||
* items in the table have a limited number of copies.
|
||||
*/
|
||||
public void setInfinite(final boolean infinite) {
|
||||
infiniteSupply = infinite;
|
||||
}
|
||||
|
||||
public boolean isInfinite() {
|
||||
return infiniteSupply;
|
||||
}
|
||||
|
||||
public CascadeManager getCascadeManager() {
|
||||
return cascadeManager;
|
||||
}
|
||||
|
||||
public void refreshSort() {
|
||||
if (getOrderedList().isEmpty()) { return; }
|
||||
|
||||
Collections.sort(getOrderedList(), new MyComparator());
|
||||
}
|
||||
|
||||
//Manages sorting orders for multiple depths of sorting
|
||||
public final class CascadeManager {
|
||||
private final List<ItemColumn> colsToSort = new ArrayList<ItemColumn>(3);
|
||||
private Sorter sorter = null;
|
||||
|
||||
// Adds a column to sort cascade list.
|
||||
// If column is first in the cascade, inverts direction of sort.
|
||||
// Otherwise, sorts in ascending direction.
|
||||
public void add(final ItemColumn col0, final boolean forSetup) {
|
||||
sorter = null;
|
||||
|
||||
if (forSetup) { //just add column unmodified if setting up sort columns
|
||||
colsToSort.add(0, col0);
|
||||
}
|
||||
else {
|
||||
if (colsToSort.size() > 0 && colsToSort.get(0).equals(col0)) { //if column already at top level, just invert
|
||||
col0.getConfig().setSortPriority(1);
|
||||
col0.getConfig().setSortState(col0.getConfig().getSortState() == SortState.ASC ? SortState.DESC : SortState.ASC);
|
||||
}
|
||||
else { //otherwise move column to top level and move others down
|
||||
colsToSort.remove(col0);
|
||||
col0.getConfig().setSortPriority(1);
|
||||
col0.getConfig().setSortState(col0.getConfig().getDefaultSortState());
|
||||
colsToSort.add(0, col0);
|
||||
}
|
||||
|
||||
//decrement sort priority on remaining columns
|
||||
for (int i = 1; i < maxSortDepth; i++) {
|
||||
if (colsToSort.size() == i) { break; }
|
||||
|
||||
if (colsToSort.get(i).getConfig().getSortPriority() != 0) {
|
||||
colsToSort.get(i).getConfig().setSortPriority(i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//unset and remove boundary columns.
|
||||
if (colsToSort.size() > maxSortDepth) {
|
||||
colsToSort.get(maxSortDepth).getConfig().setSortPriority(0);
|
||||
colsToSort.remove(maxSortDepth);
|
||||
}
|
||||
}
|
||||
|
||||
public Sorter getSorter() {
|
||||
if (sorter == null) {
|
||||
sorter = createSorter();
|
||||
}
|
||||
return sorter;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
colsToSort.clear();
|
||||
sorter = null;
|
||||
}
|
||||
|
||||
private Sorter createSorter() {
|
||||
final List<ItemPoolSorter<InventoryItem>> oneColSorters = new ArrayList<ItemPoolSorter<InventoryItem>>(maxSortDepth);
|
||||
|
||||
for (final ItemColumn col : colsToSort) {
|
||||
oneColSorters.add(new ItemPoolSorter<InventoryItem>(
|
||||
col.getFnSort(),
|
||||
col.getConfig().getSortState().equals(SortState.ASC) ? true : false));
|
||||
}
|
||||
|
||||
return new Sorter(oneColSorters);
|
||||
}
|
||||
|
||||
public class Sorter implements Comparator<Entry<InventoryItem, Integer>> {
|
||||
private final List<ItemPoolSorter<InventoryItem>> sorters;
|
||||
private final int cntFields;
|
||||
|
||||
public Sorter(final List<ItemPoolSorter<InventoryItem>> sorters0) {
|
||||
sorters = sorters0;
|
||||
cntFields = sorters0.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int compare(final Entry<InventoryItem, Integer> arg0, final Entry<InventoryItem, Integer> arg1) {
|
||||
int lastCompare = 0;
|
||||
int iField = -1;
|
||||
while ((++iField < cntFields) && (lastCompare == 0)) { // reverse
|
||||
// iteration
|
||||
final ItemPoolSorter<InventoryItem> sorter = sorters.get(iField);
|
||||
if (sorter == null) {
|
||||
break;
|
||||
}
|
||||
lastCompare = sorter.compare(arg0, arg1);
|
||||
}
|
||||
return lastCompare;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class MyComparator implements Comparator<Entry<T, Integer>> {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public int compare(final Entry<T, Integer> o1, final Entry<T, Integer> o2) {
|
||||
return cascadeManager.getSorter().compare((Entry<InventoryItem, Integer>)o1, (Entry<InventoryItem, Integer>)o2);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
import forge.itemmanager.ItemColumnConfig.SortState;
|
||||
import forge.util.ItemPool;
|
||||
import forge.util.ItemPoolSorter;
|
||||
|
||||
|
||||
public final class ItemManagerModel<T extends InventoryItem> {
|
||||
private static final int maxSortDepth = 3;
|
||||
|
||||
private final ItemPool<T> data;
|
||||
private boolean infiniteSupply;
|
||||
private final CascadeManager cascadeManager = new CascadeManager();
|
||||
|
||||
public ItemManagerModel(final Class<T> genericType0) {
|
||||
data = new ItemPool<T>(genericType0);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
// same thing as above, it was copied to provide sorting (needed by table
|
||||
// views in deck editors)
|
||||
private final transient List<Entry<T, Integer>> itemsOrdered = new ArrayList<Map.Entry<T, Integer>>();
|
||||
|
||||
protected transient boolean isListInSync = false;
|
||||
|
||||
public List<Entry<T, Integer>> getOrderedList() {
|
||||
if (!isListInSync) {
|
||||
rebuildOrderedList();
|
||||
}
|
||||
return itemsOrdered;
|
||||
}
|
||||
|
||||
private void rebuildOrderedList() {
|
||||
itemsOrdered.clear();
|
||||
if (data != null) {
|
||||
for (final Entry<T, Integer> e : data) {
|
||||
itemsOrdered.add(e);
|
||||
}
|
||||
}
|
||||
isListInSync = true;
|
||||
}
|
||||
|
||||
public int countDistinct() {
|
||||
return data.countDistinct();
|
||||
}
|
||||
|
||||
public ItemPool<T> getItems() {
|
||||
return data.getView();
|
||||
}
|
||||
|
||||
public void removeItem(final T item0, final int qty) {
|
||||
if (data.count(item0) > 0) {
|
||||
if (isInfinite()) {
|
||||
data.removeAll(item0);
|
||||
}
|
||||
else {
|
||||
data.remove(item0, qty);
|
||||
}
|
||||
isListInSync = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void replaceAll(final T item0, final T replacement0) {
|
||||
final int count = data.count(item0);
|
||||
if (count > 0) {
|
||||
data.removeAll(item0);
|
||||
data.add(replacement0, count);
|
||||
isListInSync = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void addItem(final T item0, final int qty) {
|
||||
data.add(item0, qty);
|
||||
isListInSync = false;
|
||||
}
|
||||
|
||||
public void addItems(final Iterable<Entry<T, Integer>> items0) {
|
||||
data.addAll(items0);
|
||||
isListInSync = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this table's pool of items is in infinite supply. If false,
|
||||
* items in the table have a limited number of copies.
|
||||
*/
|
||||
public void setInfinite(final boolean infinite) {
|
||||
infiniteSupply = infinite;
|
||||
}
|
||||
|
||||
public boolean isInfinite() {
|
||||
return infiniteSupply;
|
||||
}
|
||||
|
||||
public CascadeManager getCascadeManager() {
|
||||
return cascadeManager;
|
||||
}
|
||||
|
||||
public void refreshSort() {
|
||||
if (getOrderedList().isEmpty()) { return; }
|
||||
|
||||
Collections.sort(getOrderedList(), new MyComparator());
|
||||
}
|
||||
|
||||
//Manages sorting orders for multiple depths of sorting
|
||||
public final class CascadeManager {
|
||||
private final List<ItemColumn> colsToSort = new ArrayList<ItemColumn>(3);
|
||||
private Sorter sorter = null;
|
||||
|
||||
// Adds a column to sort cascade list.
|
||||
// If column is first in the cascade, inverts direction of sort.
|
||||
// Otherwise, sorts in ascending direction.
|
||||
public void add(final ItemColumn col0, final boolean forSetup) {
|
||||
sorter = null;
|
||||
|
||||
if (forSetup) { //just add column unmodified if setting up sort columns
|
||||
colsToSort.add(0, col0);
|
||||
}
|
||||
else {
|
||||
if (colsToSort.size() > 0 && colsToSort.get(0).equals(col0)) { //if column already at top level, just invert
|
||||
col0.getConfig().setSortPriority(1);
|
||||
col0.getConfig().setSortState(col0.getConfig().getSortState() == SortState.ASC ? SortState.DESC : SortState.ASC);
|
||||
}
|
||||
else { //otherwise move column to top level and move others down
|
||||
colsToSort.remove(col0);
|
||||
col0.getConfig().setSortPriority(1);
|
||||
col0.getConfig().setSortState(col0.getConfig().getDefaultSortState());
|
||||
colsToSort.add(0, col0);
|
||||
}
|
||||
|
||||
//decrement sort priority on remaining columns
|
||||
for (int i = 1; i < maxSortDepth; i++) {
|
||||
if (colsToSort.size() == i) { break; }
|
||||
|
||||
if (colsToSort.get(i).getConfig().getSortPriority() != 0) {
|
||||
colsToSort.get(i).getConfig().setSortPriority(i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//unset and remove boundary columns.
|
||||
if (colsToSort.size() > maxSortDepth) {
|
||||
colsToSort.get(maxSortDepth).getConfig().setSortPriority(0);
|
||||
colsToSort.remove(maxSortDepth);
|
||||
}
|
||||
}
|
||||
|
||||
public Sorter getSorter() {
|
||||
if (sorter == null) {
|
||||
sorter = createSorter();
|
||||
}
|
||||
return sorter;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
colsToSort.clear();
|
||||
sorter = null;
|
||||
}
|
||||
|
||||
private Sorter createSorter() {
|
||||
final List<ItemPoolSorter<InventoryItem>> oneColSorters = new ArrayList<ItemPoolSorter<InventoryItem>>(maxSortDepth);
|
||||
|
||||
for (final ItemColumn col : colsToSort) {
|
||||
oneColSorters.add(new ItemPoolSorter<InventoryItem>(
|
||||
col.getFnSort(),
|
||||
col.getConfig().getSortState().equals(SortState.ASC) ? true : false));
|
||||
}
|
||||
|
||||
return new Sorter(oneColSorters);
|
||||
}
|
||||
|
||||
public class Sorter implements Comparator<Entry<InventoryItem, Integer>> {
|
||||
private final List<ItemPoolSorter<InventoryItem>> sorters;
|
||||
private final int cntFields;
|
||||
|
||||
public Sorter(final List<ItemPoolSorter<InventoryItem>> sorters0) {
|
||||
sorters = sorters0;
|
||||
cntFields = sorters0.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int compare(final Entry<InventoryItem, Integer> arg0, final Entry<InventoryItem, Integer> arg1) {
|
||||
int lastCompare = 0;
|
||||
int iField = -1;
|
||||
while ((++iField < cntFields) && (lastCompare == 0)) { // reverse
|
||||
// iteration
|
||||
final ItemPoolSorter<InventoryItem> sorter = sorters.get(iField);
|
||||
if (sorter == null) {
|
||||
break;
|
||||
}
|
||||
lastCompare = sorter.compare(arg0, arg1);
|
||||
}
|
||||
return lastCompare;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class MyComparator implements Comparator<Entry<T, Integer>> {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public int compare(final Entry<T, Integer> o1, final Entry<T, Integer> o2) {
|
||||
return cascadeManager.getSorter().compare((Entry<InventoryItem, Integer>)o1, (Entry<InventoryItem, Integer>)o2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,234 +1,234 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.itemmanager.ItemColumnConfig.SortState;
|
||||
|
||||
/**
|
||||
* A collection of methods pertaining to columns in card catalog and
|
||||
* current deck tables, for use in the deck editor.
|
||||
* <br><br>
|
||||
* <i>(S at beginning of class name denotes a static factory.)</i>
|
||||
*
|
||||
*/
|
||||
public final class SColumnUtil {
|
||||
public static Map<ColumnDef, ItemColumnConfig> getColumns(Iterable<ColumnDef> colDefs) {
|
||||
int i = 0;
|
||||
final Map<ColumnDef, ItemColumnConfig> columns = new HashMap<ColumnDef, ItemColumnConfig>();
|
||||
for (ColumnDef colDef : colDefs) {
|
||||
ItemColumnConfig column = new ItemColumnConfig(colDef);
|
||||
column.setIndex(i++);
|
||||
columns.put(colDef, column);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getStringColumn() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = new HashMap<ColumnDef, ItemColumnConfig>();
|
||||
ItemColumnConfig column = new ItemColumnConfig(ColumnDef.STRING);
|
||||
column.setSortPriority(1);
|
||||
columns.put(ColumnDef.STRING, column);
|
||||
return columns;
|
||||
}
|
||||
|
||||
private static Map<ColumnDef, ItemColumnConfig> getCardColumns(ColumnDef quantityColDef, boolean includeFavorite) {
|
||||
return getCardColumns(quantityColDef, includeFavorite, false, false, false, false);
|
||||
}
|
||||
private static Map<ColumnDef, ItemColumnConfig> getCardColumns(ColumnDef quantityColDef, boolean includeFavorite,
|
||||
boolean includeOwned, boolean includePrice, boolean includeNew, boolean includeDecks) {
|
||||
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
|
||||
if (includeFavorite) {
|
||||
colDefs.add(ColumnDef.FAVORITE);
|
||||
}
|
||||
if (quantityColDef != null) {
|
||||
colDefs.add(quantityColDef);
|
||||
}
|
||||
if (includeOwned) {
|
||||
colDefs.add(ColumnDef.OWNED);
|
||||
}
|
||||
colDefs.add(ColumnDef.NAME);
|
||||
if (includePrice) {
|
||||
colDefs.add(ColumnDef.PRICE);
|
||||
}
|
||||
if (includeNew) {
|
||||
colDefs.add(ColumnDef.NEW);
|
||||
}
|
||||
if (includeDecks) {
|
||||
colDefs.add(ColumnDef.DECKS);
|
||||
}
|
||||
colDefs.add(ColumnDef.COST);
|
||||
colDefs.add(ColumnDef.COLOR);
|
||||
colDefs.add(ColumnDef.TYPE);
|
||||
colDefs.add(ColumnDef.POWER);
|
||||
colDefs.add(ColumnDef.TOUGHNESS);
|
||||
colDefs.add(ColumnDef.CMC);
|
||||
colDefs.add(ColumnDef.RARITY);
|
||||
colDefs.add(ColumnDef.SET);
|
||||
colDefs.add(ColumnDef.AI);
|
||||
colDefs.add(ColumnDef.RANKING);
|
||||
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
|
||||
columns.get(ColumnDef.AI).setVisible(false);
|
||||
columns.get(ColumnDef.RANKING).setVisible(false);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getCatalogDefaultColumns(boolean isInfinite) {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(isInfinite ? null : ColumnDef.QUANTITY, true);
|
||||
columns.get(ColumnDef.FAVORITE).setSortPriority(1);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getDeckEditorDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false);
|
||||
columns.get(ColumnDef.CMC).setSortPriority(1);
|
||||
columns.get(ColumnDef.TYPE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getDeckViewerDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false);
|
||||
columns.get(ColumnDef.CMC).setSortPriority(1);
|
||||
columns.get(ColumnDef.TYPE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getDraftPackDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false);
|
||||
columns.get(ColumnDef.RARITY).setSortPriority(1); //sort rares to top
|
||||
columns.get(ColumnDef.RARITY).setSortState(SortState.DESC);
|
||||
columns.get(ColumnDef.COLOR).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
columns.get(ColumnDef.RANKING).setVisible(true);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getSpecialCardPoolDefaultColumns() {
|
||||
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
|
||||
colDefs.add(ColumnDef.FAVORITE);
|
||||
colDefs.add(ColumnDef.NAME);
|
||||
colDefs.add(ColumnDef.TYPE);
|
||||
colDefs.add(ColumnDef.RARITY);
|
||||
colDefs.add(ColumnDef.SET);
|
||||
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
|
||||
columns.get(ColumnDef.FAVORITE).setSortPriority(1);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getSpellShopDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, true, true, false, false);
|
||||
columns.get(ColumnDef.OWNED).setSortPriority(1);
|
||||
columns.get(ColumnDef.PRICE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getQuestInventoryDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, false, true, true, true);
|
||||
columns.get(ColumnDef.NEW).setSortPriority(1);
|
||||
columns.get(ColumnDef.PRICE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getQuestEditorPoolDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, false, false, true, false);
|
||||
columns.get(ColumnDef.NEW).setSortPriority(1);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getQuestDeckEditorDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false, false, false, true, true);
|
||||
columns.get(ColumnDef.CMC).setSortPriority(1);
|
||||
columns.get(ColumnDef.TYPE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getConquestAEtherDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(null, false, false, false, false, false);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(1);
|
||||
columns.get(ColumnDef.COLOR).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getConquestCollectionDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(null, false, false, false, true, false);
|
||||
columns.get(ColumnDef.NEW).setSortPriority(1);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getConquestDeckEditorDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false, false, false, true, false);
|
||||
columns.get(ColumnDef.CMC).setSortPriority(1);
|
||||
columns.get(ColumnDef.TYPE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getConquestCommandersDefaultColumns() {
|
||||
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
|
||||
colDefs.add(ColumnDef.NAME);
|
||||
colDefs.add(ColumnDef.COLOR);
|
||||
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(1);
|
||||
columns.get(ColumnDef.COLOR).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getDecksDefaultColumns(boolean allowEdit, boolean includeFolder) {
|
||||
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
|
||||
colDefs.add(ColumnDef.DECK_FAVORITE);
|
||||
if (allowEdit) {
|
||||
colDefs.add(ColumnDef.DECK_ACTIONS);
|
||||
}
|
||||
if (includeFolder) {
|
||||
colDefs.add(ColumnDef.DECK_FOLDER);
|
||||
}
|
||||
colDefs.add(ColumnDef.NAME);
|
||||
colDefs.add(ColumnDef.DECK_COLOR);
|
||||
colDefs.add(ColumnDef.DECK_FORMAT);
|
||||
colDefs.add(ColumnDef.DECK_EDITION);
|
||||
colDefs.add(ColumnDef.DECK_MAIN);
|
||||
colDefs.add(ColumnDef.DECK_SIDE);
|
||||
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
|
||||
columns.get(ColumnDef.DECK_FAVORITE).setSortPriority(1);
|
||||
if (includeFolder) {
|
||||
columns.get(ColumnDef.DECK_FOLDER).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
}
|
||||
else {
|
||||
columns.get(ColumnDef.NAME).setSortPriority(2);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.itemmanager.ItemColumnConfig.SortState;
|
||||
|
||||
/**
|
||||
* A collection of methods pertaining to columns in card catalog and
|
||||
* current deck tables, for use in the deck editor.
|
||||
* <br><br>
|
||||
* <i>(S at beginning of class name denotes a static factory.)</i>
|
||||
*
|
||||
*/
|
||||
public final class SColumnUtil {
|
||||
public static Map<ColumnDef, ItemColumnConfig> getColumns(Iterable<ColumnDef> colDefs) {
|
||||
int i = 0;
|
||||
final Map<ColumnDef, ItemColumnConfig> columns = new HashMap<ColumnDef, ItemColumnConfig>();
|
||||
for (ColumnDef colDef : colDefs) {
|
||||
ItemColumnConfig column = new ItemColumnConfig(colDef);
|
||||
column.setIndex(i++);
|
||||
columns.put(colDef, column);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getStringColumn() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = new HashMap<ColumnDef, ItemColumnConfig>();
|
||||
ItemColumnConfig column = new ItemColumnConfig(ColumnDef.STRING);
|
||||
column.setSortPriority(1);
|
||||
columns.put(ColumnDef.STRING, column);
|
||||
return columns;
|
||||
}
|
||||
|
||||
private static Map<ColumnDef, ItemColumnConfig> getCardColumns(ColumnDef quantityColDef, boolean includeFavorite) {
|
||||
return getCardColumns(quantityColDef, includeFavorite, false, false, false, false);
|
||||
}
|
||||
private static Map<ColumnDef, ItemColumnConfig> getCardColumns(ColumnDef quantityColDef, boolean includeFavorite,
|
||||
boolean includeOwned, boolean includePrice, boolean includeNew, boolean includeDecks) {
|
||||
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
|
||||
if (includeFavorite) {
|
||||
colDefs.add(ColumnDef.FAVORITE);
|
||||
}
|
||||
if (quantityColDef != null) {
|
||||
colDefs.add(quantityColDef);
|
||||
}
|
||||
if (includeOwned) {
|
||||
colDefs.add(ColumnDef.OWNED);
|
||||
}
|
||||
colDefs.add(ColumnDef.NAME);
|
||||
if (includePrice) {
|
||||
colDefs.add(ColumnDef.PRICE);
|
||||
}
|
||||
if (includeNew) {
|
||||
colDefs.add(ColumnDef.NEW);
|
||||
}
|
||||
if (includeDecks) {
|
||||
colDefs.add(ColumnDef.DECKS);
|
||||
}
|
||||
colDefs.add(ColumnDef.COST);
|
||||
colDefs.add(ColumnDef.COLOR);
|
||||
colDefs.add(ColumnDef.TYPE);
|
||||
colDefs.add(ColumnDef.POWER);
|
||||
colDefs.add(ColumnDef.TOUGHNESS);
|
||||
colDefs.add(ColumnDef.CMC);
|
||||
colDefs.add(ColumnDef.RARITY);
|
||||
colDefs.add(ColumnDef.SET);
|
||||
colDefs.add(ColumnDef.AI);
|
||||
colDefs.add(ColumnDef.RANKING);
|
||||
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
|
||||
columns.get(ColumnDef.AI).setVisible(false);
|
||||
columns.get(ColumnDef.RANKING).setVisible(false);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getCatalogDefaultColumns(boolean isInfinite) {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(isInfinite ? null : ColumnDef.QUANTITY, true);
|
||||
columns.get(ColumnDef.FAVORITE).setSortPriority(1);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getDeckEditorDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false);
|
||||
columns.get(ColumnDef.CMC).setSortPriority(1);
|
||||
columns.get(ColumnDef.TYPE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getDeckViewerDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false);
|
||||
columns.get(ColumnDef.CMC).setSortPriority(1);
|
||||
columns.get(ColumnDef.TYPE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getDraftPackDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false);
|
||||
columns.get(ColumnDef.RARITY).setSortPriority(1); //sort rares to top
|
||||
columns.get(ColumnDef.RARITY).setSortState(SortState.DESC);
|
||||
columns.get(ColumnDef.COLOR).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
columns.get(ColumnDef.RANKING).setVisible(true);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getSpecialCardPoolDefaultColumns() {
|
||||
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
|
||||
colDefs.add(ColumnDef.FAVORITE);
|
||||
colDefs.add(ColumnDef.NAME);
|
||||
colDefs.add(ColumnDef.TYPE);
|
||||
colDefs.add(ColumnDef.RARITY);
|
||||
colDefs.add(ColumnDef.SET);
|
||||
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
|
||||
columns.get(ColumnDef.FAVORITE).setSortPriority(1);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getSpellShopDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, true, true, false, false);
|
||||
columns.get(ColumnDef.OWNED).setSortPriority(1);
|
||||
columns.get(ColumnDef.PRICE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getQuestInventoryDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, false, true, true, true);
|
||||
columns.get(ColumnDef.NEW).setSortPriority(1);
|
||||
columns.get(ColumnDef.PRICE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getQuestEditorPoolDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.QUANTITY, false, false, false, true, false);
|
||||
columns.get(ColumnDef.NEW).setSortPriority(1);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getQuestDeckEditorDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false, false, false, true, true);
|
||||
columns.get(ColumnDef.CMC).setSortPriority(1);
|
||||
columns.get(ColumnDef.TYPE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getConquestAEtherDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(null, false, false, false, false, false);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(1);
|
||||
columns.get(ColumnDef.COLOR).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getConquestCollectionDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(null, false, false, false, true, false);
|
||||
columns.get(ColumnDef.NEW).setSortPriority(1);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getConquestDeckEditorDefaultColumns() {
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getCardColumns(ColumnDef.DECK_QUANTITY, false, false, false, true, false);
|
||||
columns.get(ColumnDef.CMC).setSortPriority(1);
|
||||
columns.get(ColumnDef.TYPE).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getConquestCommandersDefaultColumns() {
|
||||
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
|
||||
colDefs.add(ColumnDef.NAME);
|
||||
colDefs.add(ColumnDef.COLOR);
|
||||
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(1);
|
||||
columns.get(ColumnDef.COLOR).setSortPriority(2);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public static Map<ColumnDef, ItemColumnConfig> getDecksDefaultColumns(boolean allowEdit, boolean includeFolder) {
|
||||
List<ColumnDef> colDefs = new ArrayList<ColumnDef>();
|
||||
colDefs.add(ColumnDef.DECK_FAVORITE);
|
||||
if (allowEdit) {
|
||||
colDefs.add(ColumnDef.DECK_ACTIONS);
|
||||
}
|
||||
if (includeFolder) {
|
||||
colDefs.add(ColumnDef.DECK_FOLDER);
|
||||
}
|
||||
colDefs.add(ColumnDef.NAME);
|
||||
colDefs.add(ColumnDef.DECK_COLOR);
|
||||
colDefs.add(ColumnDef.DECK_FORMAT);
|
||||
colDefs.add(ColumnDef.DECK_EDITION);
|
||||
colDefs.add(ColumnDef.DECK_MAIN);
|
||||
colDefs.add(ColumnDef.DECK_SIDE);
|
||||
|
||||
Map<ColumnDef, ItemColumnConfig> columns = getColumns(colDefs);
|
||||
columns.get(ColumnDef.DECK_FAVORITE).setSortPriority(1);
|
||||
if (includeFolder) {
|
||||
columns.get(ColumnDef.DECK_FOLDER).setSortPriority(2);
|
||||
columns.get(ColumnDef.NAME).setSortPriority(3);
|
||||
}
|
||||
else {
|
||||
columns.get(ColumnDef.NAME).setSortPriority(2);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,394 +1,394 @@
|
||||
package forge.itemmanager;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import forge.StaticData;
|
||||
import forge.card.*;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.game.GameFormat;
|
||||
import forge.interfaces.IButton;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.itemmanager.SItemManagerUtil.StatTypes;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.quest.data.StarRating;
|
||||
import forge.util.BinaryUtil;
|
||||
import forge.util.PredicateString.StringOp;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Static factory; holds blocks of form elements and predicates
|
||||
* which are used in various editing environments.
|
||||
* <br><br>
|
||||
* <i>(S at beginning of class name denotes a static factory.)</i>
|
||||
*/
|
||||
public class SFilterUtil {
|
||||
|
||||
/**
|
||||
* builds a string search filter
|
||||
*/
|
||||
public static Predicate<PaperCard> buildTextFilter(String text, boolean invert, boolean inName, boolean inType, boolean inText, boolean inCost) {
|
||||
text = text.trim();
|
||||
|
||||
if (text.isEmpty()) {
|
||||
return Predicates.alwaysTrue();
|
||||
}
|
||||
|
||||
if (BooleanExpression.isExpression(text)) {
|
||||
BooleanExpression expression = new BooleanExpression(text, inName, inType, inText, inCost);
|
||||
|
||||
try {
|
||||
Predicate<CardRules> filter = expression.evaluate();
|
||||
if (filter != null) {
|
||||
return Predicates.compose(invert ? Predicates.not(filter) : filter, PaperCard.FN_GET_RULES);
|
||||
}
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
ignored.printStackTrace();
|
||||
//Continue with standard filtering if the expression is not valid.
|
||||
}
|
||||
}
|
||||
|
||||
List<String> splitText = getSplitText(text);
|
||||
List<Predicate<CardRules>> terms = new ArrayList<>();
|
||||
for (String s : splitText) {
|
||||
List<Predicate<CardRules>> subands = new ArrayList<>();
|
||||
|
||||
if (inName) { subands.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, s)); }
|
||||
if (inType) { subands.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, s)); }
|
||||
if (inText) { subands.add(CardRulesPredicates.rules(StringOp.CONTAINS_IC, s)); }
|
||||
if (inCost) { subands.add(CardRulesPredicates.cost(StringOp.CONTAINS_IC, s)); }
|
||||
|
||||
terms.add(Predicates.or(subands));
|
||||
}
|
||||
Predicate<CardRules> textFilter = invert ? Predicates.not(Predicates.or(terms)) : Predicates.and(terms);
|
||||
|
||||
return Predicates.compose(textFilter, PaperCard.FN_GET_RULES);
|
||||
}
|
||||
|
||||
private static List<String> getSplitText(String text) {
|
||||
boolean inQuotes = false;
|
||||
String entry = "";
|
||||
List<String> splitText = new ArrayList<String>();
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char ch = text.charAt(i);
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
if (!inQuotes) { //if not in quotes, end current entry
|
||||
if (entry.length() > 0) {
|
||||
splitText.add(entry);
|
||||
entry = "";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
inQuotes = !inQuotes;
|
||||
continue; //don't append quotation character itself
|
||||
case '\\':
|
||||
if (i < text.length() - 1 && text.charAt(i + 1) == '"') {
|
||||
ch = '"'; //allow appending escaped quotation character
|
||||
i++; //prevent changing inQuotes for that character
|
||||
}
|
||||
break;
|
||||
case ',':
|
||||
if (!inQuotes) { //ignore commas outside quotes
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
entry += ch;
|
||||
}
|
||||
if (entry.length() > 0) {
|
||||
splitText.add(entry);
|
||||
}
|
||||
return splitText;
|
||||
}
|
||||
|
||||
public static <T extends InventoryItem> Predicate<T> buildItemTextFilter(String text) {
|
||||
if (text.trim().isEmpty()) {
|
||||
return Predicates.alwaysTrue();
|
||||
}
|
||||
|
||||
return new ItemTextPredicate<>(text);
|
||||
}
|
||||
|
||||
private static class ItemTextPredicate<T extends InventoryItem> implements Predicate<T> {
|
||||
private final List<String> splitText;
|
||||
|
||||
private ItemTextPredicate(String text) {
|
||||
splitText = getSplitText(text.toLowerCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(T input) {
|
||||
String name = input.getName().toLowerCase();
|
||||
for (String s : splitText) {
|
||||
if (name.contains(s)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Predicate<PaperCard> buildStarRatingFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap, final HashSet<StarRating> QuestRatings) {
|
||||
final Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap2 = buttonMap;
|
||||
return new Predicate<PaperCard>() {
|
||||
@Override
|
||||
public boolean apply(PaperCard card) {
|
||||
|
||||
StarRating r = new StarRating();
|
||||
r.Name = card.getName();
|
||||
r.Edition = card.getEdition();
|
||||
int j = 0;
|
||||
for (int i = 1; i < 6; i++) {
|
||||
r.rating = i;
|
||||
if (QuestRatings.contains(r)) {
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
boolean result = true;
|
||||
|
||||
if (j == 0) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_NONE).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
} else if (j == 1) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_1).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
} else if (j == 2) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_2).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
} else if (j == 3) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_3).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
} else if (j == 4) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_4).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
} else if (j == 5) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_5).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Predicate<PaperCard> buildFoilFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap) {
|
||||
final int Foil = (((buttonMap.get(StatTypes.FOIL_OLD).isSelected()) ? 1 : 0)
|
||||
+ ((buttonMap.get(StatTypes.FOIL_NEW).isSelected()) ? 2 : 0)
|
||||
+ ((buttonMap.get(StatTypes.FOIL_NONE).isSelected()) ? 4 : 0));
|
||||
|
||||
return new Predicate<PaperCard>() {
|
||||
@Override
|
||||
public boolean apply(PaperCard card) {
|
||||
|
||||
boolean result = false;
|
||||
|
||||
CardEdition edition = StaticData.instance().getEditions().get(card.getEdition());
|
||||
if ((Foil & 1) == 1) {
|
||||
// Old Style Foil
|
||||
if (edition.getFoilType() == CardEdition.FoilType.OLD_STYLE) {
|
||||
result = result || card.isFoil();
|
||||
}
|
||||
}
|
||||
if ((Foil & 2) == 2) {
|
||||
// New Style Foil
|
||||
if (edition.getFoilType() == CardEdition.FoilType.MODERN) {
|
||||
result = result || card.isFoil();
|
||||
}
|
||||
}
|
||||
if ((Foil & 4) == 4) {
|
||||
result = result || !card.isFoil();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public static Predicate<PaperCard> buildColorFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap) {
|
||||
byte colors0 = 0;
|
||||
|
||||
if (buttonMap.get(StatTypes.WHITE).isSelected()) {
|
||||
colors0 |= MagicColor.WHITE;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.BLUE).isSelected()) {
|
||||
colors0 |= MagicColor.BLUE;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.BLACK).isSelected()) {
|
||||
colors0 |= MagicColor.BLACK;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.RED).isSelected()) {
|
||||
colors0 |= MagicColor.RED;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.GREEN).isSelected()) {
|
||||
colors0 |= MagicColor.GREEN;
|
||||
}
|
||||
|
||||
final byte colors = colors0;
|
||||
final boolean wantColorless = buttonMap.get(StatTypes.COLORLESS).isSelected();
|
||||
final boolean wantMulticolor = buttonMap.get(StatTypes.MULTICOLOR).isSelected();
|
||||
|
||||
return new Predicate<PaperCard>() {
|
||||
@Override
|
||||
public boolean apply(PaperCard card) {
|
||||
CardRules rules = card.getRules();
|
||||
ColorSet color = rules.getColor();
|
||||
boolean allColorsFilteredOut = colors == 0;
|
||||
|
||||
//use color identity for lands, which allows filtering to just lands that can be played in your deck
|
||||
boolean useColorIdentity = rules.getType().isLand() && !allColorsFilteredOut && FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_FILTER_LANDS_BY_COLOR_IDENTITY);
|
||||
if (useColorIdentity) {
|
||||
color = rules.getColorIdentity();
|
||||
}
|
||||
|
||||
boolean result = true;
|
||||
if (wantMulticolor) {
|
||||
if (colors == 0) { //handle showing all multi-color cards if all 5 colors are filtered
|
||||
result = color.isMulticolor() || (wantColorless && color.isColorless());
|
||||
} else if (colors != ColorSet.ALL_COLORS.getColor()) {
|
||||
if (useColorIdentity && !allColorsFilteredOut) {
|
||||
result = color.hasAnyColor(colors) || (wantColorless && color.isColorless());
|
||||
} else {
|
||||
result = (wantColorless && color.isColorless()) || rules.canCastWithAvailable(colors);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = !color.isMulticolor();
|
||||
if (colors != ColorSet.ALL_COLORS.getColor()) {
|
||||
if (useColorIdentity && !allColorsFilteredOut) {
|
||||
result = result && (color.hasAnyColor(colors) || (wantColorless && color.isColorless()));
|
||||
} else {
|
||||
result = result && (color.isColorless() || rules.canCastWithAvailable(colors));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!wantColorless) {
|
||||
if (colors != 0 && colors != ColorSet.ALL_COLORS.getColor()) {
|
||||
//if colorless filtered out ensure phyrexian cards don't appear
|
||||
//unless at least one of their colors is selected
|
||||
result = result && color.hasAnyColor(colors);
|
||||
}
|
||||
result = result && !color.isColorless();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Predicate<DeckProxy> buildDeckColorFilter(final Map<StatTypes, ? extends IButton> buttonMap) {
|
||||
return new Predicate<DeckProxy>() {
|
||||
@Override
|
||||
public boolean apply(DeckProxy input) {
|
||||
byte colorProfile = input.getColor().getColor();
|
||||
if (colorProfile == 0) {
|
||||
return buttonMap.get(StatTypes.DECK_COLORLESS).isSelected();
|
||||
}
|
||||
|
||||
boolean wantMulticolor = buttonMap.get(StatTypes.DECK_MULTICOLOR).isSelected();
|
||||
if (!wantMulticolor && BinaryUtil.bitCount(colorProfile) > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte colors = 0;
|
||||
if (buttonMap.get(StatTypes.DECK_WHITE).isSelected()) {
|
||||
colors |= MagicColor.WHITE;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.DECK_BLUE).isSelected()) {
|
||||
colors |= MagicColor.BLUE;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.DECK_BLACK).isSelected()) {
|
||||
colors |= MagicColor.BLACK;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.DECK_RED).isSelected()) {
|
||||
colors |= MagicColor.RED;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.DECK_GREEN).isSelected()) {
|
||||
colors |= MagicColor.GREEN;
|
||||
}
|
||||
|
||||
return colors == 0 && wantMulticolor && BinaryUtil.bitCount(colorProfile) > 1 || (colorProfile & colors) == colorProfile;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void showOnlyStat(StatTypes clickedStat, IButton clickedButton, Map<StatTypes, ? extends IButton> buttonMap) {
|
||||
boolean foundSelected = false;
|
||||
for (Map.Entry<StatTypes, ? extends IButton> btn : buttonMap.entrySet()) {
|
||||
if (btn.getKey() != clickedStat) {
|
||||
if (btn.getKey() == StatTypes.MULTICOLOR) {
|
||||
switch (clickedStat) {
|
||||
case WHITE:
|
||||
case BLUE:
|
||||
case BLACK:
|
||||
case RED:
|
||||
case GREEN:
|
||||
//ensure multicolor filter selected after right-clicking a color filter
|
||||
if (!btn.getValue().isSelected()) {
|
||||
btn.getValue().setSelected(true);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (btn.getKey() == StatTypes.DECK_MULTICOLOR) {
|
||||
switch (clickedStat) {
|
||||
case DECK_WHITE:
|
||||
case DECK_BLUE:
|
||||
case DECK_BLACK:
|
||||
case DECK_RED:
|
||||
case DECK_GREEN:
|
||||
//ensure multicolor filter selected after right-clicking a color filter
|
||||
if (!btn.getValue().isSelected()) {
|
||||
btn.getValue().setSelected(true);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (btn.getValue().isSelected()) {
|
||||
foundSelected = true;
|
||||
btn.getValue().setSelected(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!clickedButton.isSelected()) {
|
||||
clickedButton.setSelected(true);
|
||||
}
|
||||
else if (!foundSelected) {
|
||||
//if statLabel only label in group selected, re-select all other labels in group
|
||||
for (Map.Entry<StatTypes, ? extends IButton> btn : buttonMap.entrySet()) {
|
||||
if (btn.getKey() != clickedStat) {
|
||||
if (!btn.getValue().isSelected()) {
|
||||
btn.getValue().setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Predicate<PaperCard> buildFormatFilter(Set<GameFormat> formats, boolean allowReprints) {
|
||||
List<Predicate<PaperCard>> predicates = new ArrayList<>();
|
||||
for (GameFormat f : formats) {
|
||||
predicates.add(allowReprints ? f.getFilterRules() : f.getFilterPrinted());
|
||||
}
|
||||
return Predicates.or(predicates);
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> optimizedAnd(Predicate<T> p1, Predicate<T> p2) {
|
||||
return p1 == null ? p2 : (p2 == null ? p1 : Predicates.and(p1, p2));
|
||||
}
|
||||
}
|
||||
package forge.itemmanager;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import forge.StaticData;
|
||||
import forge.card.*;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.game.GameFormat;
|
||||
import forge.interfaces.IButton;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.itemmanager.SItemManagerUtil.StatTypes;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.quest.data.StarRating;
|
||||
import forge.util.BinaryUtil;
|
||||
import forge.util.PredicateString.StringOp;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Static factory; holds blocks of form elements and predicates
|
||||
* which are used in various editing environments.
|
||||
* <br><br>
|
||||
* <i>(S at beginning of class name denotes a static factory.)</i>
|
||||
*/
|
||||
public class SFilterUtil {
|
||||
|
||||
/**
|
||||
* builds a string search filter
|
||||
*/
|
||||
public static Predicate<PaperCard> buildTextFilter(String text, boolean invert, boolean inName, boolean inType, boolean inText, boolean inCost) {
|
||||
text = text.trim();
|
||||
|
||||
if (text.isEmpty()) {
|
||||
return Predicates.alwaysTrue();
|
||||
}
|
||||
|
||||
if (BooleanExpression.isExpression(text)) {
|
||||
BooleanExpression expression = new BooleanExpression(text, inName, inType, inText, inCost);
|
||||
|
||||
try {
|
||||
Predicate<CardRules> filter = expression.evaluate();
|
||||
if (filter != null) {
|
||||
return Predicates.compose(invert ? Predicates.not(filter) : filter, PaperCard.FN_GET_RULES);
|
||||
}
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
ignored.printStackTrace();
|
||||
//Continue with standard filtering if the expression is not valid.
|
||||
}
|
||||
}
|
||||
|
||||
List<String> splitText = getSplitText(text);
|
||||
List<Predicate<CardRules>> terms = new ArrayList<>();
|
||||
for (String s : splitText) {
|
||||
List<Predicate<CardRules>> subands = new ArrayList<>();
|
||||
|
||||
if (inName) { subands.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, s)); }
|
||||
if (inType) { subands.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, s)); }
|
||||
if (inText) { subands.add(CardRulesPredicates.rules(StringOp.CONTAINS_IC, s)); }
|
||||
if (inCost) { subands.add(CardRulesPredicates.cost(StringOp.CONTAINS_IC, s)); }
|
||||
|
||||
terms.add(Predicates.or(subands));
|
||||
}
|
||||
Predicate<CardRules> textFilter = invert ? Predicates.not(Predicates.or(terms)) : Predicates.and(terms);
|
||||
|
||||
return Predicates.compose(textFilter, PaperCard.FN_GET_RULES);
|
||||
}
|
||||
|
||||
private static List<String> getSplitText(String text) {
|
||||
boolean inQuotes = false;
|
||||
String entry = "";
|
||||
List<String> splitText = new ArrayList<String>();
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char ch = text.charAt(i);
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
if (!inQuotes) { //if not in quotes, end current entry
|
||||
if (entry.length() > 0) {
|
||||
splitText.add(entry);
|
||||
entry = "";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
inQuotes = !inQuotes;
|
||||
continue; //don't append quotation character itself
|
||||
case '\\':
|
||||
if (i < text.length() - 1 && text.charAt(i + 1) == '"') {
|
||||
ch = '"'; //allow appending escaped quotation character
|
||||
i++; //prevent changing inQuotes for that character
|
||||
}
|
||||
break;
|
||||
case ',':
|
||||
if (!inQuotes) { //ignore commas outside quotes
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
entry += ch;
|
||||
}
|
||||
if (entry.length() > 0) {
|
||||
splitText.add(entry);
|
||||
}
|
||||
return splitText;
|
||||
}
|
||||
|
||||
public static <T extends InventoryItem> Predicate<T> buildItemTextFilter(String text) {
|
||||
if (text.trim().isEmpty()) {
|
||||
return Predicates.alwaysTrue();
|
||||
}
|
||||
|
||||
return new ItemTextPredicate<>(text);
|
||||
}
|
||||
|
||||
private static class ItemTextPredicate<T extends InventoryItem> implements Predicate<T> {
|
||||
private final List<String> splitText;
|
||||
|
||||
private ItemTextPredicate(String text) {
|
||||
splitText = getSplitText(text.toLowerCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(T input) {
|
||||
String name = input.getName().toLowerCase();
|
||||
for (String s : splitText) {
|
||||
if (name.contains(s)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Predicate<PaperCard> buildStarRatingFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap, final HashSet<StarRating> QuestRatings) {
|
||||
final Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap2 = buttonMap;
|
||||
return new Predicate<PaperCard>() {
|
||||
@Override
|
||||
public boolean apply(PaperCard card) {
|
||||
|
||||
StarRating r = new StarRating();
|
||||
r.Name = card.getName();
|
||||
r.Edition = card.getEdition();
|
||||
int j = 0;
|
||||
for (int i = 1; i < 6; i++) {
|
||||
r.rating = i;
|
||||
if (QuestRatings.contains(r)) {
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
boolean result = true;
|
||||
|
||||
if (j == 0) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_NONE).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
} else if (j == 1) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_1).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
} else if (j == 2) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_2).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
} else if (j == 3) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_3).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
} else if (j == 4) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_4).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
} else if (j == 5) {
|
||||
if (!buttonMap2.get(StatTypes.RATE_5).isSelected()) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Predicate<PaperCard> buildFoilFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap) {
|
||||
final int Foil = (((buttonMap.get(StatTypes.FOIL_OLD).isSelected()) ? 1 : 0)
|
||||
+ ((buttonMap.get(StatTypes.FOIL_NEW).isSelected()) ? 2 : 0)
|
||||
+ ((buttonMap.get(StatTypes.FOIL_NONE).isSelected()) ? 4 : 0));
|
||||
|
||||
return new Predicate<PaperCard>() {
|
||||
@Override
|
||||
public boolean apply(PaperCard card) {
|
||||
|
||||
boolean result = false;
|
||||
|
||||
CardEdition edition = StaticData.instance().getEditions().get(card.getEdition());
|
||||
if ((Foil & 1) == 1) {
|
||||
// Old Style Foil
|
||||
if (edition.getFoilType() == CardEdition.FoilType.OLD_STYLE) {
|
||||
result = result || card.isFoil();
|
||||
}
|
||||
}
|
||||
if ((Foil & 2) == 2) {
|
||||
// New Style Foil
|
||||
if (edition.getFoilType() == CardEdition.FoilType.MODERN) {
|
||||
result = result || card.isFoil();
|
||||
}
|
||||
}
|
||||
if ((Foil & 4) == 4) {
|
||||
result = result || !card.isFoil();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public static Predicate<PaperCard> buildColorFilter(Map<SItemManagerUtil.StatTypes, ? extends IButton> buttonMap) {
|
||||
byte colors0 = 0;
|
||||
|
||||
if (buttonMap.get(StatTypes.WHITE).isSelected()) {
|
||||
colors0 |= MagicColor.WHITE;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.BLUE).isSelected()) {
|
||||
colors0 |= MagicColor.BLUE;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.BLACK).isSelected()) {
|
||||
colors0 |= MagicColor.BLACK;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.RED).isSelected()) {
|
||||
colors0 |= MagicColor.RED;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.GREEN).isSelected()) {
|
||||
colors0 |= MagicColor.GREEN;
|
||||
}
|
||||
|
||||
final byte colors = colors0;
|
||||
final boolean wantColorless = buttonMap.get(StatTypes.COLORLESS).isSelected();
|
||||
final boolean wantMulticolor = buttonMap.get(StatTypes.MULTICOLOR).isSelected();
|
||||
|
||||
return new Predicate<PaperCard>() {
|
||||
@Override
|
||||
public boolean apply(PaperCard card) {
|
||||
CardRules rules = card.getRules();
|
||||
ColorSet color = rules.getColor();
|
||||
boolean allColorsFilteredOut = colors == 0;
|
||||
|
||||
//use color identity for lands, which allows filtering to just lands that can be played in your deck
|
||||
boolean useColorIdentity = rules.getType().isLand() && !allColorsFilteredOut && FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_FILTER_LANDS_BY_COLOR_IDENTITY);
|
||||
if (useColorIdentity) {
|
||||
color = rules.getColorIdentity();
|
||||
}
|
||||
|
||||
boolean result = true;
|
||||
if (wantMulticolor) {
|
||||
if (colors == 0) { //handle showing all multi-color cards if all 5 colors are filtered
|
||||
result = color.isMulticolor() || (wantColorless && color.isColorless());
|
||||
} else if (colors != ColorSet.ALL_COLORS.getColor()) {
|
||||
if (useColorIdentity && !allColorsFilteredOut) {
|
||||
result = color.hasAnyColor(colors) || (wantColorless && color.isColorless());
|
||||
} else {
|
||||
result = (wantColorless && color.isColorless()) || rules.canCastWithAvailable(colors);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = !color.isMulticolor();
|
||||
if (colors != ColorSet.ALL_COLORS.getColor()) {
|
||||
if (useColorIdentity && !allColorsFilteredOut) {
|
||||
result = result && (color.hasAnyColor(colors) || (wantColorless && color.isColorless()));
|
||||
} else {
|
||||
result = result && (color.isColorless() || rules.canCastWithAvailable(colors));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!wantColorless) {
|
||||
if (colors != 0 && colors != ColorSet.ALL_COLORS.getColor()) {
|
||||
//if colorless filtered out ensure phyrexian cards don't appear
|
||||
//unless at least one of their colors is selected
|
||||
result = result && color.hasAnyColor(colors);
|
||||
}
|
||||
result = result && !color.isColorless();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Predicate<DeckProxy> buildDeckColorFilter(final Map<StatTypes, ? extends IButton> buttonMap) {
|
||||
return new Predicate<DeckProxy>() {
|
||||
@Override
|
||||
public boolean apply(DeckProxy input) {
|
||||
byte colorProfile = input.getColor().getColor();
|
||||
if (colorProfile == 0) {
|
||||
return buttonMap.get(StatTypes.DECK_COLORLESS).isSelected();
|
||||
}
|
||||
|
||||
boolean wantMulticolor = buttonMap.get(StatTypes.DECK_MULTICOLOR).isSelected();
|
||||
if (!wantMulticolor && BinaryUtil.bitCount(colorProfile) > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte colors = 0;
|
||||
if (buttonMap.get(StatTypes.DECK_WHITE).isSelected()) {
|
||||
colors |= MagicColor.WHITE;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.DECK_BLUE).isSelected()) {
|
||||
colors |= MagicColor.BLUE;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.DECK_BLACK).isSelected()) {
|
||||
colors |= MagicColor.BLACK;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.DECK_RED).isSelected()) {
|
||||
colors |= MagicColor.RED;
|
||||
}
|
||||
if (buttonMap.get(StatTypes.DECK_GREEN).isSelected()) {
|
||||
colors |= MagicColor.GREEN;
|
||||
}
|
||||
|
||||
return colors == 0 && wantMulticolor && BinaryUtil.bitCount(colorProfile) > 1 || (colorProfile & colors) == colorProfile;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void showOnlyStat(StatTypes clickedStat, IButton clickedButton, Map<StatTypes, ? extends IButton> buttonMap) {
|
||||
boolean foundSelected = false;
|
||||
for (Map.Entry<StatTypes, ? extends IButton> btn : buttonMap.entrySet()) {
|
||||
if (btn.getKey() != clickedStat) {
|
||||
if (btn.getKey() == StatTypes.MULTICOLOR) {
|
||||
switch (clickedStat) {
|
||||
case WHITE:
|
||||
case BLUE:
|
||||
case BLACK:
|
||||
case RED:
|
||||
case GREEN:
|
||||
//ensure multicolor filter selected after right-clicking a color filter
|
||||
if (!btn.getValue().isSelected()) {
|
||||
btn.getValue().setSelected(true);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (btn.getKey() == StatTypes.DECK_MULTICOLOR) {
|
||||
switch (clickedStat) {
|
||||
case DECK_WHITE:
|
||||
case DECK_BLUE:
|
||||
case DECK_BLACK:
|
||||
case DECK_RED:
|
||||
case DECK_GREEN:
|
||||
//ensure multicolor filter selected after right-clicking a color filter
|
||||
if (!btn.getValue().isSelected()) {
|
||||
btn.getValue().setSelected(true);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (btn.getValue().isSelected()) {
|
||||
foundSelected = true;
|
||||
btn.getValue().setSelected(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!clickedButton.isSelected()) {
|
||||
clickedButton.setSelected(true);
|
||||
}
|
||||
else if (!foundSelected) {
|
||||
//if statLabel only label in group selected, re-select all other labels in group
|
||||
for (Map.Entry<StatTypes, ? extends IButton> btn : buttonMap.entrySet()) {
|
||||
if (btn.getKey() != clickedStat) {
|
||||
if (!btn.getValue().isSelected()) {
|
||||
btn.getValue().setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Predicate<PaperCard> buildFormatFilter(Set<GameFormat> formats, boolean allowReprints) {
|
||||
List<Predicate<PaperCard>> predicates = new ArrayList<>();
|
||||
for (GameFormat f : formats) {
|
||||
predicates.add(allowReprints ? f.getFilterRules() : f.getFilterPrinted());
|
||||
}
|
||||
return Predicates.or(predicates);
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> optimizedAnd(Predicate<T> p1, Predicate<T> p2) {
|
||||
return p1 == null ? p2 : (p2 == null ? p1 : Predicates.and(p1, p2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,180 +1,180 @@
|
||||
package forge.itemmanager;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.assets.IHasSkinProp;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.interfaces.IComboBox;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.util.ComparableOp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* Static methods for working with top-level editor methods,
|
||||
* included but not limited to preferences IO, icon generation,
|
||||
* and stats analysis.
|
||||
*
|
||||
* <br><br>
|
||||
* <i>(S at beginning of class name denotes a static factory.)</i>
|
||||
*
|
||||
*/
|
||||
public final class SItemManagerUtil {
|
||||
/** An enum to encapsulate metadata for the stats/filter objects. */
|
||||
public static enum StatTypes implements IHasSkinProp {
|
||||
WHITE (FSkinProp.IMG_MANA_W, CardRulesPredicates.Presets.IS_WHITE, "White cards"),
|
||||
BLUE (FSkinProp.IMG_MANA_U, CardRulesPredicates.Presets.IS_BLUE, "Blue cards"),
|
||||
BLACK (FSkinProp.IMG_MANA_B, CardRulesPredicates.Presets.IS_BLACK, "Black cards"),
|
||||
RED (FSkinProp.IMG_MANA_R, CardRulesPredicates.Presets.IS_RED, "Red cards"),
|
||||
GREEN (FSkinProp.IMG_MANA_G, CardRulesPredicates.Presets.IS_GREEN, "Green cards"),
|
||||
COLORLESS (FSkinProp.IMG_MANA_COLORLESS, CardRulesPredicates.Presets.IS_COLORLESS, "Colorless cards"),
|
||||
MULTICOLOR (FSkinProp.IMG_MULTI, CardRulesPredicates.Presets.IS_MULTICOLOR, "Multicolor cards"),
|
||||
|
||||
PACK_OR_DECK (FSkinProp.IMG_PACK, null, "Card packs and prebuilt decks"),
|
||||
LAND (FSkinProp.IMG_LAND, CardRulesPredicates.Presets.IS_LAND, "Lands"),
|
||||
ARTIFACT (FSkinProp.IMG_ARTIFACT, CardRulesPredicates.Presets.IS_ARTIFACT, "Artifacts"),
|
||||
CREATURE (FSkinProp.IMG_CREATURE, CardRulesPredicates.Presets.IS_CREATURE, "Creatures"),
|
||||
ENCHANTMENT (FSkinProp.IMG_ENCHANTMENT, CardRulesPredicates.Presets.IS_ENCHANTMENT, "Enchantments"),
|
||||
PLANESWALKER (FSkinProp.IMG_PLANESWALKER, CardRulesPredicates.Presets.IS_PLANESWALKER, "Planeswalkers"),
|
||||
INSTANT (FSkinProp.IMG_INSTANT, CardRulesPredicates.Presets.IS_INSTANT, "Instants"),
|
||||
SORCERY (FSkinProp.IMG_SORCERY, CardRulesPredicates.Presets.IS_SORCERY, "Sorceries"),
|
||||
|
||||
CMC_0 (FSkinProp.IMG_MANA_0, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 0), "Cards with CMC 0"),
|
||||
CMC_1 (FSkinProp.IMG_MANA_1, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 1), "Cards with CMC 1"),
|
||||
CMC_2 (FSkinProp.IMG_MANA_2, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 2), "Cards with CMC 2"),
|
||||
CMC_3 (FSkinProp.IMG_MANA_3, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 3), "Cards with CMC 3"),
|
||||
CMC_4 (FSkinProp.IMG_MANA_4, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 4), "Cards with CMC 4"),
|
||||
CMC_5 (FSkinProp.IMG_MANA_5, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 5), "Cards with CMC 5"),
|
||||
CMC_6 (FSkinProp.IMG_MANA_6, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.GT_OR_EQUAL, 6), "Cards with CMC 6+"),
|
||||
|
||||
DECK_WHITE (FSkinProp.IMG_MANA_W, null, "White decks"),
|
||||
DECK_BLUE (FSkinProp.IMG_MANA_U, null, "Blue decks"),
|
||||
DECK_BLACK (FSkinProp.IMG_MANA_B, null, "Black decks"),
|
||||
DECK_RED (FSkinProp.IMG_MANA_R, null, "Red decks"),
|
||||
DECK_GREEN (FSkinProp.IMG_MANA_G, null, "Green decks"),
|
||||
DECK_COLORLESS (FSkinProp.IMG_MANA_COLORLESS, null, "Colorless decks"),
|
||||
DECK_MULTICOLOR (FSkinProp.IMG_MULTI, null, "Multicolor decks"),
|
||||
|
||||
FOIL_OLD (FSkinProp.FOIL_11, null, "Old style Foil cards"),
|
||||
FOIL_NEW (FSkinProp.FOIL_01, null, "New style Foil cards"),
|
||||
FOIL_NONE (FSkinProp.ICO_CLOSE, null, "Non-Foil cards"),
|
||||
|
||||
RATE_NONE (FSkinProp.IMG_FAVNONE, null, "Unrated cards"),
|
||||
RATE_1 (FSkinProp.IMG_FAV1, null, "1 star cards"),
|
||||
RATE_2 (FSkinProp.IMG_FAV2, null, "2 star cards"),
|
||||
RATE_3 (FSkinProp.IMG_FAV3, null, "3 star cards"),
|
||||
RATE_4 (FSkinProp.IMG_FAV4, null, "4 star cards"),
|
||||
RATE_5 (FSkinProp.IMG_FAV5, null, "5 star cards");
|
||||
|
||||
|
||||
public final FSkinProp skinProp;
|
||||
public final Predicate<CardRules> predicate;
|
||||
public final String label;
|
||||
|
||||
private StatTypes(final FSkinProp skinProp0, final Predicate<CardRules> predicate0, final String label0) {
|
||||
skinProp = skinProp0;
|
||||
predicate = predicate0;
|
||||
label = label0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FSkinProp getSkinProp() {
|
||||
return skinProp;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getItemDisplayString(final InventoryItem item, final int qty, final boolean forTitle) {
|
||||
final List<InventoryItem> items = new ArrayList<InventoryItem>();
|
||||
items.add(item);
|
||||
return getItemDisplayString(items, qty, forTitle);
|
||||
}
|
||||
public static String getItemDisplayString(final Iterable<? extends InventoryItem> items, final int qty, final boolean forTitle) {
|
||||
//determine shared type among items
|
||||
int itemCount = 0;
|
||||
String sharedType = null;
|
||||
boolean checkForSharedType = true;
|
||||
|
||||
for (final InventoryItem item : items) {
|
||||
if (checkForSharedType) {
|
||||
if (sharedType == null) {
|
||||
sharedType = item.getItemType();
|
||||
}
|
||||
else if (!item.getItemType().equals(sharedType)) {
|
||||
sharedType = null;
|
||||
checkForSharedType = false;
|
||||
}
|
||||
}
|
||||
itemCount++;
|
||||
}
|
||||
if (sharedType == null) {
|
||||
sharedType = "Item"; //if no shared type, use generic "item"
|
||||
}
|
||||
|
||||
//build display string based on shared type, item count, and quantity of each item
|
||||
String result;
|
||||
if (forTitle) { //convert to lowercase if not for title
|
||||
result = sharedType;
|
||||
if (itemCount != 1 || qty != 1) {
|
||||
result += "s";
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = sharedType.toLowerCase();
|
||||
if (itemCount != 1) {
|
||||
result = itemCount + " " + result + "s";
|
||||
}
|
||||
if (qty < 0) { //treat negative numbers as unknown quantity
|
||||
result = "X copies of " + result;
|
||||
}
|
||||
else if (qty != 1) {
|
||||
result = qty + " copies of " + result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String buildDisplayList(final Iterable<Entry<InventoryItem, Integer>> items) {
|
||||
final List<Entry<InventoryItem, Integer>> sorted = new ArrayList<Entry<InventoryItem, Integer>>();
|
||||
for (final Entry<InventoryItem, Integer> itemEntry : items) {
|
||||
sorted.add(itemEntry);
|
||||
}
|
||||
Collections.sort(sorted, new Comparator<Entry<InventoryItem, Integer>>() {
|
||||
@Override
|
||||
public int compare(final Entry<InventoryItem, Integer> x, final Entry<InventoryItem, Integer> y) {
|
||||
return x.getKey().toString().compareTo(y.getKey().toString());
|
||||
}
|
||||
});
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (final Entry<InventoryItem, Integer> itemEntry : sorted) {
|
||||
builder.append("\n" + itemEntry.getValue() + " * " + itemEntry.getKey().toString());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static final GroupDef[] CARD_GROUPBY_OPTIONS = { GroupDef.DEFAULT, GroupDef.CARD_TYPE, GroupDef.COLOR, GroupDef.COLOR_IDENTITY, GroupDef.SET, GroupDef.CARD_RARITY };
|
||||
private static final GroupDef[] DECK_GROUPBY_OPTIONS = { GroupDef.COLOR, GroupDef.COLOR_IDENTITY, GroupDef.SET };
|
||||
private static final ColumnDef[] CARD_PILEBY_OPTIONS = { ColumnDef.CMC, ColumnDef.COLOR, ColumnDef.NAME, ColumnDef.COST, ColumnDef.TYPE, ColumnDef.RARITY, ColumnDef.SET };
|
||||
private static final ColumnDef[] DECK_PILEBY_OPTIONS = { ColumnDef.DECK_COLOR, ColumnDef.DECK_FOLDER, ColumnDef.NAME, ColumnDef.DECK_FORMAT, ColumnDef.DECK_EDITION };
|
||||
|
||||
public static void populateImageViewOptions(final IItemManager<?> itemManager, final IComboBox<Object> cbGroupByOptions, final IComboBox<Object> cbPileByOptions) {
|
||||
final boolean isDeckManager = itemManager.getGenericType().equals(DeckProxy.class);
|
||||
final GroupDef[] groupByOptions = isDeckManager ? DECK_GROUPBY_OPTIONS : CARD_GROUPBY_OPTIONS;
|
||||
final ColumnDef[] pileByOptions = isDeckManager ? DECK_PILEBY_OPTIONS : CARD_PILEBY_OPTIONS;
|
||||
cbGroupByOptions.addItem("(none)");
|
||||
cbPileByOptions.addItem("(none)");
|
||||
for (final GroupDef option : groupByOptions) {
|
||||
cbGroupByOptions.addItem(option);
|
||||
}
|
||||
for (final ColumnDef option : pileByOptions) {
|
||||
cbPileByOptions.addItem(option);
|
||||
}
|
||||
cbGroupByOptions.setSelectedIndex(0);
|
||||
cbPileByOptions.setSelectedIndex(0);
|
||||
}
|
||||
}
|
||||
package forge.itemmanager;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.assets.IHasSkinProp;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.interfaces.IComboBox;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.util.ComparableOp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* Static methods for working with top-level editor methods,
|
||||
* included but not limited to preferences IO, icon generation,
|
||||
* and stats analysis.
|
||||
*
|
||||
* <br><br>
|
||||
* <i>(S at beginning of class name denotes a static factory.)</i>
|
||||
*
|
||||
*/
|
||||
public final class SItemManagerUtil {
|
||||
/** An enum to encapsulate metadata for the stats/filter objects. */
|
||||
public static enum StatTypes implements IHasSkinProp {
|
||||
WHITE (FSkinProp.IMG_MANA_W, CardRulesPredicates.Presets.IS_WHITE, "White cards"),
|
||||
BLUE (FSkinProp.IMG_MANA_U, CardRulesPredicates.Presets.IS_BLUE, "Blue cards"),
|
||||
BLACK (FSkinProp.IMG_MANA_B, CardRulesPredicates.Presets.IS_BLACK, "Black cards"),
|
||||
RED (FSkinProp.IMG_MANA_R, CardRulesPredicates.Presets.IS_RED, "Red cards"),
|
||||
GREEN (FSkinProp.IMG_MANA_G, CardRulesPredicates.Presets.IS_GREEN, "Green cards"),
|
||||
COLORLESS (FSkinProp.IMG_MANA_COLORLESS, CardRulesPredicates.Presets.IS_COLORLESS, "Colorless cards"),
|
||||
MULTICOLOR (FSkinProp.IMG_MULTI, CardRulesPredicates.Presets.IS_MULTICOLOR, "Multicolor cards"),
|
||||
|
||||
PACK_OR_DECK (FSkinProp.IMG_PACK, null, "Card packs and prebuilt decks"),
|
||||
LAND (FSkinProp.IMG_LAND, CardRulesPredicates.Presets.IS_LAND, "Lands"),
|
||||
ARTIFACT (FSkinProp.IMG_ARTIFACT, CardRulesPredicates.Presets.IS_ARTIFACT, "Artifacts"),
|
||||
CREATURE (FSkinProp.IMG_CREATURE, CardRulesPredicates.Presets.IS_CREATURE, "Creatures"),
|
||||
ENCHANTMENT (FSkinProp.IMG_ENCHANTMENT, CardRulesPredicates.Presets.IS_ENCHANTMENT, "Enchantments"),
|
||||
PLANESWALKER (FSkinProp.IMG_PLANESWALKER, CardRulesPredicates.Presets.IS_PLANESWALKER, "Planeswalkers"),
|
||||
INSTANT (FSkinProp.IMG_INSTANT, CardRulesPredicates.Presets.IS_INSTANT, "Instants"),
|
||||
SORCERY (FSkinProp.IMG_SORCERY, CardRulesPredicates.Presets.IS_SORCERY, "Sorceries"),
|
||||
|
||||
CMC_0 (FSkinProp.IMG_MANA_0, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 0), "Cards with CMC 0"),
|
||||
CMC_1 (FSkinProp.IMG_MANA_1, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 1), "Cards with CMC 1"),
|
||||
CMC_2 (FSkinProp.IMG_MANA_2, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 2), "Cards with CMC 2"),
|
||||
CMC_3 (FSkinProp.IMG_MANA_3, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 3), "Cards with CMC 3"),
|
||||
CMC_4 (FSkinProp.IMG_MANA_4, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 4), "Cards with CMC 4"),
|
||||
CMC_5 (FSkinProp.IMG_MANA_5, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.EQUALS, 5), "Cards with CMC 5"),
|
||||
CMC_6 (FSkinProp.IMG_MANA_6, new CardRulesPredicates.LeafNumber(CardRulesPredicates.LeafNumber.CardField.CMC, ComparableOp.GT_OR_EQUAL, 6), "Cards with CMC 6+"),
|
||||
|
||||
DECK_WHITE (FSkinProp.IMG_MANA_W, null, "White decks"),
|
||||
DECK_BLUE (FSkinProp.IMG_MANA_U, null, "Blue decks"),
|
||||
DECK_BLACK (FSkinProp.IMG_MANA_B, null, "Black decks"),
|
||||
DECK_RED (FSkinProp.IMG_MANA_R, null, "Red decks"),
|
||||
DECK_GREEN (FSkinProp.IMG_MANA_G, null, "Green decks"),
|
||||
DECK_COLORLESS (FSkinProp.IMG_MANA_COLORLESS, null, "Colorless decks"),
|
||||
DECK_MULTICOLOR (FSkinProp.IMG_MULTI, null, "Multicolor decks"),
|
||||
|
||||
FOIL_OLD (FSkinProp.FOIL_11, null, "Old style Foil cards"),
|
||||
FOIL_NEW (FSkinProp.FOIL_01, null, "New style Foil cards"),
|
||||
FOIL_NONE (FSkinProp.ICO_CLOSE, null, "Non-Foil cards"),
|
||||
|
||||
RATE_NONE (FSkinProp.IMG_FAVNONE, null, "Unrated cards"),
|
||||
RATE_1 (FSkinProp.IMG_FAV1, null, "1 star cards"),
|
||||
RATE_2 (FSkinProp.IMG_FAV2, null, "2 star cards"),
|
||||
RATE_3 (FSkinProp.IMG_FAV3, null, "3 star cards"),
|
||||
RATE_4 (FSkinProp.IMG_FAV4, null, "4 star cards"),
|
||||
RATE_5 (FSkinProp.IMG_FAV5, null, "5 star cards");
|
||||
|
||||
|
||||
public final FSkinProp skinProp;
|
||||
public final Predicate<CardRules> predicate;
|
||||
public final String label;
|
||||
|
||||
private StatTypes(final FSkinProp skinProp0, final Predicate<CardRules> predicate0, final String label0) {
|
||||
skinProp = skinProp0;
|
||||
predicate = predicate0;
|
||||
label = label0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FSkinProp getSkinProp() {
|
||||
return skinProp;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getItemDisplayString(final InventoryItem item, final int qty, final boolean forTitle) {
|
||||
final List<InventoryItem> items = new ArrayList<InventoryItem>();
|
||||
items.add(item);
|
||||
return getItemDisplayString(items, qty, forTitle);
|
||||
}
|
||||
public static String getItemDisplayString(final Iterable<? extends InventoryItem> items, final int qty, final boolean forTitle) {
|
||||
//determine shared type among items
|
||||
int itemCount = 0;
|
||||
String sharedType = null;
|
||||
boolean checkForSharedType = true;
|
||||
|
||||
for (final InventoryItem item : items) {
|
||||
if (checkForSharedType) {
|
||||
if (sharedType == null) {
|
||||
sharedType = item.getItemType();
|
||||
}
|
||||
else if (!item.getItemType().equals(sharedType)) {
|
||||
sharedType = null;
|
||||
checkForSharedType = false;
|
||||
}
|
||||
}
|
||||
itemCount++;
|
||||
}
|
||||
if (sharedType == null) {
|
||||
sharedType = "Item"; //if no shared type, use generic "item"
|
||||
}
|
||||
|
||||
//build display string based on shared type, item count, and quantity of each item
|
||||
String result;
|
||||
if (forTitle) { //convert to lowercase if not for title
|
||||
result = sharedType;
|
||||
if (itemCount != 1 || qty != 1) {
|
||||
result += "s";
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = sharedType.toLowerCase();
|
||||
if (itemCount != 1) {
|
||||
result = itemCount + " " + result + "s";
|
||||
}
|
||||
if (qty < 0) { //treat negative numbers as unknown quantity
|
||||
result = "X copies of " + result;
|
||||
}
|
||||
else if (qty != 1) {
|
||||
result = qty + " copies of " + result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String buildDisplayList(final Iterable<Entry<InventoryItem, Integer>> items) {
|
||||
final List<Entry<InventoryItem, Integer>> sorted = new ArrayList<Entry<InventoryItem, Integer>>();
|
||||
for (final Entry<InventoryItem, Integer> itemEntry : items) {
|
||||
sorted.add(itemEntry);
|
||||
}
|
||||
Collections.sort(sorted, new Comparator<Entry<InventoryItem, Integer>>() {
|
||||
@Override
|
||||
public int compare(final Entry<InventoryItem, Integer> x, final Entry<InventoryItem, Integer> y) {
|
||||
return x.getKey().toString().compareTo(y.getKey().toString());
|
||||
}
|
||||
});
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (final Entry<InventoryItem, Integer> itemEntry : sorted) {
|
||||
builder.append("\n" + itemEntry.getValue() + " * " + itemEntry.getKey().toString());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static final GroupDef[] CARD_GROUPBY_OPTIONS = { GroupDef.DEFAULT, GroupDef.CARD_TYPE, GroupDef.COLOR, GroupDef.COLOR_IDENTITY, GroupDef.SET, GroupDef.CARD_RARITY };
|
||||
private static final GroupDef[] DECK_GROUPBY_OPTIONS = { GroupDef.COLOR, GroupDef.COLOR_IDENTITY, GroupDef.SET };
|
||||
private static final ColumnDef[] CARD_PILEBY_OPTIONS = { ColumnDef.CMC, ColumnDef.COLOR, ColumnDef.NAME, ColumnDef.COST, ColumnDef.TYPE, ColumnDef.RARITY, ColumnDef.SET };
|
||||
private static final ColumnDef[] DECK_PILEBY_OPTIONS = { ColumnDef.DECK_COLOR, ColumnDef.DECK_FOLDER, ColumnDef.NAME, ColumnDef.DECK_FORMAT, ColumnDef.DECK_EDITION };
|
||||
|
||||
public static void populateImageViewOptions(final IItemManager<?> itemManager, final IComboBox<Object> cbGroupByOptions, final IComboBox<Object> cbPileByOptions) {
|
||||
final boolean isDeckManager = itemManager.getGenericType().equals(DeckProxy.class);
|
||||
final GroupDef[] groupByOptions = isDeckManager ? DECK_GROUPBY_OPTIONS : CARD_GROUPBY_OPTIONS;
|
||||
final ColumnDef[] pileByOptions = isDeckManager ? DECK_PILEBY_OPTIONS : CARD_PILEBY_OPTIONS;
|
||||
cbGroupByOptions.addItem("(none)");
|
||||
cbPileByOptions.addItem("(none)");
|
||||
for (final GroupDef option : groupByOptions) {
|
||||
cbGroupByOptions.addItem(option);
|
||||
}
|
||||
for (final ColumnDef option : pileByOptions) {
|
||||
cbPileByOptions.addItem(option);
|
||||
}
|
||||
cbGroupByOptions.setSelectedIndex(0);
|
||||
cbPileByOptions.setSelectedIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class StringTokenizer implements Iterator<String> {
|
||||
|
||||
private String string;
|
||||
private int index = 0;
|
||||
|
||||
public StringTokenizer(String string) {
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < string.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String next() {
|
||||
return string.charAt(index++) + "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("remove");
|
||||
}
|
||||
|
||||
}
|
||||
package forge.itemmanager;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class StringTokenizer implements Iterator<String> {
|
||||
|
||||
private String string;
|
||||
private int index = 0;
|
||||
|
||||
public StringTokenizer(String string) {
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < string.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String next() {
|
||||
return string.charAt(index++) + "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("remove");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user