Ajout de plein de nouveaux miniels (les objets). Ajout du code du serveur aussi
This commit is contained in:
parent
3897fafc01
commit
623d5c307c
3
.gitignore
vendored
3
.gitignore
vendored
@ -13,3 +13,6 @@ bin/
|
||||
.classpath
|
||||
.settings
|
||||
.project
|
||||
|
||||
*.bernard.quickmurder
|
||||
*.log
|
||||
|
||||
28
build.gradle
28
build.gradle
@ -6,10 +6,8 @@
|
||||
* User Manual available at https://docs.gradle.org/6.0/userguide/java_library_plugin.html
|
||||
*/
|
||||
|
||||
plugins {
|
||||
// Apply the java-library plugin to add support for Java Library
|
||||
id 'java-library'
|
||||
}
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
repositories {
|
||||
// Use jcenter for resolving dependencies.
|
||||
@ -18,16 +16,20 @@ repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes(
|
||||
'Main-Class': 'com.bernard.murder.view.LauncherFrame'
|
||||
)
|
||||
}
|
||||
from {
|
||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
compile 'com.amihaiemil.web:eo-yaml:4.3.3'
|
||||
implementation 'com.amihaiemil.web:eo-yaml:5.1.3'
|
||||
implementation 'com.formdev:flatlaf:0.37'
|
||||
|
||||
// This dependency is exported to consumers, that is to say found on their compile classpath.
|
||||
api 'org.apache.commons:commons-math3:3.6.1'
|
||||
|
||||
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
|
||||
implementation 'com.google.guava:guava:28.0-jre'
|
||||
|
||||
// Use JUnit test framework
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
20
src/main/java/com/bernard/murder/BytesUtils.java
Executable file
20
src/main/java/com/bernard/murder/BytesUtils.java
Executable file
@ -0,0 +1,20 @@
|
||||
package com.bernard.murder;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class BytesUtils {
|
||||
|
||||
public static String readString(ByteBuffer buffer) {
|
||||
int stringLength = buffer.getInt();
|
||||
byte[] stringData = new byte[stringLength];
|
||||
buffer.get(stringData);
|
||||
return new String(stringData);
|
||||
}
|
||||
|
||||
public static void writeString(ByteBuffer buffer, String s) {
|
||||
byte[] data = s.getBytes();
|
||||
buffer.putInt(data.length);
|
||||
buffer.put(data);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.bernard.murder;
|
||||
|
||||
import com.bernard.murder.view.MurderatorMainFrame;
|
||||
|
||||
public class Murderator {
|
||||
|
||||
static MurderatorMainFrame mainFrame;
|
||||
|
||||
public static void main(String[] args) {
|
||||
mainFrame = new MurderatorMainFrame();
|
||||
/*File f = new File("/home/mysaa/Documents/eclipse-workspace/Murderator/uneMurder.bernard.tmurder");
|
||||
try {
|
||||
System.out.println(GameCreator.genFromFile(f));
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
mainFrame.startFrame();
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,6 +2,10 @@ package com.bernard.murder;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
@ -15,11 +19,14 @@ import java.util.stream.StreamSupport;
|
||||
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.amihaiemil.eoyaml.YamlNode;
|
||||
import com.amihaiemil.eoyaml.YamlSequence;
|
||||
import com.amihaiemil.eoyaml.YamlSequenceBuilder;
|
||||
|
||||
public class ParseUtils {
|
||||
|
||||
|
||||
static Pattern timeLengthPattern = Pattern.compile("^(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s?)?$");
|
||||
|
||||
public static long parseTimeLength(String tl) {
|
||||
@ -28,36 +35,56 @@ public class ParseUtils {
|
||||
int h = mtch.group(2)==null?0:Integer.parseInt(mtch.group(2));
|
||||
int m = mtch.group(4)==null?0:Integer.parseInt(mtch.group(4));
|
||||
int s = mtch.group(6)==null?0:Integer.parseInt(mtch.group(6));
|
||||
return h*3600+m*60+s;
|
||||
return (h*3600+m*60+s)*1000;
|
||||
}
|
||||
|
||||
public static <T> T watch(T el) {
|
||||
System.out.println(el);
|
||||
return el;
|
||||
}
|
||||
|
||||
|
||||
public static String dumpTimeLength(long t) {
|
||||
long h=t/1000/3600, m=t/1000/60%60, s=t/1000%60;
|
||||
return (h!=0?h+"h":"" )+ (m!=0?m+"m":"")+(s!=0?s+"s":"");
|
||||
}
|
||||
|
||||
|
||||
public static String dumpHourDate(long t) {
|
||||
return DateTimeFormatter.ISO_LOCAL_TIME.format(LocalTime.ofInstant(Instant.ofEpochMilli(t-t%1000), ZoneId.systemDefault()));
|
||||
}
|
||||
|
||||
|
||||
public static <T> Set<T> union(Collection<T> c1, Collection<T> c2){
|
||||
Set<T> out = c1.stream().collect(Collectors.toSet());
|
||||
out.addAll(c2);
|
||||
return out;
|
||||
}
|
||||
|
||||
public static Set<String> mappingKeys(YamlMapping mapping) throws IOException{
|
||||
return mapping.keys().stream().map(n ->{
|
||||
try {
|
||||
return Yaml.createYamlInput(n.toString()).readYamlSequence().string(0);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
public static boolean isSubWord(String word, String subword) {
|
||||
int i=0,j=0;
|
||||
while(true) {
|
||||
if(i==subword.length())return true;
|
||||
if(j==word.length())return false;
|
||||
if(subword.charAt(i)==word.charAt(j))i++;
|
||||
j++;
|
||||
}
|
||||
return null;
|
||||
}).collect(Collectors.toSet());
|
||||
}
|
||||
public static Stream<YamlNode> sequenceStream(YamlSequence sequence){
|
||||
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(sequence.iterator(),Spliterator.ORDERED),false);
|
||||
}
|
||||
|
||||
public static String node(YamlNode n){
|
||||
try {
|
||||
return Yaml.createYamlInput(n.toString()).readYamlSequence().string(0);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
public static boolean and(boolean[] bb) {
|
||||
for(boolean b : bb)
|
||||
if(!b)return false;
|
||||
return true;
|
||||
}
|
||||
return null;
|
||||
|
||||
|
||||
public static Set<String> mappingKeys(YamlMapping mapping) throws IOException{
|
||||
return mapping.keys().stream().map(n ->n.asScalar().value()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
|
||||
public static Stream<YamlNode> sequenceStream(YamlSequence sequence){
|
||||
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(sequence.iterator(),Spliterator.ORDERED),false);
|
||||
}
|
||||
|
||||
public static <T> Function<YamlNode,T> wetherMapping(Function<YamlNode,T> fnot,Function<YamlMapping,T> fyes){
|
||||
@ -67,8 +94,54 @@ public class ParseUtils {
|
||||
public static Color randColor() {
|
||||
return Color.getHSBColor((float) Math.random(), 1.0f, 1.0f);
|
||||
}
|
||||
public static Color randDarkColor() {
|
||||
return Color.getHSBColor((float) Math.random(), 1.0f, 0.3f);
|
||||
}
|
||||
public static Color randDarkBlueColor() {
|
||||
// 180° to 240°
|
||||
return Color.getHSBColor( (float) (0.5f + 0.2f*Math.random()), 1.0f, 0.3f);
|
||||
}
|
||||
public static Color getContrastColor(Color color) {
|
||||
double y = (299 * color.getRed() + 587 * color.getGreen() + 114 * color.getBlue()) / 1000;
|
||||
return y >= 128 ? Color.black : Color.white;
|
||||
}
|
||||
|
||||
|
||||
public static final <M> YamlMapping setToMapSS(Set<M> nodes, Function<M,String> key, Function<M,String> value) {
|
||||
YamlMappingBuilder builder = Yaml.createYamlMappingBuilder();
|
||||
for(M n : nodes)
|
||||
builder = builder.add(key.apply(n), value.apply(n));
|
||||
return builder.build();
|
||||
}
|
||||
public static final <M> YamlMapping setToMapSY(Set<M> nodes, Function<M,String> key, Function<M,YamlNode> value) {
|
||||
YamlMappingBuilder builder = Yaml.createYamlMappingBuilder();
|
||||
for(M n : nodes)
|
||||
builder = builder.add(key.apply(n), value.apply(n));
|
||||
return builder.build();
|
||||
}
|
||||
public static final <M> YamlMapping setToMapYS(Set<M> nodes, Function<M,YamlNode> key, Function<M,String> value) {
|
||||
YamlMappingBuilder builder = Yaml.createYamlMappingBuilder();
|
||||
for(M n : nodes)
|
||||
builder = builder.add(key.apply(n), value.apply(n));
|
||||
return builder.build();
|
||||
}
|
||||
public static final <M> YamlMapping setToMapYY(Set<M> nodes, Function<M,YamlNode> key, Function<M,YamlNode> value) {
|
||||
YamlMappingBuilder builder = Yaml.createYamlMappingBuilder();
|
||||
for(M n : nodes)
|
||||
builder = builder.add(key.apply(n), value.apply(n));
|
||||
return builder.build();
|
||||
}
|
||||
public static final <M> YamlSequence setToSeqY(Set<YamlNode> nodes) {
|
||||
YamlSequenceBuilder builder = Yaml.createYamlSequenceBuilder();
|
||||
for(YamlNode n : nodes)
|
||||
builder = builder.add(n);
|
||||
return builder.build();
|
||||
}
|
||||
public static final <M> YamlSequence setToSeqS(Set<String> nodes) {
|
||||
YamlSequenceBuilder builder = Yaml.createYamlSequenceBuilder();
|
||||
for(String n : nodes)
|
||||
builder = builder.add(n);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
120
src/main/java/com/bernard/murder/YamlUtils.java
Executable file
120
src/main/java/com/bernard/murder/YamlUtils.java
Executable file
@ -0,0 +1,120 @@
|
||||
package com.bernard.murder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collector;
|
||||
|
||||
import com.amihaiemil.eoyaml.Node;
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.amihaiemil.eoyaml.YamlNode;
|
||||
import com.amihaiemil.eoyaml.YamlSequence;
|
||||
import com.amihaiemil.eoyaml.YamlSequenceBuilder;
|
||||
|
||||
|
||||
public class YamlUtils {
|
||||
|
||||
|
||||
public static final YamlSequence listToSeq(List<YamlNode> nodes) {
|
||||
YamlSequenceBuilder ysb = Yaml.createYamlSequenceBuilder();
|
||||
for(YamlNode n : nodes)
|
||||
ysb = ysb.add(n);
|
||||
return ysb.build();
|
||||
}
|
||||
|
||||
public static final YamlSequence listToSeqString(List<String> nodes) {
|
||||
YamlSequenceBuilder ysb = Yaml.createYamlSequenceBuilder();
|
||||
for(String n : nodes)
|
||||
ysb = ysb.add(n);
|
||||
return ysb.build();
|
||||
}
|
||||
|
||||
public static final YamlMapping mapToMapping(Map<YamlNode,YamlNode> nodes) {
|
||||
YamlMappingBuilder ysb = Yaml.createYamlMappingBuilder();
|
||||
for(Entry<YamlNode, YamlNode> n : nodes.entrySet())
|
||||
ysb = ysb.add(n.getKey(),n.getValue());
|
||||
return ysb.build();
|
||||
}
|
||||
|
||||
public static final YamlSequence getSequence(YamlNode node) {
|
||||
if(node.type()==Node.SEQUENCE)return node.asSequence();
|
||||
if(node.type()==Node.SCALAR && node.asScalar().value().contentEquals("[]"))return Yaml.createYamlSequenceBuilder().build();
|
||||
throw new IllegalArgumentException("Le noeud n'est pas une séquence");
|
||||
}
|
||||
|
||||
public static final YamlMapping getMapping(YamlNode node) {
|
||||
if(node.type()==Node.MAPPING)return node.asMapping();
|
||||
if(node.type()==Node.SCALAR && node.asScalar().value().contentEquals("{}"))return Yaml.createYamlMappingBuilder().build();
|
||||
throw new IllegalArgumentException("Le noeud n'est pas une séquence");
|
||||
}
|
||||
|
||||
public static final boolean isMapping(YamlNode node) {
|
||||
return (node.type()==Node.MAPPING) || (node.type()==Node.SCALAR && node.asScalar().value().contentEquals("{}"));
|
||||
}
|
||||
|
||||
public static final boolean isSequence(YamlNode node) {
|
||||
return (node.type()==Node.SEQUENCE) || (node.type()==Node.SCALAR && node.asScalar().value().contentEquals("[]"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* (Copied from Collectors class)
|
||||
* Simple implementation class for {@code Collector}.
|
||||
*
|
||||
* @param <T> the type of elements to be collected
|
||||
* @param <R> the type of the result
|
||||
*/
|
||||
static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
|
||||
private final Supplier<A> supplier;
|
||||
private final BiConsumer<A, T> accumulator;
|
||||
private final BinaryOperator<A> combiner;
|
||||
private final Function<A, R> finisher;
|
||||
private final Set<Characteristics> characteristics;
|
||||
|
||||
CollectorImpl(Supplier<A> supplier,
|
||||
BiConsumer<A, T> accumulator,
|
||||
BinaryOperator<A> combiner,
|
||||
Function<A,R> finisher,
|
||||
Set<Characteristics> characteristics) {
|
||||
this.supplier = supplier;
|
||||
this.accumulator = accumulator;
|
||||
this.combiner = combiner;
|
||||
this.finisher = finisher;
|
||||
this.characteristics = characteristics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiConsumer<A, T> accumulator() {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Supplier<A> supplier() {
|
||||
return supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryOperator<A> combiner() {
|
||||
return combiner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<A, R> finisher() {
|
||||
return finisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Characteristics> characteristics() {
|
||||
return characteristics;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
182
src/main/java/com/bernard/murder/audio/AudioServer.java
Executable file
182
src/main/java/com/bernard/murder/audio/AudioServer.java
Executable file
@ -0,0 +1,182 @@
|
||||
package com.bernard.murder.audio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
import com.bernard.murder.BytesUtils;
|
||||
|
||||
public class AudioServer {
|
||||
|
||||
// Format des paquets [commande 1, UUID identifier, byte deviceType, String name]
|
||||
public static final byte DECLARE_NUMBER = 0x02;
|
||||
// Format des paquets [commande 1, UUID identifier, byte deviceType, int id]
|
||||
public static final byte OK_ID = 0x03;
|
||||
// Format des paquets [commande 1]
|
||||
public static final byte ASK_AUDIO_LIST= 0x04;
|
||||
// Format des paquets [commande 1, int Count, {int id, String name}]
|
||||
public static final byte GIVE_AUDIO_LIST = 0x05;
|
||||
// Format des paquets: [commande 1, int listenId, int myId]
|
||||
public static final byte ASK_STREAMING = 0x06;
|
||||
// Format des paquets: [commande 1, int id]
|
||||
public static final byte START_STREAMING = 0x07;
|
||||
// Format des paquets: [commande 1, int listenId, int myId]
|
||||
public static final byte ASK_STOP_STREAMING = 0x09;
|
||||
// Format des paquets: [commande 1, int id]
|
||||
public static final byte STOP_STREAMING = 0x08;
|
||||
// Format des paquets [commande 1, int id, ~ data]
|
||||
public static final byte AUDIO_STREAM = 0x01;
|
||||
|
||||
|
||||
public static final byte SPEAKER_DEVICE = 0x01;
|
||||
public static final byte MIC_DEVICE = 0x02;
|
||||
|
||||
|
||||
public static AudioFormat formatAudio = new AudioFormat(8000f, 16, 1, true, true);
|
||||
public static int packetMaxSize = 97282;
|
||||
public static int communicationPort = 35295;
|
||||
|
||||
public Serveur serveur;
|
||||
|
||||
int micId = 0;
|
||||
int speakerId = 0;
|
||||
|
||||
Map<Integer,String> mics;
|
||||
Map<Integer,String> speakers;
|
||||
Map<Integer,SocketAddress> micsAddr;
|
||||
Map<Integer,SocketAddress> speakersAddr;
|
||||
Map<Integer,List<Integer>> listening; // micId, List<speakerId>
|
||||
|
||||
public AudioServer() {
|
||||
mics = new HashMap<Integer, String>();
|
||||
micsAddr = new HashMap<Integer, SocketAddress>();
|
||||
speakers = new HashMap<Integer, String>();
|
||||
speakersAddr = new HashMap<Integer, SocketAddress>();
|
||||
listening = new HashMap<Integer, List<Integer>>();
|
||||
|
||||
|
||||
try {
|
||||
initServer();
|
||||
} catch (SocketException | UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void initServer() throws SocketException, UnknownHostException {
|
||||
serveur = new Serveur(this::receiveCommand, AudioServer.communicationPort);
|
||||
}
|
||||
|
||||
public void receiveCommand(ByteBuffer data,SocketAddress senderAddress) {
|
||||
byte commande = data.get();
|
||||
System.out.println("Commande reçue : "+commande);
|
||||
switch (commande) {
|
||||
|
||||
case AudioServer.DECLARE_NUMBER:
|
||||
|
||||
UUID uuid = new UUID(data.getLong(), data.getLong());
|
||||
byte deviceType = data.get();
|
||||
String deviceName = BytesUtils.readString(data);
|
||||
int newId;
|
||||
switch (deviceType) {
|
||||
case AudioServer.MIC_DEVICE:
|
||||
newId = micId++;
|
||||
mics.put(newId, deviceName);
|
||||
micsAddr.put(newId, senderAddress);
|
||||
listening.put(newId, new ArrayList<>());
|
||||
break;
|
||||
case AudioServer.SPEAKER_DEVICE:
|
||||
newId = speakerId++;
|
||||
speakers.put(newId, deviceName);
|
||||
speakersAddr.put(newId, senderAddress);
|
||||
break;
|
||||
default:return;
|
||||
}
|
||||
ByteBuffer out = ByteBuffer.allocate(AudioServer.packetMaxSize);
|
||||
out.put(AudioServer.OK_ID);
|
||||
out.putLong(uuid.getMostSignificantBits());
|
||||
out.putLong(uuid.getLeastSignificantBits());
|
||||
out.put(deviceType);
|
||||
out.putInt(newId);
|
||||
try {
|
||||
serveur.sendData(out, senderAddress);
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
break;
|
||||
case AudioServer.ASK_STREAMING:
|
||||
int listened = data.getInt();
|
||||
int listener = data.getInt();
|
||||
listening.get(listened).add(listener);
|
||||
ByteBuffer out3 = ByteBuffer.allocate(AudioServer.packetMaxSize);
|
||||
out3.put(AudioServer.START_STREAMING);
|
||||
out3.putInt(listened);
|
||||
try {
|
||||
serveur.sendData(out3, micsAddr.get(listened));
|
||||
} catch (IOException e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
break;
|
||||
|
||||
case AudioServer.STOP_STREAMING:
|
||||
int listened2 = data.getInt();
|
||||
int listener2 = data.getInt();
|
||||
listening.get(listener2).remove(listened2);
|
||||
ByteBuffer out4 = ByteBuffer.allocate(AudioServer.packetMaxSize);
|
||||
out4.put(AudioServer.STOP_STREAMING);
|
||||
out4.putInt(listened2);
|
||||
try {
|
||||
serveur.sendData(out4, micsAddr.get(listened2));
|
||||
} catch (IOException e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
break;
|
||||
|
||||
case AudioServer.AUDIO_STREAM:
|
||||
int micId = data.getInt();
|
||||
byte[] audioData = new byte[data.remaining()];
|
||||
data.get(audioData);
|
||||
|
||||
|
||||
for(int spck : listening.get(micId)) {
|
||||
data.clear();
|
||||
SocketAddress dest = speakersAddr.get(spck);
|
||||
try {
|
||||
serveur.sendData(data, dest);
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AudioServer.ASK_AUDIO_LIST:
|
||||
ByteBuffer out2 = ByteBuffer.allocate(AudioServer.packetMaxSize);
|
||||
out2.put(AudioServer.GIVE_AUDIO_LIST);
|
||||
out2.putInt(mics.size());
|
||||
for(Entry<Integer, String> e : mics.entrySet()) {
|
||||
out2.putInt(e.getKey());
|
||||
BytesUtils.writeString(out2, e.getValue());
|
||||
}
|
||||
try {
|
||||
serveur.sendData(out2, senderAddress);
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
150
src/main/java/com/bernard/murder/audio/MicServer.java
Executable file
150
src/main/java/com/bernard/murder/audio/MicServer.java
Executable file
@ -0,0 +1,150 @@
|
||||
package com.bernard.murder.audio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.TargetDataLine;
|
||||
|
||||
import com.bernard.murder.BytesUtils;
|
||||
|
||||
public class MicServer {
|
||||
|
||||
TargetDataLine micLine;
|
||||
|
||||
int packetLength = 9728;
|
||||
|
||||
int micId;
|
||||
|
||||
String micName;
|
||||
|
||||
UUID askedUUID;
|
||||
|
||||
Serveur serveur;
|
||||
|
||||
SocketAddress masterAddress;
|
||||
|
||||
Thread streamingThread;
|
||||
|
||||
volatile boolean shouldStream = false;
|
||||
|
||||
Runnable serverAnswered;
|
||||
|
||||
|
||||
public MicServer(SocketAddress adresse,String micName,TargetDataLine tdl) {
|
||||
this.micName = micName;
|
||||
this.masterAddress = adresse;
|
||||
this.micLine = tdl;
|
||||
try {
|
||||
initServer();
|
||||
initializeAudioId();
|
||||
|
||||
} catch (SocketException | UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void initializeMicDevice() throws LineUnavailableException {
|
||||
micLine.open(AudioServer.formatAudio);
|
||||
packetLength = micLine.getBufferSize()/5;
|
||||
}
|
||||
|
||||
public void initServer() throws SocketException, UnknownHostException {
|
||||
serveur = new Serveur(this::receiveCommand, AudioServer.communicationPort);
|
||||
}
|
||||
|
||||
public void initializeAudioId() {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(AudioServer.packetMaxSize);
|
||||
|
||||
|
||||
askedUUID = UUID.randomUUID();
|
||||
|
||||
buffer.put(AudioServer.DECLARE_NUMBER);
|
||||
buffer.putLong(askedUUID.getMostSignificantBits());
|
||||
buffer.putLong(askedUUID.getLeastSignificantBits());
|
||||
buffer.put(AudioServer.MIC_DEVICE);
|
||||
|
||||
BytesUtils.writeString(buffer, micName);
|
||||
|
||||
try {
|
||||
serveur.sendData(buffer,masterAddress);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveCommand(ByteBuffer data) {
|
||||
byte commande = data.get();
|
||||
switch (commande) {
|
||||
|
||||
case AudioServer.START_STREAMING:
|
||||
int micId = data.getInt();
|
||||
if(micId != this.micId)return;
|
||||
shouldStream = true;
|
||||
launchDataStream();
|
||||
break;
|
||||
case AudioServer.STOP_STREAMING:
|
||||
int micId2 = data.getInt();
|
||||
if(micId2 != this.micId)return;
|
||||
shouldStream = false;
|
||||
break;
|
||||
|
||||
case AudioServer.OK_ID:
|
||||
UUID uuid = new UUID(data.getLong(), data.getLong());
|
||||
byte deviceType = data.get();
|
||||
int deviceId = data.getInt();
|
||||
|
||||
if(!askedUUID.equals(uuid) || deviceType!=AudioServer.MIC_DEVICE)
|
||||
return;
|
||||
|
||||
micId = deviceId;
|
||||
|
||||
serverAnswered.run();
|
||||
|
||||
if(micLine==null)
|
||||
try {
|
||||
initializeMicDevice();
|
||||
} catch (LineUnavailableException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void launchDataStream() {
|
||||
if(streamingThread!=null)return;
|
||||
streamingThread = new Thread(()->{
|
||||
byte[] packetData = new byte[1+4+packetLength];
|
||||
ByteBuffer audioPacket = ByteBuffer.wrap(packetData);
|
||||
audioPacket.put(AudioServer.AUDIO_STREAM);
|
||||
audioPacket.putInt(micId);
|
||||
while(shouldStream) {
|
||||
micLine.read(packetData, 5, packetLength);
|
||||
try {
|
||||
serveur.sendData(audioPacket,masterAddress);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
streamingThread.start();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
micLine.close();
|
||||
serveur.dispose();
|
||||
}
|
||||
|
||||
public void setServerAnswered(Runnable serverAnswered) {
|
||||
this.serverAnswered = serverAnswered;
|
||||
}
|
||||
|
||||
}
|
||||
158
src/main/java/com/bernard/murder/audio/Serveur.java
Executable file
158
src/main/java/com/bernard/murder/audio/Serveur.java
Executable file
@ -0,0 +1,158 @@
|
||||
package com.bernard.murder.audio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.bernard.murder.ParseUtils;
|
||||
|
||||
public class Serveur {
|
||||
|
||||
int packetMaxLength = 9600;
|
||||
// (commande 1, uuid 16, short sliceCount 4, short sliceId 4, int totalSize 8, int offset 8, data ~)
|
||||
byte dataMergeCommand = (byte) 0xFF;
|
||||
DatagramSocket socket;
|
||||
Thread packetReceiver;
|
||||
Map<UUID, byte[]> byteArrays = new HashMap<>();
|
||||
Map<UUID, boolean[]> receivedSlicesArray = new HashMap<>();
|
||||
|
||||
volatile boolean isReceiving = false;
|
||||
|
||||
BiConsumer<ByteBuffer,SocketAddress> consumer;
|
||||
|
||||
public Serveur(Consumer<ByteBuffer> dataEater, int port) throws UnknownHostException, SocketException {
|
||||
this((b,i)->dataEater.accept(b),new InetSocketAddress(port));
|
||||
}
|
||||
public Serveur(Consumer<ByteBuffer> dataEater,SocketAddress addresse) throws UnknownHostException, SocketException {
|
||||
this((b,i)->dataEater.accept(b),addresse);
|
||||
}
|
||||
public Serveur(BiConsumer<ByteBuffer,SocketAddress> dataEater,int port) throws UnknownHostException, SocketException {
|
||||
this(dataEater,new InetSocketAddress(port));
|
||||
}
|
||||
|
||||
public Serveur(BiConsumer<ByteBuffer,SocketAddress> dataEater,SocketAddress adresse) throws SocketException {
|
||||
|
||||
byteArrays = new HashMap<UUID, byte[]>();
|
||||
receivedSlicesArray = new HashMap<UUID, boolean[]>();
|
||||
this.consumer = dataEater;
|
||||
this.socket = new DatagramSocket(adresse);
|
||||
|
||||
packetReceiver = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while(isReceiving) {
|
||||
|
||||
byte[] data = new byte[packetMaxLength];
|
||||
DatagramPacket paquet = new DatagramPacket(data, packetMaxLength);
|
||||
|
||||
try {
|
||||
try {
|
||||
socket.receive(paquet);
|
||||
}catch(SocketException e) {
|
||||
return;//probably socket closed
|
||||
}
|
||||
if(data[paquet.getOffset()]==0xFF) {
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, paquet.getOffset() + 1, 41);
|
||||
UUID uuid = new UUID(bb.getLong(), bb.getLong());
|
||||
short sliceCount = bb.getShort();
|
||||
short sliceId = bb.getShort();
|
||||
int totalSize = bb.getInt();
|
||||
int offset = bb.getInt();
|
||||
|
||||
|
||||
if(!receivedSlicesArray.containsKey(uuid)) {
|
||||
byte[] bigData = new byte[totalSize];
|
||||
boolean[] recievedArray = new boolean[sliceCount];
|
||||
byteArrays.put(uuid, bigData);
|
||||
receivedSlicesArray.put(uuid, recievedArray);
|
||||
}
|
||||
byte[] bigData = byteArrays.get(uuid);
|
||||
boolean[] recievedArray = receivedSlicesArray.get(uuid);
|
||||
System.arraycopy(data, paquet.getOffset()+41, bigData, offset, paquet.getLength()-41);
|
||||
recievedArray[sliceId] = true;
|
||||
if(!ParseUtils.and(recievedArray)) {
|
||||
ByteBuffer dataBuffer = ByteBuffer.wrap(bigData);
|
||||
consumer.accept(dataBuffer,paquet.getSocketAddress());
|
||||
byteArrays.remove(uuid);
|
||||
receivedSlicesArray.remove(uuid);
|
||||
}
|
||||
}else {
|
||||
ByteBuffer dataBuffer = ByteBuffer.wrap(data,paquet.getOffset(),paquet.getLength());
|
||||
consumer.accept(dataBuffer,paquet.getSocketAddress());
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
isReceiving = true;
|
||||
packetReceiver.start();
|
||||
}
|
||||
|
||||
public void sendData(ByteBuffer buffer,SocketAddress address) throws IOException {
|
||||
byte[] data = new byte[buffer.position()];
|
||||
buffer.clear();
|
||||
buffer.get(data);
|
||||
sendData(data,address);
|
||||
}
|
||||
public void sendData(byte[] data, SocketAddress address) throws IOException {
|
||||
if(data.length < packetMaxLength) {
|
||||
DatagramPacket packet = new DatagramPacket(data, data.length,address);
|
||||
socket.send(packet);
|
||||
}else {
|
||||
short packetCount = (short) (data.length / (packetMaxLength-42));
|
||||
short packetLength = (short) (data.length / packetCount);
|
||||
short lastPacketLength = (short) (data.length - (packetCount-1)*packetLength);
|
||||
|
||||
UUID uuid = UUID.randomUUID();
|
||||
byte[][] dataz = new byte[packetCount][];
|
||||
for (short i = 0; i < dataz.length-1; i++) {
|
||||
byte[] packagePayload = new byte[packetLength+41];
|
||||
ByteBuffer buffer = ByteBuffer.wrap(packagePayload, 0, 41);
|
||||
buffer.put(dataMergeCommand);
|
||||
buffer.putLong(uuid.getMostSignificantBits());
|
||||
buffer.putLong(uuid.getLeastSignificantBits());
|
||||
buffer.putShort(packetCount);
|
||||
buffer.putShort(i);
|
||||
buffer.putInt(data.length);
|
||||
buffer.putInt(i*packetLength);
|
||||
System.arraycopy(data, 0, packagePayload, 41, packetLength);
|
||||
dataz[i]=packagePayload;
|
||||
}
|
||||
byte[] packagePayload = new byte[packetLength+41];
|
||||
ByteBuffer buffer = ByteBuffer.wrap(packagePayload, 0, 41);
|
||||
buffer.put(dataMergeCommand);
|
||||
buffer.putLong(uuid.getMostSignificantBits());
|
||||
buffer.putLong(uuid.getLeastSignificantBits());
|
||||
buffer.putShort(packetCount);
|
||||
buffer.putShort((short) (packetCount-1));
|
||||
buffer.putInt(data.length);
|
||||
buffer.putInt((packetCount-1)*packetLength);
|
||||
System.arraycopy(data, 0, packagePayload, 41, lastPacketLength);
|
||||
dataz[packetCount-1]=packagePayload;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
public void dispose() {
|
||||
isReceiving = false;
|
||||
socket.close();
|
||||
packetReceiver.interrupt();
|
||||
}
|
||||
|
||||
}
|
||||
200
src/main/java/com/bernard/murder/audio/SpeakerServer.java
Executable file
200
src/main/java/com/bernard/murder/audio/SpeakerServer.java
Executable file
@ -0,0 +1,200 @@
|
||||
package com.bernard.murder.audio;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.SourceDataLine;
|
||||
|
||||
import com.bernard.murder.BytesUtils;
|
||||
|
||||
|
||||
public class SpeakerServer {
|
||||
|
||||
SourceDataLine speakerLine;
|
||||
|
||||
int packetLength = 9728;
|
||||
|
||||
int speakerId;
|
||||
|
||||
String speakerName;
|
||||
|
||||
UUID askedUUID;
|
||||
|
||||
Serveur serveur;
|
||||
|
||||
Map<Integer,String> mics;
|
||||
volatile boolean isMicListUpToDate = false;
|
||||
|
||||
int listeningTo = -1;
|
||||
|
||||
SocketAddress masterAddress;
|
||||
|
||||
Runnable serverAnswered;
|
||||
|
||||
|
||||
public SpeakerServer(SocketAddress serveur,String speakerName,SourceDataLine speaker) {
|
||||
this.speakerName = speakerName;
|
||||
this.masterAddress = serveur;
|
||||
this.speakerLine = speaker;
|
||||
try {
|
||||
initServer();
|
||||
initializeAudioId();
|
||||
} catch (SocketException | UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void initServer() throws SocketException, UnknownHostException {
|
||||
serveur = new Serveur(this::receiveCommand,AudioServer.communicationPort);
|
||||
}
|
||||
|
||||
public void initializeSpeakerDevice() throws LineUnavailableException {
|
||||
speakerLine.open(AudioServer.formatAudio);
|
||||
packetLength = speakerLine.getBufferSize()/5;
|
||||
}
|
||||
|
||||
public void initializeAudioId() {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(AudioServer.packetMaxSize);
|
||||
|
||||
|
||||
askedUUID = UUID.randomUUID();
|
||||
|
||||
buffer.put(AudioServer.DECLARE_NUMBER);
|
||||
buffer.putLong(askedUUID.getMostSignificantBits());
|
||||
buffer.putLong(askedUUID.getLeastSignificantBits());
|
||||
buffer.put(AudioServer.SPEAKER_DEVICE);
|
||||
|
||||
BytesUtils.writeString(buffer, speakerName);
|
||||
|
||||
|
||||
try {
|
||||
serveur.sendData(buffer,masterAddress);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void askForStream(int micId) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(AudioServer.packetMaxSize);
|
||||
|
||||
|
||||
buffer.put(AudioServer.START_STREAMING);
|
||||
buffer.putInt(micId);
|
||||
buffer.putInt(speakerId);
|
||||
|
||||
try {
|
||||
serveur.sendData(buffer,masterAddress);
|
||||
listeningTo = micId;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopStreaming() {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(AudioServer.packetMaxSize);
|
||||
|
||||
|
||||
buffer.put(AudioServer.STOP_STREAMING);
|
||||
buffer.putInt(listeningTo);
|
||||
buffer.putInt(speakerId);
|
||||
|
||||
try {
|
||||
serveur.sendData(buffer,masterAddress);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void askAudioList() {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(AudioServer.packetMaxSize);
|
||||
buffer.put(AudioServer.ASK_AUDIO_LIST);
|
||||
try {
|
||||
serveur.sendData(buffer,masterAddress);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public Map<Integer,String> getAudioList() {
|
||||
return getAudioList(false);
|
||||
}
|
||||
|
||||
public Map<Integer,String> getAudioList(boolean invalidate) {
|
||||
isMicListUpToDate = !invalidate && isMicListUpToDate;
|
||||
if(!isMicListUpToDate)askAudioList();
|
||||
while(!isMicListUpToDate) {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
System.out.println("Voici les "+mics);
|
||||
return mics;
|
||||
}
|
||||
|
||||
public void receiveCommand(ByteBuffer data) {
|
||||
byte commande = data.get();
|
||||
System.out.println("Commande recue : "+commande);
|
||||
switch (commande) {
|
||||
|
||||
case AudioServer.AUDIO_STREAM:
|
||||
int micId = data.getInt();
|
||||
if(micId != listeningTo)return;
|
||||
data.compact();
|
||||
byte[] audioData=new byte[data.remaining()];
|
||||
data.get(audioData);//XXX Check wether audio data starts at position and not at 0
|
||||
speakerLine.write(audioData, 0, packetLength);
|
||||
break;
|
||||
|
||||
case AudioServer.OK_ID:
|
||||
UUID uuid = new UUID(data.getLong(), data.getLong());
|
||||
byte deviceType = data.get();
|
||||
int deviceId = data.getInt();
|
||||
|
||||
if(!askedUUID.equals(uuid) || deviceType!=AudioServer.SPEAKER_DEVICE)
|
||||
return;
|
||||
|
||||
speakerId = deviceId;
|
||||
serverAnswered.run();
|
||||
if(speakerLine==null)
|
||||
try {
|
||||
initializeSpeakerDevice();
|
||||
} catch (LineUnavailableException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
case AudioServer.GIVE_AUDIO_LIST:
|
||||
int micCount = data.getInt();
|
||||
mics = new HashMap<Integer, String>(micCount);
|
||||
for(int i = 0; i<micCount;i++) {
|
||||
int thisMicId = data.getInt();
|
||||
mics.put(thisMicId,BytesUtils.readString(data));
|
||||
}
|
||||
isMicListUpToDate=true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
public void dispose() {
|
||||
speakerLine.close();
|
||||
serveur.dispose();
|
||||
}
|
||||
|
||||
public void setServerAnswered(Runnable serverAnswered) {
|
||||
this.serverAnswered = serverAnswered;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -1,12 +1,20 @@
|
||||
package com.bernard.murder.game;
|
||||
|
||||
import static com.bernard.murder.ParseUtils.mappingKeys;
|
||||
import static com.bernard.murder.ParseUtils.node;
|
||||
import static com.bernard.murder.ParseUtils.parseTimeLength;
|
||||
import static com.bernard.murder.ParseUtils.sequenceStream;
|
||||
|
||||
import static com.bernard.murder.ParseUtils.watch;
|
||||
|
||||
import static com.bernard.murder.YamlUtils.getMapping;
|
||||
import static com.bernard.murder.YamlUtils.isMapping;
|
||||
import static com.bernard.murder.YamlUtils.getSequence;
|
||||
import static com.bernard.murder.YamlUtils.isSequence;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
@ -16,10 +24,13 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import com.amihaiemil.eoyaml.Node;
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlInput;
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.amihaiemil.eoyaml.YamlNode;
|
||||
import com.amihaiemil.eoyaml.YamlPrinter;
|
||||
import com.amihaiemil.eoyaml.YamlSequence;
|
||||
import com.bernard.murder.ParseUtils;
|
||||
import com.bernard.murder.model.Action;
|
||||
@ -31,89 +42,89 @@ import com.bernard.murder.model.Status;
|
||||
|
||||
public class GameCreator {
|
||||
|
||||
|
||||
public static Partie genFromFile(File toread) throws IOException{
|
||||
|
||||
YamlInput input = Yaml.createYamlInput(toread);
|
||||
YamlMapping globalMap = input.readYamlMapping();
|
||||
|
||||
YamlMapping yjoueurs = globalMap.yamlMapping("joueurs");
|
||||
System.out.println(yjoueurs);
|
||||
YamlMapping yjoueurs = getMapping(globalMap.value("joueurs"));
|
||||
|
||||
// Pour pouvoir créer les objets et les espaces personnels
|
||||
Set<String> playerNames = mappingKeys(yjoueurs).stream().map(n -> n.toString()).collect(Collectors.toSet());
|
||||
|
||||
|
||||
YamlMapping yactions = globalMap.yamlMapping("actions");
|
||||
YamlMapping yactions = getMapping(globalMap.value("actions"));
|
||||
Set<Action> actions = yactions.keys()
|
||||
.stream()
|
||||
.map(n -> new Action(node(n), parseTimeLength(yactions.string(n))))
|
||||
.map(n -> new Action(n.asScalar().value(), parseTimeLength(yactions.string(n))))
|
||||
.collect(Collectors.toSet());
|
||||
Map<String,Set<Action>> persActions = playerNames.stream()
|
||||
.collect(Collectors.toMap(Function.identity(), s -> actions.stream().map(Action::clone).collect(Collectors.toSet())));
|
||||
YamlSequence yinventory = globalMap.yamlSequence("inventaire");
|
||||
|
||||
YamlSequence yinventory = getSequence(globalMap.value("inventaire"));
|
||||
|
||||
Set<String> objets = StreamSupport.stream(Spliterators.spliteratorUnknownSize(yinventory.iterator(),Spliterator.ORDERED),false)
|
||||
.map(n ->ParseUtils.node(n))
|
||||
.map(n ->n.asScalar().value())
|
||||
.collect(Collectors.toSet());
|
||||
Map<String,Set<Objet>> persObjets = playerNames.stream()
|
||||
.collect(Collectors.toMap(Function.identity(),p -> objets.stream().map(o ->new Objet(String.format(o,p))).collect(Collectors.toSet())));
|
||||
|
||||
YamlSequence ystatus = globalMap.yamlSequence("status");
|
||||
Set<Status> status = sequenceStream(ystatus).map(n -> new Status(node(n))).collect(Collectors.toSet());
|
||||
YamlSequence ystatus = getSequence(globalMap.value("status"));
|
||||
Set<Status> status = sequenceStream(ystatus).map(n -> new Status(n.asScalar().value())).collect(Collectors.toSet());
|
||||
|
||||
YamlMapping yespaces = globalMap.yamlMapping("espaces");
|
||||
YamlMapping yespaces = getMapping(globalMap.value("espaces"));
|
||||
|
||||
Map<String, Map<Objet, Integer>> objetsDansEspaces = yespaces.keys().stream().collect(Collectors.toMap(
|
||||
n -> node(n),
|
||||
n-> parseHiddenObjects(yespaces.yamlSequence(n))
|
||||
n -> n.asScalar().value(),
|
||||
n-> parseHiddenObjects(getSequence(yespaces.value(n)))
|
||||
));
|
||||
Set<Piece> espaceObjets = yespaces.keys().stream()
|
||||
.map(n -> new Piece(node(n), objetsDansEspaces.get(node(n))))
|
||||
.map(n -> new Piece(n.asScalar().value(), objetsDansEspaces.get(n.asScalar().value())))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
YamlMapping yespacesPersos = globalMap.yamlMapping("espacesPersos");
|
||||
YamlMapping yespacesPersos = getMapping(globalMap.value("espacesPersos"));
|
||||
|
||||
Map<String,Set<Piece>> persespacesPersos = playerNames.stream().collect(Collectors.toMap(
|
||||
Function.identity(),
|
||||
p -> yespacesPersos.keys().stream()
|
||||
.map(e -> new Piece(
|
||||
String.format(node(e), p),
|
||||
parseHiddenObjects(yespacesPersos.yamlSequence(e),p)
|
||||
String.format(e.asScalar().value(), p),
|
||||
parseHiddenObjects(getSequence(yespacesPersos.value(e)),p)
|
||||
))
|
||||
.collect(Collectors.toSet())
|
||||
));
|
||||
|
||||
//Per perso settings
|
||||
for(YamlNode pn : yjoueurs.keys()) {
|
||||
String pname = node(pn);
|
||||
System.out.println(pn);
|
||||
System.out.println(yjoueurs.yamlMapping(pn));
|
||||
String pname = pn.asScalar().value();
|
||||
persActions.get(pname).addAll(
|
||||
yjoueurs.yamlMapping(pn).yamlMapping("actions").keys()
|
||||
getMapping(getMapping(yjoueurs.value(pn)).value("actions")).keys()
|
||||
.stream()
|
||||
.map(n -> new Action(node(n), parseTimeLength(yjoueurs.yamlMapping(pn).yamlMapping("actions").string(n))))
|
||||
.map(n -> new Action(n.asScalar().value(), parseTimeLength(getMapping(getMapping(yjoueurs.value(pn)).value("actions")).string(n))))
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
persObjets.get(pname).addAll(
|
||||
StreamSupport.stream(Spliterators.spliteratorUnknownSize(yjoueurs.yamlMapping(pn).yamlSequence("inventaire").iterator(),Spliterator.ORDERED),false)
|
||||
.map(n ->ParseUtils.node(n))
|
||||
StreamSupport.stream(Spliterators.spliteratorUnknownSize(getSequence(getMapping(yjoueurs.value(pn)).value("inventaire")).iterator(),Spliterator.ORDERED),false)
|
||||
.map(n ->n.asScalar().value())
|
||||
.map(o ->new Objet(o))
|
||||
.collect(Collectors.toSet())
|
||||
);
|
||||
if(yjoueurs.yamlMapping(pn).yamlMapping("espacePerso")!= null)
|
||||
if(isMapping(getMapping(yjoueurs.value(pn)).value("espacePerso")))
|
||||
// Plusieurs espaces
|
||||
yjoueurs.yamlMapping(pn).yamlMapping("espacePerso").keys().forEach(n ->
|
||||
getMapping(getMapping(yjoueurs.value(pn)).value("espacePerso")).keys().forEach(n ->
|
||||
persespacesPersos.get(pname)
|
||||
.stream()
|
||||
.filter(p -> p.getNom().contentEquals(node(n)))
|
||||
.filter(p -> p.getNom().contentEquals(n.asScalar().value()))
|
||||
.findAny()
|
||||
.orElseGet(() -> new Piece(node(n)))
|
||||
.insertObjects(parseHiddenObjects(yjoueurs.yamlMapping(pn).yamlMapping("espacePerso").yamlSequence(n)))
|
||||
.orElseGet(() -> new Piece(n.asScalar().value()))
|
||||
.insertObjects(parseHiddenObjects(getSequence(getMapping(getMapping(yjoueurs.value(pn)).value("espacePerso")).value(n))))
|
||||
|
||||
);
|
||||
else
|
||||
((persespacesPersos.get(pname).isEmpty())?
|
||||
Stream.of(new Piece(String.format("Espace de %s",pname))):persespacesPersos.get(pname).stream())
|
||||
.forEach(p -> p.insertObjects(parseHiddenObjects(yjoueurs.yamlMapping(pn).yamlSequence("espacePerso"))));
|
||||
.forEach(p -> p.insertObjects(parseHiddenObjects(getSequence(getMapping(yjoueurs.value(pn)).value("espacePerso")))));
|
||||
|
||||
|
||||
}
|
||||
@ -126,8 +137,8 @@ public class GameCreator {
|
||||
persActions.get(p),
|
||||
status.stream().filter(st -> sequenceStream(ystatus)
|
||||
.filter(n -> n instanceof YamlMapping)
|
||||
.filter(n -> ((YamlMapping)n).string(st.getName())!=null)
|
||||
.filter(n -> ((YamlMapping)((YamlMapping)n).yamlMapping(st.getName())).string("onStart").contentEquals("true"))
|
||||
.filter(n -> getMapping(n).string(st.getName())!=null)
|
||||
.filter(n -> getMapping(getMapping(n).value(st.getName())).string("onStart").contentEquals("true"))
|
||||
.findAny().isPresent())
|
||||
.collect(Collectors.toSet()),
|
||||
persespacesPersos.get(p)
|
||||
@ -138,12 +149,130 @@ public class GameCreator {
|
||||
|
||||
private static Map<Objet,Integer> parseHiddenObjects(YamlSequence sequence,Object... nameFormat){
|
||||
return sequenceStream(sequence).collect(Collectors.toMap(
|
||||
on -> new Objet(String.format((on instanceof YamlMapping)?(((YamlMapping)on).keys().stream().map(nn -> node(nn)).findAny().get()):node(on),nameFormat)),
|
||||
on -> ((on instanceof YamlMapping)?(((YamlMapping)on).integer(((YamlMapping)on).keys().stream().findAny().get())):-1)
|
||||
on -> new Objet(String.format((on.type()==Node.MAPPING)?(on.asMapping().keys().stream().map(nn -> nn.asScalar().value()).findAny().get()):on.asScalar().value(),nameFormat)),
|
||||
on -> ((on.type()==Node.MAPPING)?(on.asMapping().integer(on.asMapping().keys().stream().findAny().get())):-1)
|
||||
));
|
||||
}
|
||||
private static Map<Objet,Integer> parseHiddenObjects(YamlSequence sequence){
|
||||
return parseHiddenObjects(sequence, new Object[0]);
|
||||
}
|
||||
|
||||
public static final void quickSave(File f, Partie p, YamlMapping minelsMap) throws IOException {
|
||||
YamlMappingBuilder globalMapping = Yaml.createYamlMappingBuilder()
|
||||
|
||||
.add("personnages",
|
||||
ParseUtils.setToMapSY(p.personnagesStream().collect(Collectors.toSet()),
|
||||
perso -> perso.getNom(),
|
||||
perso ->
|
||||
Yaml.createYamlMappingBuilder()
|
||||
|
||||
.add("actions",ParseUtils.setToMapSY(perso.getActions(),
|
||||
act -> act.getName(),
|
||||
act -> Yaml.createYamlMappingBuilder()
|
||||
.add("basetime", Long.toString(act.getBasetime()))
|
||||
.add("triggerTime", Long.toString(act.getTriggertime()))
|
||||
.build()))
|
||||
|
||||
.add("espacePerso",ParseUtils.setToMapSY(perso.streamEspacesPersos().collect(Collectors.toSet()),
|
||||
esp -> esp.getNom(),
|
||||
esp -> ParseUtils.setToSeqY(esp.streamHiddenObjects().map(etr -> Yaml.createYamlMappingBuilder().add(etr.getKey().getNom(), Integer.toString(etr.getValue())).build()).collect(Collectors.toSet()))
|
||||
))
|
||||
|
||||
.add("status", ParseUtils.setToSeqS(perso.streamStatus().map(Status::getName).collect(Collectors.toSet())))
|
||||
|
||||
.add("inventaire", ParseUtils.setToSeqS(perso.getInventaire().stream().map(Objet::getNom).collect(Collectors.toSet()))).build()
|
||||
))
|
||||
|
||||
.add("status", ParseUtils.setToSeqS(p.statuzStream().map(Status::getName).collect(Collectors.toSet())))
|
||||
|
||||
.add("pieces",ParseUtils.setToMapSY(p.piecesStream().collect(Collectors.toSet()),
|
||||
Piece::getNom,
|
||||
esp -> ParseUtils.setToSeqY(esp.streamHiddenObjects().map(etr -> Yaml.createYamlMappingBuilder().add(etr.getKey().getNom(), Integer.toString(etr.getValue())).build()).collect(Collectors.toSet()))
|
||||
))
|
||||
.add("minels", minelsMap);
|
||||
|
||||
|
||||
YamlPrinter printer = Yaml.createYamlPrinter(new FileWriter(f));
|
||||
|
||||
printer.print(globalMapping.build());
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static final QuicksavedPartie readQuickSave(File f) throws IOException {
|
||||
YamlInput input = Yaml.createYamlInput(f);
|
||||
YamlMapping globalMap = input.readYamlMapping();
|
||||
|
||||
YamlSequence ystatus = getSequence(globalMap.value("status"));
|
||||
Set<Status> status = sequenceStream(ystatus).map(n -> new Status(n.asScalar().value())).collect(Collectors.toSet());
|
||||
|
||||
|
||||
YamlMapping yespaces = getMapping(globalMap.value("pieces"));
|
||||
Map<String, Map<Objet, Integer>> objetsDansEspaces = yespaces.keys().stream().collect(Collectors.toMap(
|
||||
n -> watch(watch(n).asScalar().value()),
|
||||
n-> parseHiddenObjects(getSequence(yespaces.value(n)))
|
||||
));
|
||||
Set<Piece> espaceObjets = yespaces.keys().stream()
|
||||
.map(n -> new Piece(n.asScalar().value(), objetsDansEspaces.get(n.asScalar().value())))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
|
||||
YamlMapping yjoueurs = getMapping(globalMap.value("personnages"));
|
||||
|
||||
Set<Personnage> personnages = new HashSet<Personnage>();
|
||||
for(YamlNode pn : yjoueurs.keys()) {
|
||||
String pname = pn.asScalar().value();
|
||||
|
||||
Set<Action> actions = getMapping(getMapping(yjoueurs.value(pn)).value("actions")).keys()
|
||||
.stream()
|
||||
.map(n -> new Action(n.asScalar().value(), Long.parseLong(getMapping(getMapping(getMapping(yjoueurs.value(pn)).value("actions")).value(n)).string("basetime")),
|
||||
Long.parseLong(getMapping(getMapping(getMapping(yjoueurs.value(pn)).value("actions")).value(n)).string("triggerTime"))))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<Objet> inventaire =
|
||||
StreamSupport.stream(Spliterators.spliteratorUnknownSize(getSequence(getMapping(yjoueurs.value(pn)).value("inventaire")).iterator(),Spliterator.ORDERED),false)
|
||||
.map(n ->n.asScalar().value())
|
||||
.map(o ->new Objet(o))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<Piece> espacesPerso = getMapping(getMapping(yjoueurs.value(pn)).value("espacePerso")).keys().stream().map(n ->
|
||||
new Piece(n.asScalar().value(), parseHiddenObjects(getSequence(getMapping(getMapping(yjoueurs.value(pn)).value("espacePerso")).value(n))))).collect(Collectors.toSet());
|
||||
|
||||
Set<Status> persoStatus = status.stream().filter(
|
||||
s -> !isSequence(getMapping(yjoueurs.value(pn)).value("status"))?false:getSequence(getMapping(yjoueurs.value(pn)).value("status")).values().stream().anyMatch(n -> n.asScalar().value().equals(s.getName()))
|
||||
).collect(Collectors.toSet());
|
||||
|
||||
|
||||
personnages.add(new Personnage(pname, inventaire, actions, persoStatus, espacesPerso));
|
||||
}
|
||||
|
||||
YamlMapping minelsMap = getMapping(globalMap.value("minels"));
|
||||
|
||||
return new QuicksavedPartie(new Partie(personnages, status, espaceObjets),minelsMap);
|
||||
|
||||
}
|
||||
|
||||
public static class QuicksavedPartie{
|
||||
Partie partie;
|
||||
YamlMapping minelsMap;
|
||||
|
||||
|
||||
public QuicksavedPartie(Partie partie, YamlMapping minelsMap) {
|
||||
this.partie = partie;
|
||||
this.minelsMap = minelsMap;
|
||||
}
|
||||
|
||||
public Partie getPartie() {
|
||||
return partie;
|
||||
}
|
||||
|
||||
|
||||
public YamlMapping getMinelsMap() {
|
||||
return minelsMap;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,13 +1,126 @@
|
||||
package com.bernard.murder.game;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.swing.Timer;
|
||||
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.bernard.murder.model.Inventaire;
|
||||
import com.bernard.murder.model.Objet;
|
||||
import com.bernard.murder.model.Partie;
|
||||
import com.bernard.murder.model.Personnage;
|
||||
|
||||
public class GameManager {
|
||||
|
||||
Partie partie;
|
||||
Map<Inventaire,Set<Runnable>> inventoryUpdateListeners;
|
||||
|
||||
long startTime;
|
||||
|
||||
Timer quickSaver;
|
||||
|
||||
Supplier<YamlMapping> minelsQuicksaver;
|
||||
|
||||
public GameManager(Partie partie) {
|
||||
this.partie = partie;
|
||||
this.inventoryUpdateListeners = new HashMap<Inventaire, Set<Runnable>>();
|
||||
this.minelsQuicksaver = () -> Yaml.createYamlMappingBuilder().build();
|
||||
startTime = System.currentTimeMillis();
|
||||
|
||||
quickSaver = new Timer(10_000, e -> this.quickSave());
|
||||
quickSaver.start();
|
||||
}
|
||||
|
||||
public synchronized void moveObjet(Objet o, Inventaire toInv) {
|
||||
Inventaire inv = partie.findObjectInventory(o);
|
||||
System.out.println("Moving "+o+" from "+inv+" to "+toInv);
|
||||
inv.removeObjet(o);
|
||||
toInv.addObjet(o);
|
||||
inventoryUpdate(inv);
|
||||
inventoryUpdate(toInv);
|
||||
}
|
||||
|
||||
public void inventoryUpdate(Inventaire inv) {
|
||||
if(!inventoryUpdateListeners.containsKey(inv))return;
|
||||
for(Runnable r : inventoryUpdateListeners.get(inv))
|
||||
r.run();
|
||||
}
|
||||
|
||||
public void dumpCurrentState() {
|
||||
System.out.println(partie);
|
||||
}
|
||||
|
||||
public void addInventoryUpdateListener(Inventaire inv, Runnable runnable) {
|
||||
if(!inventoryUpdateListeners.containsKey(inv))
|
||||
inventoryUpdateListeners.put(inv, new HashSet<Runnable>());
|
||||
inventoryUpdateListeners.get(inv).add(runnable);
|
||||
}
|
||||
|
||||
public void quickSave() {
|
||||
System.out.println("Quicksaving");
|
||||
File toSave = new File(quickSaveFilename());
|
||||
File tempOldSave = new File(quickSaveFilename()+".tmp");
|
||||
if(toSave.exists())toSave.renameTo(tempOldSave);
|
||||
|
||||
try {
|
||||
GameCreator.quickSave(toSave, partie,minelsQuicksaver.get());
|
||||
System.out.println("Quicksaved");
|
||||
if(tempOldSave.exists())tempOldSave.delete();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String quickSaveFilename() {
|
||||
return "murder-"+DateTimeFormatter.ofPattern("uu-MM-dd_HH'h'mm").withZone(ZoneId.systemDefault()).withLocale(Locale.getDefault()).format(Instant.ofEpochMilli(startTime))+".bernard.quickmurder";
|
||||
}
|
||||
|
||||
public Set<Inventaire> getEveryInventaire() {
|
||||
Set<Inventaire> inventaires = new HashSet<Inventaire>();
|
||||
inventaires.addAll(partie.pieces());
|
||||
inventaires.addAll(partie.personnages());
|
||||
partie.personnagesStream().forEach(p -> inventaires.addAll(p.espacePersos()));
|
||||
return inventaires;
|
||||
}
|
||||
|
||||
public Set<Inventaire> getEveryInventaireByName(Set<String> names) {
|
||||
Set<Inventaire> inventaires = new HashSet<Inventaire>();
|
||||
inventaires.addAll(partie.pieces());
|
||||
inventaires.addAll(partie.personnages());
|
||||
partie.personnagesStream().forEach(p -> inventaires.addAll(p.espacePersos()));
|
||||
return inventaires.stream().filter(i -> names.contains(i.getInventoryName())).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public Personnage getPersoByName(String key) {
|
||||
return partie.personnagesStream().filter(p -> key.equalsIgnoreCase(p.getNom())).findAny().orElse(null);
|
||||
}
|
||||
|
||||
public void bindMinelQuicksaver(Supplier<YamlMapping> minelsQuicksaver) {
|
||||
this.minelsQuicksaver = minelsQuicksaver;
|
||||
}
|
||||
|
||||
public Inventaire getInventoryByName(String name) {
|
||||
Set<Inventaire> inventaires = new HashSet<Inventaire>();
|
||||
inventaires.addAll(partie.pieces());
|
||||
inventaires.addAll(partie.personnages());
|
||||
partie.personnagesStream().forEach(p -> inventaires.addAll(p.espacePersos()));
|
||||
return inventaires.stream().filter(i -> name.equalsIgnoreCase(i.getInventoryName())).findAny().orElseGet(()->{
|
||||
System.out.println("JE n'ai pas trouvé l'inventaire "+name+" dans la liste "+inventaires.stream().map(Inventaire::getInventoryName).collect(Collectors.joining(",")));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,9 +9,17 @@ public class Action implements Cloneable{
|
||||
public Action(String action, long basetime) {
|
||||
this.action = action;
|
||||
this.basetime = basetime;
|
||||
this.triggertime = Long.MIN_VALUE;
|
||||
this.triggertime = 0;
|
||||
}
|
||||
|
||||
public Action(String action, long basetime, long triggertime) {
|
||||
this.action = action;
|
||||
this.basetime = basetime;
|
||||
this.triggertime = triggertime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Action clone() {
|
||||
Action actions = new Action(action, basetime);
|
||||
@ -24,6 +32,38 @@ public class Action implements Cloneable{
|
||||
return "Action [action=" + action + ", basetime=" + basetime + ", triggertime=" + triggertime + ", transient id=" + System.identityHashCode(this) + "]";
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public boolean canBeLaunched() {
|
||||
return System.currentTimeMillis()-triggertime-basetime>0;
|
||||
}
|
||||
|
||||
public void launch() {
|
||||
triggertime=System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean hasFinished() {
|
||||
return triggertime + basetime - System.currentTimeMillis()<0;
|
||||
}
|
||||
|
||||
public long timeToWaitLeft() {
|
||||
return basetime - System.currentTimeMillis() + triggertime;
|
||||
}
|
||||
|
||||
public long dateReset() {
|
||||
return triggertime + basetime;
|
||||
}
|
||||
|
||||
public long getBasetime() {
|
||||
return basetime;
|
||||
}
|
||||
|
||||
public long getTriggertime() {
|
||||
return triggertime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -6,4 +6,10 @@ public interface Inventaire {
|
||||
|
||||
Set<Objet> getObjects();
|
||||
|
||||
void removeObjet(Objet o);
|
||||
|
||||
void addObjet(Objet o);
|
||||
|
||||
String getInventoryName();
|
||||
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
package com.bernard.murder.model;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Partie {
|
||||
|
||||
|
||||
Set<Personnage> personnages;
|
||||
Set<Status> statuz;
|
||||
Set<Piece> piece;
|
||||
@ -34,6 +36,35 @@ public class Partie {
|
||||
return "Partie [personnages=" + personnages + ", statuz=" + statuz + ", piece=" + piece + "]";
|
||||
}
|
||||
|
||||
public Inventaire findObjectInventory(Objet o) {
|
||||
Optional<Personnage> persoInv = personnages.stream().filter(p -> p.inventaire.contains(o)).findAny();
|
||||
if(persoInv.isPresent())return persoInv.get();
|
||||
|
||||
Optional<Piece> persoInvRoom = personnages.stream()
|
||||
.map(p -> p.espacesPersos.stream()
|
||||
.filter(ep -> ep.contenu.keySet().contains(o)).findAny())
|
||||
.filter(Optional::isPresent).map(Optional::get).findAny();
|
||||
if(persoInvRoom.isPresent())return persoInvRoom.get();
|
||||
|
||||
Optional<Piece> invRoom = piece.stream()
|
||||
.filter(ep -> ep.contenu.keySet().contains(o)).findAny();
|
||||
if(invRoom.isPresent())return invRoom.get();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream<Status> statuzStream() {
|
||||
return statuz.stream();
|
||||
}
|
||||
|
||||
public Set<Piece> pieces() {
|
||||
return piece;
|
||||
}
|
||||
|
||||
public Set<Personnage> personnages() {
|
||||
return personnages;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -34,6 +34,10 @@ public class Personnage implements Inventaire{
|
||||
return inventaire;
|
||||
}
|
||||
|
||||
public Set<Action> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public Stream<Piece> streamEspacesPersos(){
|
||||
return espacesPersos.stream();
|
||||
}
|
||||
@ -55,5 +59,41 @@ public class Personnage implements Inventaire{
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void removeObjet(Objet o) {
|
||||
System.out.println("Avant :"+inventaire);
|
||||
this.inventaire.remove(o);
|
||||
System.out.println("Après :"+inventaire);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void addObjet(Objet o) {
|
||||
this.inventaire.add(o);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Stream<Status> streamStatus() {
|
||||
return status.stream();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getInventoryName() {
|
||||
return "Inventaire de "+getNom();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Set<Piece> espacePersos() {
|
||||
return espacesPersos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -2,7 +2,9 @@ package com.bernard.murder.model;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Piece implements Inventaire{
|
||||
|
||||
@ -37,6 +39,24 @@ public class Piece implements Inventaire{
|
||||
contenu.putAll(objs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeObjet(Objet o) {
|
||||
this.contenu.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addObjet(Objet o) {
|
||||
this.contenu.put(o,-1);
|
||||
}
|
||||
|
||||
public Stream<Entry<Objet, Integer>> streamHiddenObjects() {
|
||||
return contenu.entrySet().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInventoryName() {
|
||||
return nom;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
module murder{
|
||||
|
||||
requires com.amihaiemil.eoyaml;
|
||||
requires java.desktop;
|
||||
|
||||
}
|
||||
106
src/main/java/com/bernard/murder/util/view/MouseReactiveTabbedPane.java
Executable file
106
src/main/java/com/bernard/murder/util/view/MouseReactiveTabbedPane.java
Executable file
@ -0,0 +1,106 @@
|
||||
package com.bernard.murder.util.view;
|
||||
|
||||
import java.awt.MouseInfo;
|
||||
import java.awt.Point;
|
||||
import java.awt.dnd.DropTargetDragEvent;
|
||||
import java.awt.dnd.DropTargetDropEvent;
|
||||
import java.awt.dnd.DropTargetEvent;
|
||||
import java.awt.dnd.DropTargetListener;
|
||||
import java.util.TooManyListenersException;
|
||||
|
||||
import javax.swing.JTabbedPane;
|
||||
|
||||
import com.bernard.murder.view.minel.objetDnD.NotADropTarget;
|
||||
|
||||
public class MouseReactiveTabbedPane extends JTabbedPane {
|
||||
|
||||
private static final long serialVersionUID = -4985256252193243545L;
|
||||
long waitTime = 500_000_000;
|
||||
Thread plannedThread;
|
||||
int dropAcceptance;
|
||||
|
||||
int hoverIndex = -1;
|
||||
long enteredTime = -1;
|
||||
|
||||
public MouseReactiveTabbedPane(int tabPlacement) {
|
||||
super(tabPlacement);
|
||||
|
||||
final MouseReactiveTabbedPane pane = this;
|
||||
|
||||
this.setDropTarget(new NotADropTarget());
|
||||
|
||||
try {
|
||||
this.getDropTarget().addDropTargetListener(new DropTargetListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void dragOver(DropTargetDragEvent dtde) {
|
||||
int tab = getTab(dtde);
|
||||
System.out.println(">"+tab+"/"+hoverIndex+"-"+enteredTime);
|
||||
if(tab==-1) {
|
||||
enteredTime=-1;
|
||||
hoverIndex=-1;
|
||||
return;
|
||||
}
|
||||
if(tab!=hoverIndex) {
|
||||
//On viens d'entrer dans un nouveau tab !
|
||||
enteredTime=System.nanoTime();
|
||||
hoverIndex=tab;
|
||||
if(plannedThread==null){
|
||||
plannedThread = new Thread(() -> {
|
||||
while(System.nanoTime()>enteredTime+waitTime) {
|
||||
try {
|
||||
Thread.sleep(2);
|
||||
} catch (InterruptedException e1) {}
|
||||
}
|
||||
if(getTab() == hoverIndex)
|
||||
pane.setSelectedIndex(hoverIndex);
|
||||
hoverIndex = -1;
|
||||
enteredTime = -1;
|
||||
plannedThread = null;
|
||||
});
|
||||
plannedThread.start();
|
||||
}
|
||||
}
|
||||
dtde.acceptDrag(dropAcceptance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dropActionChanged(DropTargetDragEvent dtde) {}
|
||||
@Override
|
||||
public void drop(DropTargetDropEvent dtde) {}
|
||||
@Override
|
||||
public void dragExit(DropTargetEvent dte) {
|
||||
enteredTime=-1;
|
||||
hoverIndex=-1;
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void dragEnter(DropTargetDragEvent e) {}
|
||||
});
|
||||
} catch (TooManyListenersException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getTab(DropTargetDragEvent dtde) {
|
||||
for (int i = 0; i < this.getTabCount(); i++)
|
||||
if (this.getBoundsAt(i).contains(dtde.getLocation()))
|
||||
return i;
|
||||
return -1;
|
||||
|
||||
}
|
||||
public int getTab() {
|
||||
Point loc = MouseInfo.getPointerInfo().getLocation();
|
||||
Point screen = this.getLocationOnScreen();
|
||||
Point point = new Point(loc.x - screen.x, loc.y - screen.y);
|
||||
for (int i = 0; i < this.getTabCount(); i++)
|
||||
if (this.getBoundsAt(i).contains(point))
|
||||
return i;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
18
src/main/java/com/bernard/murder/util/view/SimpleDocumentListener.java
Executable file
18
src/main/java/com/bernard/murder/util/view/SimpleDocumentListener.java
Executable file
@ -0,0 +1,18 @@
|
||||
package com.bernard.murder.util.view;
|
||||
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
|
||||
public abstract class SimpleDocumentListener implements DocumentListener {
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
changedUpdate(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
changedUpdate(e);
|
||||
}
|
||||
|
||||
}
|
||||
138
src/main/java/com/bernard/murder/view/EnceinteServeurFrame.java
Executable file
138
src/main/java/com/bernard/murder/view/EnceinteServeurFrame.java
Executable file
@ -0,0 +1,138 @@
|
||||
package com.bernard.murder.view;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.Line;
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.Mixer;
|
||||
import javax.sound.sampled.Mixer.Info;
|
||||
import javax.sound.sampled.SourceDataLine;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import com.bernard.murder.audio.AudioServer;
|
||||
import com.bernard.murder.audio.SpeakerServer;
|
||||
|
||||
public class EnceinteServeurFrame extends JFrame{
|
||||
|
||||
private static final long serialVersionUID = -2023529082781210475L;
|
||||
|
||||
SpeakerServer serveur;
|
||||
String deviceName;
|
||||
|
||||
public EnceinteServeurFrame(String deviceName) {
|
||||
this.setSize(300, 500);
|
||||
this.setMinimumSize(new Dimension(100, 200));
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
this.setTitle("Serveur audio");
|
||||
this.deviceName = deviceName;
|
||||
|
||||
this.setContentPane(genContentPan());
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
public JPanel genContentPan() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
|
||||
|
||||
|
||||
InformedSourceDataline[] marray = getEnceinteList();
|
||||
JList<InformedSourceDataline> enceinteListe = new JList<InformedSourceDataline>(marray);
|
||||
|
||||
|
||||
JPanel masterPanel = new JPanel(new BorderLayout());
|
||||
JTextField masterIP = new JTextField("192.168.1.1");
|
||||
JButton serverControl = new JButton("Lancer");
|
||||
masterPanel.add(serverControl,BorderLayout.EAST);
|
||||
masterPanel.add(masterIP,BorderLayout.CENTER);
|
||||
|
||||
JList<NamedMicrophone> mics = new JList<>();
|
||||
|
||||
serverControl.addActionListener(e->{
|
||||
if(enceinteListe.getSelectedValue()==null)return;
|
||||
serverControl.setEnabled(false);
|
||||
if(serveur!=null) {
|
||||
serveur.dispose();
|
||||
serveur = null;
|
||||
serverControl.setText("Lancer");
|
||||
}else {
|
||||
serveur = new SpeakerServer(new InetSocketAddress(masterIP.getText(), AudioServer.communicationPort), deviceName,enceinteListe.getSelectedValue().tdl);
|
||||
serveur.setServerAnswered(()->{
|
||||
serverControl.setText("Arrêter");
|
||||
List<NamedMicrophone> list = serveur.getAudioList().entrySet().stream().map(et -> new NamedMicrophone(et.getKey(), et.getValue())).collect(Collectors.toList());
|
||||
NamedMicrophone[] micarray = new NamedMicrophone[list.size()];
|
||||
list.toArray(micarray);
|
||||
mics.setListData(micarray);
|
||||
});
|
||||
serverControl.setText("Lancement");
|
||||
}
|
||||
serverControl.setEnabled(true);
|
||||
});
|
||||
|
||||
panel.add(masterPanel,BorderLayout.NORTH);
|
||||
panel.add(mics,BorderLayout.SOUTH);
|
||||
panel.add(enceinteListe,BorderLayout.CENTER);
|
||||
return panel;
|
||||
}
|
||||
|
||||
public static final InformedSourceDataline[] getEnceinteList() {
|
||||
List<InformedSourceDataline> linfo = new ArrayList<>();
|
||||
Line.Info srcInfo = new Line.Info(SourceDataLine.class);
|
||||
Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
|
||||
for (Mixer.Info info : mixerInfos) {
|
||||
Mixer mixer = AudioSystem.getMixer(info);
|
||||
try {
|
||||
SourceDataLine tdl = (SourceDataLine)mixer.getLine(srcInfo);
|
||||
linfo.add(new InformedSourceDataline(tdl, info));
|
||||
} catch (LineUnavailableException|IllegalArgumentException e) {}
|
||||
}
|
||||
InformedSourceDataline[] marray = new InformedSourceDataline[linfo.size()];
|
||||
linfo.toArray(marray);
|
||||
return marray;
|
||||
}
|
||||
|
||||
|
||||
public static class InformedSourceDataline {
|
||||
|
||||
SourceDataLine tdl;
|
||||
Mixer.Info mixerInfo;
|
||||
|
||||
public InformedSourceDataline(SourceDataLine tdl, Info mixerInfo) {
|
||||
this.tdl = tdl;
|
||||
this.mixerInfo = mixerInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mixerInfo.getDescription();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class NamedMicrophone {
|
||||
|
||||
int micId;
|
||||
String micName;
|
||||
|
||||
public NamedMicrophone(int micId, String micName) {
|
||||
this.micId = micId;
|
||||
this.micName = micName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return micName;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
package com.bernard.murder.view;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.bernard.murder.model.Inventaire;
|
||||
import com.bernard.murder.model.Objet;
|
||||
|
||||
public class GlobalUIManager implements MouseListener{
|
||||
|
||||
public GlobalUIManager(JPanel globalPan) {
|
||||
globalPan.addMouseListener(this);
|
||||
}
|
||||
|
||||
Set<Objet> currentUIselection = new HashSet<Objet>();
|
||||
Map<JPanel,Inventaire> inventaire = new HashMap<>();
|
||||
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
System.out.println(e.getSource());
|
||||
System.out.println(e.getComponent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
|
||||
|
||||
if(e.getButton()==MouseEvent.NOBUTTON) {
|
||||
currentUIselection.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
if(e.getButton()==MouseEvent.NOBUTTON) {
|
||||
// Le clic a peut être été laché à l'exterieur
|
||||
currentUIselection.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
104
src/main/java/com/bernard/murder/view/HoverSelect.java
Executable file
104
src/main/java/com/bernard/murder/view/HoverSelect.java
Executable file
@ -0,0 +1,104 @@
|
||||
package com.bernard.murder.view;
|
||||
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.dnd.DnDConstants;
|
||||
import java.awt.dnd.DropTargetDragEvent;
|
||||
import java.awt.dnd.DropTargetDropEvent;
|
||||
import java.awt.dnd.DropTargetEvent;
|
||||
import java.awt.dnd.DropTargetListener;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTabbedPane;
|
||||
|
||||
public class HoverSelect implements DropTargetListener,Runnable{
|
||||
|
||||
long enteredTime = -1;
|
||||
long waitTime = 500_000_000;
|
||||
Runnable onSelect;
|
||||
Thread plannedThread;
|
||||
int dropAcceptance;
|
||||
|
||||
public HoverSelect(Runnable onSelect,long waitTime,int shouldAcceptDrop){
|
||||
this.onSelect = onSelect;
|
||||
this.waitTime = waitTime;
|
||||
this.dropAcceptance = shouldAcceptDrop;
|
||||
}
|
||||
public HoverSelect(CardLayout layout, JPanel panel, String identifier, long waitTime,int shouldAcceptDrop) {
|
||||
this(() -> layout.show(panel, identifier),waitTime,shouldAcceptDrop);
|
||||
}
|
||||
|
||||
public HoverSelect(JTabbedPane tabbedPan, int index, long waitTime,int shouldAcceptDrop) {
|
||||
this(() -> tabbedPan.setSelectedIndex(index),waitTime,shouldAcceptDrop);
|
||||
}
|
||||
|
||||
public HoverSelect(Runnable onSelect,int shouldAcceptDrop){
|
||||
this.onSelect = onSelect;
|
||||
this.dropAcceptance = shouldAcceptDrop;
|
||||
}
|
||||
|
||||
public HoverSelect(CardLayout layout, JPanel panel, String identifier,int shouldAcceptDrop) {
|
||||
this(() -> layout.show(panel, identifier),shouldAcceptDrop);
|
||||
}
|
||||
public HoverSelect(Runnable onSelect,long waitTime){
|
||||
this(onSelect,waitTime,DnDConstants.ACTION_NONE);
|
||||
}
|
||||
public HoverSelect(CardLayout layout, JPanel panel, String identifier, long waitTime) {
|
||||
this(() -> layout.show(panel, identifier),waitTime,DnDConstants.ACTION_NONE);
|
||||
}
|
||||
public HoverSelect(JTabbedPane tabbedPan, int index, int shouldAcceptDrop) {
|
||||
this(() -> tabbedPan.setSelectedIndex(index),shouldAcceptDrop);
|
||||
}
|
||||
public HoverSelect(JTabbedPane tabbedPan, int index, long waitTime) {
|
||||
this(() -> tabbedPan.setSelectedIndex(index),waitTime,DnDConstants.ACTION_NONE);
|
||||
}
|
||||
|
||||
public HoverSelect(Runnable onSelect){
|
||||
this(onSelect, DnDConstants.ACTION_NONE);
|
||||
}
|
||||
public HoverSelect(CardLayout layout, JPanel panel, String identifier) {
|
||||
this(() -> layout.show(panel, identifier),DnDConstants.ACTION_NONE);
|
||||
}
|
||||
public HoverSelect(JTabbedPane tabbedPan, int index) {
|
||||
this(() -> tabbedPan.setSelectedIndex(index),DnDConstants.ACTION_NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragEnter(DropTargetDragEvent e) {
|
||||
enteredTime = System.nanoTime();
|
||||
System.out.println("entré");
|
||||
plannedThread = new Thread(()-> {
|
||||
try {
|
||||
Thread.sleep(waitTime/1_000_000, (int)(waitTime%1_000_000));
|
||||
onSelect.run();
|
||||
} catch (InterruptedException e1) {}
|
||||
});
|
||||
plannedThread.run();
|
||||
e.acceptDrag(dropAcceptance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragExit(DropTargetEvent e) {
|
||||
if(plannedThread!=null)plannedThread.interrupt();
|
||||
plannedThread = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragOver(DropTargetDragEvent dtde) {}
|
||||
@Override
|
||||
public void dropActionChanged(DropTargetDragEvent dtde) {}
|
||||
@Override
|
||||
public void drop(DropTargetDropEvent dtde) {}
|
||||
@Override
|
||||
public void run() {
|
||||
enteredTime = System.nanoTime();
|
||||
System.out.println("entré");
|
||||
plannedThread = new Thread(()-> {
|
||||
try {
|
||||
Thread.sleep(waitTime/1_000_000, (int)(waitTime%1_000_000));
|
||||
onSelect.run();
|
||||
} catch (InterruptedException e1) {}
|
||||
});
|
||||
plannedThread.run();
|
||||
}
|
||||
|
||||
}
|
||||
139
src/main/java/com/bernard/murder/view/LauncherFrame.java
Executable file
139
src/main/java/com/bernard/murder/view/LauncherFrame.java
Executable file
@ -0,0 +1,139 @@
|
||||
package com.bernard.murder.view;
|
||||
|
||||
import java.awt.GridLayout;
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import com.bernard.murder.game.GameCreator;
|
||||
import com.bernard.murder.game.GameCreator.QuicksavedPartie;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.model.Partie;
|
||||
import com.bernard.murder.model.Personnage;
|
||||
import com.bernard.murder.view.minel.Minel;
|
||||
|
||||
public class LauncherFrame extends JFrame{
|
||||
|
||||
private static final long serialVersionUID = 5831232688024137883L;
|
||||
|
||||
public static void main(String[] args) {
|
||||
new LauncherFrame();
|
||||
}
|
||||
|
||||
public LauncherFrame() {
|
||||
try {
|
||||
//TODO implement flatlaf look&feel
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
this.setTitle("Configuration du terminal");
|
||||
this.setSize(300, 200);
|
||||
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
|
||||
JPanel contentPan = new JPanel(new GridLayout(5,1));
|
||||
|
||||
|
||||
JButton creerMaitre = new JButton("Terminal maître");
|
||||
creerMaitre.addActionListener(e -> {
|
||||
this.setEnabled(false);
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
int returnState = chooser.showOpenDialog(this);
|
||||
if(returnState==JFileChooser.APPROVE_OPTION) {
|
||||
File toread = chooser.getSelectedFile();
|
||||
try {
|
||||
Partie partie = GameCreator.genFromFile(toread);
|
||||
GameManager manager = new GameManager(partie);
|
||||
Map<String,List<Minel>> minelsSup = MinelsCreator.genSupMinels(partie,manager);
|
||||
Map<Personnage,List<Minel>> minels = MinelsCreator.genPersoMinels(partie,manager);
|
||||
|
||||
new MurderatorGameFrame("Murder du "+DateFormat.getDateInstance().format(Calendar.getInstance().getTime()),partie,manager,minelsSup,minels);
|
||||
this.setVisible(false);
|
||||
dispose();
|
||||
|
||||
}catch(Exception ex) {
|
||||
ex.printStackTrace();
|
||||
JOptionPane.showMessageDialog(this, ex.getLocalizedMessage(), "Impossible de lire le fichier", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
this.setEnabled(true);
|
||||
});
|
||||
|
||||
JButton creerEsclave = new JButton("Terminal esclave");
|
||||
creerEsclave.setEnabled(false);
|
||||
|
||||
JButton creerEnceinte = new JButton("Enceinte");
|
||||
creerEnceinte.addActionListener(e -> {
|
||||
this.setEnabled(false);
|
||||
String name = JOptionPane.showInputDialog(this, "Nom de l'enceinte", "Nom de l'enceinte", JOptionPane.PLAIN_MESSAGE);
|
||||
if(name != null) {
|
||||
new EnceinteServeurFrame(name);
|
||||
this.setVisible(false);
|
||||
dispose();
|
||||
} else {
|
||||
this.setEnabled(true);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
JButton creerMicro = new JButton("Microphone");
|
||||
creerMicro.addActionListener(e -> {
|
||||
this.setEnabled(false);
|
||||
String name = JOptionPane.showInputDialog(this, "Nom du microphone", "Nom du microphone", JOptionPane.PLAIN_MESSAGE);
|
||||
if(name != null) {
|
||||
new MicServeurFrame(name);
|
||||
this.setVisible(false);
|
||||
dispose();
|
||||
} else {
|
||||
this.setEnabled(true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
JButton chargerSauvegarde = new JButton("Charger Sauvegarde");
|
||||
chargerSauvegarde.addActionListener(e -> {
|
||||
this.setEnabled(false);
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
int returnState = chooser.showOpenDialog(this);
|
||||
if(returnState==JFileChooser.APPROVE_OPTION) {
|
||||
File toread = chooser.getSelectedFile();
|
||||
try {
|
||||
QuicksavedPartie qpartie = GameCreator.readQuickSave(toread);
|
||||
GameManager manager = new GameManager(qpartie.getPartie());
|
||||
|
||||
new MurderatorGameFrame("Murder du "+DateFormat.getDateInstance().format(Calendar.getInstance().getTime()),qpartie,manager);
|
||||
this.setVisible(false);
|
||||
dispose();
|
||||
|
||||
}catch(Exception ex) {
|
||||
ex.printStackTrace();
|
||||
JOptionPane.showMessageDialog(this, ex.getLocalizedMessage(), "Impossible de lire le fichier", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
this.setEnabled(true);
|
||||
});
|
||||
|
||||
contentPan.add(creerMaitre);
|
||||
contentPan.add(creerEsclave);
|
||||
contentPan.add(creerMicro);
|
||||
contentPan.add(creerEnceinte);
|
||||
contentPan.add(chargerSauvegarde);
|
||||
|
||||
this.setContentPane(contentPan);
|
||||
this.pack();
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
}
|
||||
113
src/main/java/com/bernard/murder/view/MicServeurFrame.java
Executable file
113
src/main/java/com/bernard/murder/view/MicServeurFrame.java
Executable file
@ -0,0 +1,113 @@
|
||||
package com.bernard.murder.view;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.Line;
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.Mixer;
|
||||
import javax.sound.sampled.Mixer.Info;
|
||||
import javax.sound.sampled.TargetDataLine;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import com.bernard.murder.audio.AudioServer;
|
||||
import com.bernard.murder.audio.MicServer;
|
||||
|
||||
public class MicServeurFrame extends JFrame{
|
||||
|
||||
private static final long serialVersionUID = -2023529082781210475L;
|
||||
|
||||
MicServer serveur;
|
||||
String deviceName;
|
||||
|
||||
public MicServeurFrame(String deviceName) {
|
||||
this.setSize(300, 500);
|
||||
this.setMinimumSize(new Dimension(100, 200));
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
this.setTitle("Serveur audio");
|
||||
this.deviceName = deviceName;
|
||||
|
||||
this.setContentPane(genContentPan());
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
public JPanel genContentPan() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
|
||||
|
||||
|
||||
InformedTargetDataline[] marray = getEnceinteList();
|
||||
JList<InformedTargetDataline> micListe = new JList<InformedTargetDataline>(marray);
|
||||
|
||||
|
||||
JPanel masterPanel = new JPanel(new BorderLayout());
|
||||
JTextField masterIP = new JTextField("192.168.1.1");
|
||||
JButton serverControl = new JButton("Lancer");
|
||||
masterPanel.add(serverControl,BorderLayout.EAST);
|
||||
masterPanel.add(masterIP,BorderLayout.CENTER);
|
||||
|
||||
serverControl.addActionListener(e->{
|
||||
if(micListe.getSelectedValue()==null)return;
|
||||
serverControl.setEnabled(false);
|
||||
if(serveur!=null) {
|
||||
serveur.dispose();
|
||||
serveur = null;
|
||||
serverControl.setText("Lancer");
|
||||
}else {
|
||||
serveur = new MicServer(new InetSocketAddress(masterIP.getText(), AudioServer.communicationPort), deviceName,micListe.getSelectedValue().tdl);
|
||||
serveur.setServerAnswered(()->{
|
||||
serverControl.setText("Arrêter");
|
||||
});
|
||||
serverControl.setText("Lancement");
|
||||
}
|
||||
serverControl.setEnabled(true);
|
||||
});
|
||||
|
||||
panel.add(masterPanel,BorderLayout.NORTH);
|
||||
panel.add(micListe,BorderLayout.CENTER);
|
||||
return panel;
|
||||
}
|
||||
|
||||
public static final InformedTargetDataline[] getEnceinteList() {
|
||||
List<InformedTargetDataline> linfo = new ArrayList<>();
|
||||
Line.Info srcInfo = new Line.Info(TargetDataLine.class);
|
||||
Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
|
||||
for (Mixer.Info info : mixerInfos) {
|
||||
Mixer mixer = AudioSystem.getMixer(info);
|
||||
try {
|
||||
TargetDataLine tdl = (TargetDataLine)mixer.getLine(srcInfo);
|
||||
linfo.add(new InformedTargetDataline(tdl, info));
|
||||
} catch (LineUnavailableException|IllegalArgumentException e) {}
|
||||
}
|
||||
InformedTargetDataline[] marray = new InformedTargetDataline[linfo.size()];
|
||||
linfo.toArray(marray);
|
||||
return marray;
|
||||
}
|
||||
|
||||
public static class InformedTargetDataline {
|
||||
|
||||
TargetDataLine tdl;
|
||||
Mixer.Info mixerInfo;
|
||||
|
||||
public InformedTargetDataline(TargetDataLine tdl, Info mixerInfo) {
|
||||
this.tdl = tdl;
|
||||
this.mixerInfo = mixerInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mixerInfo.getDescription();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
package com.bernard.murder.view;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -7,35 +9,51 @@ import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.amihaiemil.eoyaml.YamlNode;
|
||||
import com.amihaiemil.eoyaml.YamlSequence;
|
||||
import com.bernard.murder.YamlUtils;
|
||||
import com.bernard.murder.game.GameCreator.QuicksavedPartie;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.model.Partie;
|
||||
import com.bernard.murder.model.Personnage;
|
||||
import com.bernard.murder.view.minel.ActionsMinel;
|
||||
import com.bernard.murder.view.minel.InventaireMinel;
|
||||
import com.bernard.murder.view.minel.Minel;
|
||||
import com.bernard.murder.view.minel.ObjetSearchMinel;
|
||||
import com.bernard.murder.view.minel.ServeurMinel;
|
||||
import com.bernard.murder.view.minel.TextPanMinel;
|
||||
|
||||
public class MinelsCreator {
|
||||
|
||||
public static Map<String, List<Minel>> genSupMinels(Partie partie, GameManager manager) {
|
||||
Map<String, List<Minel>> outPute = new HashMap<String, List<Minel>>();
|
||||
public static Map<String, List<Minel>> genSupMinels(Partie qpartie, GameManager manager) {
|
||||
|
||||
Map<String, List<Minel>> outPute = new HashMap<String, List<Minel>>();
|
||||
List<Minel> generalMinels = new ArrayList<Minel>();
|
||||
|
||||
partie.piecesStream().map(p -> new InventaireMinel(manager, p)).forEach(m -> generalMinels.add(m));
|
||||
List<Minel> piecesMinels = new ArrayList<>();
|
||||
qpartie.piecesStream().map(p -> new InventaireMinel(manager, p)).forEach(m -> piecesMinels.add(m));
|
||||
|
||||
generalMinels.add(new TextPanMinel(manager));
|
||||
generalMinels.add(new ObjetSearchMinel(manager, manager.getEveryInventaire()));
|
||||
generalMinels.add(new ServeurMinel(manager));
|
||||
|
||||
outPute.put("Général", generalMinels);
|
||||
outPute.put("Pièces", piecesMinels);
|
||||
return outPute;
|
||||
}
|
||||
|
||||
public static Map<Personnage, List<Minel>> genMinels(Partie partie, GameManager manager) {
|
||||
public static Map<Personnage, List<Minel>> genPersoMinels(Partie partie, GameManager manager) {
|
||||
return partie.personnagesStream().collect(Collectors.toMap(Function.identity(), p -> genMinelsForPerso(partie,manager,p)));
|
||||
}
|
||||
|
||||
private static List<Minel> genMinelsForPerso(Partie partie, GameManager manager, Personnage personnage){
|
||||
List<Minel> minels = new ArrayList<Minel>();
|
||||
|
||||
minels.add(new ActionsMinel(manager, personnage));
|
||||
|
||||
minels.add(new InventaireMinel(manager, personnage));
|
||||
personnage.streamEspacesPersos().map(p -> new InventaireMinel(manager, p)).forEach(m -> minels.add(m));
|
||||
|
||||
@ -45,5 +63,83 @@ public class MinelsCreator {
|
||||
return minels;
|
||||
}
|
||||
|
||||
public static Map<String, List<Minel>> genSupMinels(QuicksavedPartie qpartie, GameManager manager) {
|
||||
return genMinels("sups", qpartie, manager);
|
||||
}
|
||||
|
||||
public static Map<Personnage, List<Minel>> genPersoMinels(QuicksavedPartie qpartie, GameManager manager) {
|
||||
return genMinels("persos", qpartie, manager).entrySet().stream().collect(Collectors.toMap(e -> manager.getPersoByName(e.getKey()), Map.Entry::getValue));
|
||||
}
|
||||
|
||||
|
||||
private static Map<String, List<Minel>> genMinels(String minelType,QuicksavedPartie qpartie, GameManager manager) {
|
||||
Map<String, List<Minel>> outPute = new HashMap<String, List<Minel>>();
|
||||
|
||||
YamlMapping supMap = qpartie.getMinelsMap().yamlMapping(minelType);
|
||||
|
||||
for(YamlNode n : supMap.keys()) {
|
||||
YamlSequence minels = supMap.yamlSequence(n);
|
||||
String minelName = n.asScalar().value();
|
||||
List<Minel> minelList = new ArrayList<Minel>();
|
||||
for(YamlNode minelNode : minels) {
|
||||
YamlMapping minel = minelNode.asMapping();
|
||||
String className = minel.value("minelClass").asScalar().value();
|
||||
try {
|
||||
Class<?> minelClass = Class.forName(className);
|
||||
Constructor<?> minelConstructor = minelClass.getConstructor(GameManager.class,YamlMapping.class);
|
||||
Object minelObj = minelConstructor.newInstance(manager,minel);
|
||||
if(minelObj instanceof Minel) {
|
||||
minelList.add((Minel) minelObj);
|
||||
}else {
|
||||
throw new ClassCastException();
|
||||
}
|
||||
} catch (InstantiationException e) {
|
||||
System.err.println("La classe "+className+" n'est pas prévu pour être instanciable !");
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
System.err.println("Le constructeur (GameManager,YamlMapping) de la classe "+className+" n'est pas public");
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.println("Euhhhhhhhhh, ce doit être une erreur de code interne");
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
System.err.println("La recréation du minel de classe "+className+" a foiré");
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
System.err.println("La classe "+className+" n'a pas de constructeur (GameManager,YamlMapping)");
|
||||
e.printStackTrace();
|
||||
} catch (SecurityException e) {
|
||||
System.err.println("La classe "+className+" n'est pas accessible");
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("La classe "+className+" n'est pas chargée !");
|
||||
e.printStackTrace();
|
||||
} catch (ClassCastException e) {
|
||||
System.err.println("La classe "+className+" n'est pas un Minel !");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
outPute.put(minelName, minelList);
|
||||
}
|
||||
|
||||
return outPute;
|
||||
}
|
||||
|
||||
public static YamlMapping createMinelQuicksave(Map<Personnage, List<Minel>> persoMinels, Map<String, List<Minel>> supMinels) {
|
||||
YamlMappingBuilder supMapBuilder = Yaml.createYamlMappingBuilder();
|
||||
for(String supName : supMinels.keySet()) {
|
||||
List<YamlNode> seq = supMinels.get(supName).stream().map(m -> m.saveToYaml().add("minelClass", m.getClass().getName()).build()).collect(Collectors.toList());
|
||||
supMapBuilder = supMapBuilder.add(supName, YamlUtils.listToSeq(seq));
|
||||
}
|
||||
YamlMappingBuilder persoBuilder = Yaml.createYamlMappingBuilder();
|
||||
for(Personnage perso : persoMinels.keySet())
|
||||
persoBuilder = persoBuilder.add(perso.getNom(), YamlUtils.listToSeq(persoMinels.get(perso).stream().map(m -> m.saveToYaml().add("minelClass", m.getClass().getName()).build()).collect(Collectors.toList())));
|
||||
|
||||
|
||||
return Yaml.createYamlMappingBuilder()
|
||||
.add("sups", supMapBuilder.build())
|
||||
.add("persos", persoBuilder.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
122
src/main/java/com/bernard/murder/view/MurderatorGameFrame.java
Executable file
122
src/main/java/com/bernard/murder/view/MurderatorGameFrame.java
Executable file
@ -0,0 +1,122 @@
|
||||
package com.bernard.murder.view;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridLayout;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
|
||||
import com.bernard.murder.ParseUtils;
|
||||
import com.bernard.murder.game.GameCreator.QuicksavedPartie;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.model.Partie;
|
||||
import com.bernard.murder.model.Personnage;
|
||||
import com.bernard.murder.util.view.MouseReactiveTabbedPane;
|
||||
import com.bernard.murder.view.minel.Minel;
|
||||
|
||||
public class MurderatorGameFrame extends JFrame{
|
||||
|
||||
private static final long serialVersionUID = -4512350072325470066L;
|
||||
|
||||
|
||||
Map<String,List<Minel>> minelsSup;
|
||||
Map<Personnage,List<Minel>> minels;
|
||||
|
||||
public MurderatorGameFrame(String frameName, Partie partie, GameManager manager,Map<String,List<Minel>> minelsSup,Map<Personnage,List<Minel>> minels) {
|
||||
this.setSize(700, 500);
|
||||
this.setMinimumSize(new Dimension(200, 100));
|
||||
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
this.setTitle(frameName);
|
||||
this.minelsSup = minelsSup;
|
||||
this.minels = minels;
|
||||
manager.bindMinelQuicksaver(() -> MinelsCreator.createMinelQuicksave(minels, minelsSup));
|
||||
|
||||
this.setContentPane(genGamePane(partie,manager,minelsSup,minels));
|
||||
this.pack();
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
public MurderatorGameFrame(String frameName, QuicksavedPartie qpartie, GameManager manager) {
|
||||
this(frameName,qpartie.getPartie(),manager,MinelsCreator.genSupMinels(qpartie, manager),MinelsCreator.genPersoMinels(qpartie, manager));
|
||||
}
|
||||
|
||||
public MurderatorGameFrame(String frameName, Partie partie, GameManager manager) {
|
||||
this(frameName,partie,manager,MinelsCreator.genSupMinels(partie, manager),MinelsCreator.genPersoMinels(partie, manager));
|
||||
}
|
||||
|
||||
public JPanel genGamePane(Partie partie,GameManager manager,Map<String,List<Minel>> minelsSup,Map<Personnage,List<Minel>> minels) {
|
||||
|
||||
JPanel globalPan = new JPanel(new BorderLayout());
|
||||
|
||||
//Center Panel
|
||||
MouseReactiveTabbedPane centerPan = new MouseReactiveTabbedPane(JTabbedPane.TOP);
|
||||
|
||||
int j = 0;
|
||||
|
||||
for(String s : minelsSup.keySet()) {
|
||||
JPanel centralLocalBpanPan = new JPanel(new GridLayout(2,(minelsSup.get(s).size()+1)/2,-1,-1));
|
||||
minelsSup.get(s).stream().map(m -> m.genContentPane()).forEach(mpan -> {centralLocalBpanPan.add(mpan);mpan.setBorder(BorderFactory.createLineBorder(ParseUtils.randDarkBlueColor(),2));});
|
||||
JScrollPane centralLocalPan = new JScrollPane(centralLocalBpanPan);
|
||||
centerPan.insertTab(s,null,centralLocalPan,null,j++);
|
||||
System.out.println(j);
|
||||
}
|
||||
|
||||
for(Personnage p : minels.keySet()) {
|
||||
JPanel centralLocalBpanPan = new JPanel(new GridLayout(2, (minels.get(p).size()+1)/2,-1,-1));
|
||||
minels.get(p).stream().map(m -> m.genContentPane()).forEach(mpan -> {centralLocalBpanPan.add(mpan);mpan.setBorder(BorderFactory.createLineBorder(ParseUtils.randDarkBlueColor(),2));});
|
||||
JScrollPane centralLocalPan = new JScrollPane(centralLocalBpanPan);
|
||||
centerPan.insertTab(p.getNom(),null,centralLocalPan,null,j++);
|
||||
System.out.println(j);
|
||||
}
|
||||
|
||||
for (int i = 0; i < centerPan.getTabCount(); i++) {
|
||||
System.out.println(i);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
//Left Panel
|
||||
JPanel leftPan = new JPanel(new GridLayout(minels.size() + minelsSup.size(), 1));
|
||||
|
||||
for(String s : minelsSup.keySet()) {
|
||||
JButton localButton = new JButton(s);
|
||||
localButton.addActionListener(e -> centerLayout.show(centerPan, s));
|
||||
try {
|
||||
localButton.setDropTarget(new NotADropTarget());
|
||||
localButton.getDropTarget().addDropTargetListener(new HoverSelect(centerLayout, centerPan, s));
|
||||
} catch (TooManyListenersException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
leftPan.add(localButton);
|
||||
}
|
||||
for(Personnage p : minels.keySet()) {
|
||||
JButton localButton = new JButton(p.getNom());
|
||||
localButton.addActionListener(e -> centerLayout.show(centerPan, personnageIdentifier(p)));
|
||||
try {
|
||||
localButton.setDropTarget(new ObjetDropTarget(manager, p, ()->manager.inventoryUpdate(p)));
|
||||
localButton.getDropTarget().addDropTargetListener(new HoverSelect(centerLayout, centerPan, personnageIdentifier(p),DnDConstants.ACTION_MOVE));
|
||||
} catch (TooManyListenersException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
leftPan.add(localButton);
|
||||
}
|
||||
|
||||
globalPan.add(leftPan, BorderLayout.WEST);
|
||||
*/
|
||||
globalPan.add(centerPan, BorderLayout.CENTER);
|
||||
return globalPan;
|
||||
}
|
||||
|
||||
|
||||
public String personnageIdentifier(Personnage personnage) {
|
||||
return String.format("%08X",System.identityHashCode(personnage))+personnage.getNom();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,128 +0,0 @@
|
||||
package com.bernard.murder.view;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridLayout;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
import com.bernard.murder.game.GameCreator;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.model.Partie;
|
||||
import com.bernard.murder.model.Personnage;
|
||||
import com.bernard.murder.view.minel.Minel;
|
||||
|
||||
public class MurderatorMainFrame extends JFrame{
|
||||
|
||||
private static final long serialVersionUID = -4512350072325470066L;
|
||||
|
||||
|
||||
public MurderatorMainFrame() {
|
||||
|
||||
}
|
||||
|
||||
public void startFrame() {
|
||||
this.setSize(700, 500);
|
||||
this.setMinimumSize(new Dimension(575, 200));
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
this.setTitle("En attente d'un fichier");
|
||||
|
||||
this.setContentPane(genFirstPanel());
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
public JPanel genFirstPanel() {
|
||||
JPanel globalPanel = new JPanel();
|
||||
globalPanel.setLayout(new BoxLayout(globalPanel, BoxLayout.PAGE_AXIS));
|
||||
JPanel semiPan = new JPanel();
|
||||
semiPan.setLayout(new BoxLayout(semiPan, BoxLayout.LINE_AXIS));
|
||||
JButton loadFile = new JButton("Ouvrir un fichier");
|
||||
|
||||
loadFile.addActionListener(e -> {
|
||||
this.setEnabled(false);
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
int returnState = chooser.showOpenDialog(this);
|
||||
if(returnState==JFileChooser.APPROVE_OPTION) {
|
||||
File toread = chooser.getSelectedFile();
|
||||
try {
|
||||
Partie partie = GameCreator.genFromFile(toread);
|
||||
GameManager manager = new GameManager(partie);
|
||||
Map<String,List<Minel>> minelsSup = MinelsCreator.genSupMinels(partie,manager);
|
||||
Map<Personnage,List<Minel>> minels = MinelsCreator.genMinels(partie,manager);
|
||||
|
||||
|
||||
this.setContentPane(genGamePane(partie,manager,minelsSup,minels));
|
||||
this.getContentPane().repaint(20);
|
||||
}catch(Exception ex) {
|
||||
ex.printStackTrace();
|
||||
JOptionPane.showMessageDialog(this, ex.getLocalizedMessage(), "Impossible de lire le fichier", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
this.setEnabled(true);
|
||||
});
|
||||
|
||||
semiPan.add(loadFile);
|
||||
globalPanel.add(semiPan);
|
||||
return globalPanel;
|
||||
}
|
||||
|
||||
public JPanel genGamePane(Partie partie,GameManager manager,Map<String,List<Minel>> minelsSup,Map<Personnage,List<Minel>> minels) {
|
||||
|
||||
JPanel globalPan = new JPanel(new BorderLayout());
|
||||
GlobalUIManager guim = new GlobalUIManager(globalPan);
|
||||
|
||||
//Center Panel
|
||||
CardLayout centerLayout = new CardLayout();
|
||||
JPanel centerPan = new JPanel(centerLayout);
|
||||
|
||||
for(String s : minelsSup.keySet()) {
|
||||
JPanel centralLocalBpanPan = new JPanel(new GridLayout(2,(minelsSup.get(s).size()+1)/2));
|
||||
minelsSup.get(s).stream().map(m -> m.genContentPane(guim)).forEach(mpan -> centralLocalBpanPan.add(mpan));
|
||||
JScrollPane centralLocalPan = new JScrollPane(centralLocalBpanPan);
|
||||
centerPan.add(centralLocalPan, s);
|
||||
}
|
||||
for(Personnage p : minels.keySet()) {
|
||||
JPanel centralLocalBpanPan = new JPanel(new GridLayout(2, (minels.get(p).size()+1)/2));
|
||||
minels.get(p).stream().map(m -> m.genContentPane(guim)).forEach(mpan -> centralLocalBpanPan.add(mpan));
|
||||
JScrollPane centralLocalPan = new JScrollPane(centralLocalBpanPan);
|
||||
centerPan.add(centralLocalPan, personnageIdentifier(p));
|
||||
}
|
||||
|
||||
|
||||
//Left Panel
|
||||
JPanel leftPan = new JPanel(new GridLayout(minels.size() + minelsSup.size(), 1));
|
||||
|
||||
for(String s : minelsSup.keySet()) {
|
||||
JButton localButton = new JButton(s);
|
||||
localButton.addActionListener(e -> centerLayout.show(centerPan, s));
|
||||
leftPan.add(localButton);
|
||||
}
|
||||
for(Personnage p : minels.keySet()) {
|
||||
JButton localButton = new JButton(p.getNom());
|
||||
localButton.addActionListener(e -> centerLayout.show(centerPan, personnageIdentifier(p)));
|
||||
leftPan.add(localButton);
|
||||
}
|
||||
|
||||
globalPan.add(leftPan, BorderLayout.WEST);
|
||||
globalPan.add(centerPan, BorderLayout.CENTER);
|
||||
|
||||
return globalPan;
|
||||
}
|
||||
|
||||
|
||||
public String personnageIdentifier(Personnage personnage) {
|
||||
return String.format("%08X",System.identityHashCode(personnage))+personnage.getNom();
|
||||
}
|
||||
|
||||
}
|
||||
9
src/main/java/com/bernard/murder/view/SettingsFrame.java
Executable file
9
src/main/java/com/bernard/murder/view/SettingsFrame.java
Executable file
@ -0,0 +1,9 @@
|
||||
package com.bernard.murder.view;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
public class SettingsFrame extends JFrame{
|
||||
|
||||
private static final long serialVersionUID = 7253551627244719823L;
|
||||
|
||||
}
|
||||
113
src/main/java/com/bernard/murder/view/minel/ActionsMinel.java
Executable file
113
src/main/java/com/bernard/murder/view/minel/ActionsMinel.java
Executable file
@ -0,0 +1,113 @@
|
||||
package com.bernard.murder.view.minel;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.Timer;
|
||||
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.bernard.murder.ParseUtils;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.model.Action;
|
||||
import com.bernard.murder.model.Personnage;
|
||||
|
||||
public class ActionsMinel extends Minel {
|
||||
|
||||
public static final String availableText = "Disponible";
|
||||
public static final String waitingTimeText = "Reste %s, reset à %s";
|
||||
|
||||
Personnage personnage;
|
||||
|
||||
Collection<Action> updatingActions;
|
||||
Map<Action,JLabel> actionStatusTexts = new HashMap<>();
|
||||
Map<Action,JButton> actionButtons = new HashMap<>();
|
||||
|
||||
public ActionsMinel(GameManager manager, Personnage perso) {
|
||||
super(manager);
|
||||
this.personnage = perso;
|
||||
updatingActions = new HashSet<Action>();
|
||||
updatingActions.addAll(perso.getActions());
|
||||
}
|
||||
|
||||
public ActionsMinel(GameManager manager, YamlMapping ym) {
|
||||
this(manager,manager.getPersoByName(ym.string("personnage")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel genContentPane() {
|
||||
JPanel globalPan = new JPanel(new BorderLayout());
|
||||
|
||||
JPanel actionsListPan = new JPanel();
|
||||
actionsListPan.setLayout(new BoxLayout(actionsListPan, BoxLayout.PAGE_AXIS));
|
||||
for(Action a : personnage.getActions()) {
|
||||
JPanel actionControlPanel = new JPanel(new BorderLayout());
|
||||
JLabel actionName = new JLabel(a.getName());
|
||||
JButton actionButton = new JButton("GO");
|
||||
JLabel actionStatusText = new JLabel(availableText);
|
||||
|
||||
actionButton.addActionListener(e->launchAction(a));
|
||||
actionButtons.put(a, actionButton);
|
||||
actionStatusTexts.put(a, actionStatusText);
|
||||
|
||||
actionControlPanel.add(actionButton, BorderLayout.EAST);
|
||||
actionControlPanel.add(actionName, BorderLayout.NORTH);
|
||||
actionControlPanel.add(actionStatusText, BorderLayout.SOUTH);
|
||||
|
||||
actionsListPan.add(actionControlPanel);
|
||||
actionsListPan.add(new JSeparator());
|
||||
|
||||
Timer timer = new Timer(100, e->updateTexts());
|
||||
timer.start();
|
||||
}
|
||||
JScrollPane globalScroll = new JScrollPane(actionsListPan);
|
||||
JLabel titleLabel = new JLabel("Actions de "+personnage.getNom());
|
||||
globalPan.add(titleLabel,BorderLayout.NORTH);
|
||||
globalPan.add(globalScroll,BorderLayout.CENTER);
|
||||
|
||||
updateTexts();
|
||||
|
||||
return globalPan;
|
||||
}
|
||||
|
||||
private void launchAction(Action a) {
|
||||
if(!a.canBeLaunched())return;
|
||||
a.launch();
|
||||
actionButtons.get(a).setEnabled(false);
|
||||
updateText(a);
|
||||
updatingActions.add(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlMappingBuilder saveToYaml() {
|
||||
return Yaml.createYamlMappingBuilder().add("personnage", personnage.getNom());
|
||||
}
|
||||
|
||||
public void updateTexts() {
|
||||
updatingActions.stream().filter(Action::hasFinished).collect(Collectors.toSet())
|
||||
.stream().forEach(a -> {
|
||||
actionStatusTexts.get(a).setText(availableText);
|
||||
actionButtons.get(a).setEnabled(true);
|
||||
updatingActions.remove(a);
|
||||
});
|
||||
updatingActions.forEach(this::updateText);
|
||||
}
|
||||
|
||||
public void updateText(Action a) {
|
||||
actionStatusTexts.get(a).setText(String.format(waitingTimeText, ParseUtils.dumpTimeLength(a.timeToWaitLeft()), ParseUtils.dumpHourDate(a.dateReset())));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -1,16 +1,23 @@
|
||||
package com.bernard.murder.view.minel;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.ListCellRenderer;
|
||||
|
||||
import com.bernard.murder.ParseUtils;
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.model.Inventaire;
|
||||
import com.bernard.murder.model.Objet;
|
||||
import com.bernard.murder.view.GlobalUIManager;
|
||||
import com.bernard.murder.view.minel.objetDnD.ObjetDropTarget;
|
||||
import com.bernard.murder.view.minel.objetDnD.ObjetTransferHandler;
|
||||
|
||||
public class InventaireMinel extends Minel {
|
||||
|
||||
@ -19,27 +26,40 @@ public class InventaireMinel extends Minel {
|
||||
this.inv = inv;
|
||||
}
|
||||
|
||||
public InventaireMinel(GameManager gm, YamlMapping ym) {
|
||||
this(gm,gm.getInventoryByName(ym.string("inventaire")));
|
||||
}
|
||||
|
||||
JList<Objet> objets;
|
||||
Inventaire inv;
|
||||
|
||||
@Override
|
||||
public JPanel genContentPane(GlobalUIManager guim) {
|
||||
public JPanel genContentPane() {
|
||||
JPanel globalpan = new JPanel(new BorderLayout());
|
||||
|
||||
globalpan.setBackground(ParseUtils.randColor());
|
||||
|
||||
if(inv.getInventoryName()!=null) {
|
||||
JLabel invName = new JLabel(inv.getInventoryName());
|
||||
globalpan.add(invName, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
JPanel inventaire = new JPanel();
|
||||
inventaire.setBackground(ParseUtils.randColor());
|
||||
|
||||
JButton voler = new JButton("RandomItem");
|
||||
voler.addActionListener(e -> {
|
||||
objets.setSelectedIndex((int) (Math.random() * objets.getModel().getSize()));
|
||||
});
|
||||
|
||||
// TODO dragndrop multiple items
|
||||
objets = new JList<Objet>();
|
||||
objets.addMouseListener(guim);
|
||||
objets.setCellRenderer(new ObjetListCellRenderer());
|
||||
objets.setDragEnabled(true);
|
||||
objets.setTransferHandler(new ObjetTransferHandler());
|
||||
updateObjets();
|
||||
final ObjetDropTarget odt = new ObjetDropTarget(manager, inv, this::updateObjets);
|
||||
objets.setDropTarget(odt);
|
||||
globalpan.setDropTarget(odt);
|
||||
|
||||
manager.addInventoryUpdateListener(inv, this::updateObjets);
|
||||
|
||||
inventaire.add(objets);
|
||||
|
||||
@ -50,9 +70,40 @@ public class InventaireMinel extends Minel {
|
||||
}
|
||||
|
||||
private void updateObjets() {
|
||||
System.out.print("Updating "+inv+" with");
|
||||
manager.dumpCurrentState();
|
||||
Objet[] objz = new Objet[inv.getObjects().size()];
|
||||
objz = inv.getObjects().toArray(objz);
|
||||
objets.setListData(objz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlMappingBuilder saveToYaml() {
|
||||
return Yaml.createYamlMappingBuilder().add("inventaire", inv.getInventoryName());
|
||||
}
|
||||
|
||||
public static class ObjetListCellRenderer extends JLabel implements ListCellRenderer<Objet> {
|
||||
|
||||
private static final long serialVersionUID = -7176962839330435585L;
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<? extends Objet> list, Objet objet, int index,
|
||||
boolean isSelected, boolean cellHasFocus) {
|
||||
|
||||
setText(objet.getNom());
|
||||
|
||||
if (isSelected) {
|
||||
setFont(getFont().deriveFont(Font.BOLD));
|
||||
setBackground(list.getSelectionBackground());
|
||||
setForeground(list.getSelectionForeground());
|
||||
} else {
|
||||
setFont(getFont().deriveFont(Font.PLAIN));
|
||||
setBackground(list.getBackground());
|
||||
setForeground(list.getForeground());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,8 +2,9 @@ package com.bernard.murder.view.minel;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.view.GlobalUIManager;
|
||||
|
||||
public abstract class Minel{
|
||||
|
||||
@ -15,7 +16,12 @@ public abstract class Minel{
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public abstract JPanel genContentPane(GlobalUIManager guim);
|
||||
public Minel(GameManager manager, YamlMapping node) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public abstract JPanel genContentPane();
|
||||
|
||||
public abstract YamlMappingBuilder saveToYaml();
|
||||
|
||||
}
|
||||
|
||||
143
src/main/java/com/bernard/murder/view/minel/ObjetSearchMinel.java
Executable file
143
src/main/java/com/bernard/murder/view/minel/ObjetSearchMinel.java
Executable file
@ -0,0 +1,143 @@
|
||||
package com.bernard.murder.view.minel;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
|
||||
import com.amihaiemil.eoyaml.Scalar;
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.amihaiemil.eoyaml.YamlNode;
|
||||
import com.bernard.murder.ParseUtils;
|
||||
import com.bernard.murder.YamlUtils;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.model.Inventaire;
|
||||
import com.bernard.murder.model.Objet;
|
||||
import com.bernard.murder.util.view.SimpleDocumentListener;
|
||||
|
||||
public class ObjetSearchMinel extends Minel {
|
||||
|
||||
Set<Inventaire> overwatchedInventories;
|
||||
|
||||
Map<Objet,Inventaire> objets;
|
||||
|
||||
public ObjetSearchMinel(GameManager manager, Set<Inventaire> toOverwatch) {
|
||||
super(manager);
|
||||
overwatchedInventories = toOverwatch;
|
||||
objets = new HashMap<Objet, Inventaire>();
|
||||
for(Inventaire i : overwatchedInventories) {
|
||||
i.getObjects().stream().forEach(o -> objets.put(o, i));
|
||||
manager.addInventoryUpdateListener(i, ()->i.getObjects().stream().forEach(o -> objets.put(o, i)));
|
||||
}
|
||||
}
|
||||
|
||||
public ObjetSearchMinel(GameManager gm,YamlMapping ym) {
|
||||
this(gm,
|
||||
gm.getEveryInventaireByName(
|
||||
ym.yamlSequence("overwatchedInventories")
|
||||
.values()
|
||||
.stream()
|
||||
.map(YamlNode::asScalar)
|
||||
.map(Scalar::value)
|
||||
.collect(Collectors.toSet())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel genContentPane() {
|
||||
|
||||
JPanel globalPan = new JPanel(new BorderLayout());
|
||||
|
||||
JTextField searchField = new JTextField();
|
||||
searchField.setToolTipText("Objet à chercher");
|
||||
|
||||
JList<InventorizedObject> searchResults = new JList<>();
|
||||
|
||||
|
||||
|
||||
searchField.getDocument().addDocumentListener(new SimpleDocumentListener() {
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
System.out.println("Updated to "+e.getDocument().toString());
|
||||
String searchText = searchField.getText();
|
||||
if(searchText.isBlank()) {
|
||||
searchResults.setListData(new InventorizedObject[0]);
|
||||
return;
|
||||
}
|
||||
Set<InventorizedObject> startMatch = new HashSet<>();
|
||||
Set<InventorizedObject> anyMatch = new HashSet<>();
|
||||
Set<InventorizedObject> subwordMatch = new HashSet<>();
|
||||
|
||||
for(Objet o : objets.keySet()) {
|
||||
System.out.println(o+"->"+searchText);
|
||||
if(o.getNom().startsWith(searchText))
|
||||
startMatch.add(new InventorizedObject(o,objets.get(o)));
|
||||
else if(o.getNom().contains(searchText))
|
||||
anyMatch.add(new InventorizedObject(o,objets.get(o)));
|
||||
else if(ParseUtils.isSubWord(o.getNom(), searchText))
|
||||
subwordMatch.add(new InventorizedObject(o,objets.get(o)));
|
||||
}
|
||||
InventorizedObject[] results =
|
||||
Stream.concat(Stream.concat(
|
||||
startMatch.stream().sorted((s,v) -> s.objet.getNom().compareToIgnoreCase(v.objet.getNom())),
|
||||
anyMatch.stream().sorted((s,v) -> s.objet.getNom().compareToIgnoreCase(v.objet.getNom()))),
|
||||
subwordMatch.stream().sorted((s,v) -> s.objet.getNom().compareToIgnoreCase(v.objet.getNom())))
|
||||
.toArray(InventorizedObject[]::new);
|
||||
|
||||
searchResults.setListData(results);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
globalPan.add(searchField, BorderLayout.NORTH);
|
||||
globalPan.add(searchResults,BorderLayout.CENTER);
|
||||
|
||||
return globalPan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlMappingBuilder saveToYaml() {
|
||||
return Yaml.createYamlMappingBuilder().add("overwatchedInventories",
|
||||
YamlUtils.listToSeqString(overwatchedInventories.stream()
|
||||
.map(Inventaire::getInventoryName)
|
||||
.collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
public static class InventorizedObject{
|
||||
Objet objet;
|
||||
Inventaire inventaire;
|
||||
|
||||
|
||||
|
||||
public InventorizedObject(Objet objet, Inventaire inventaire) {
|
||||
this.objet = objet;
|
||||
this.inventaire = inventaire;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void changeInventory(Inventaire inventaire) {
|
||||
this.inventaire = inventaire;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return objet.getNom()+" ("+inventaire.getInventoryName()+")";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
39
src/main/java/com/bernard/murder/view/minel/ServeurMinel.java
Executable file
39
src/main/java/com/bernard/murder/view/minel/ServeurMinel.java
Executable file
@ -0,0 +1,39 @@
|
||||
package com.bernard.murder.view.minel;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.bernard.murder.audio.AudioServer;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
|
||||
public class ServeurMinel extends Minel {
|
||||
|
||||
AudioServer serveur;
|
||||
|
||||
public ServeurMinel(GameManager manager) {
|
||||
super(manager);
|
||||
serveur = new AudioServer();
|
||||
}
|
||||
|
||||
public ServeurMinel(GameManager manager,YamlMapping ym) {
|
||||
super(manager);
|
||||
serveur = new AudioServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel genContentPane() {
|
||||
JPanel pan = new JPanel();
|
||||
JLabel label = new JLabel("Rien pour l'instant");
|
||||
pan.add(label);
|
||||
return pan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlMappingBuilder saveToYaml() {
|
||||
return Yaml.createYamlMappingBuilder();
|
||||
}
|
||||
|
||||
}
|
||||
29
src/main/java/com/bernard/murder/view/minel/StatusMinel.java
Executable file
29
src/main/java/com/bernard/murder/view/minel/StatusMinel.java
Executable file
@ -0,0 +1,29 @@
|
||||
package com.bernard.murder.view.minel;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.model.Personnage;
|
||||
|
||||
public class StatusMinel extends Minel {
|
||||
|
||||
public StatusMinel(GameManager manager, Personnage personnage) {
|
||||
super(manager);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel genContentPane() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlMappingBuilder saveToYaml() {
|
||||
//TODO auto-generated thingy
|
||||
return Yaml.createYamlMappingBuilder();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,37 +1,50 @@
|
||||
package com.bernard.murder.view.minel;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import com.bernard.murder.ParseUtils;
|
||||
import com.amihaiemil.eoyaml.Yaml;
|
||||
import com.amihaiemil.eoyaml.YamlMapping;
|
||||
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.view.GlobalUIManager;
|
||||
|
||||
public class TextPanMinel extends Minel {
|
||||
|
||||
String initTexte = "";
|
||||
JTextArea textArea;
|
||||
|
||||
public TextPanMinel(GameManager manager) {
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel genContentPane(GlobalUIManager guim) {
|
||||
JPanel globalPan = new JPanel(new BorderLayout());
|
||||
globalPan.setBackground(ParseUtils.randColor());
|
||||
JTextArea textArea = new JTextArea();
|
||||
textArea.setBorder(new EmptyBorder(23,23,23,23));
|
||||
public TextPanMinel(GameManager gm, YamlMapping ym) {
|
||||
super(gm);
|
||||
initTexte = ym.string("texte");
|
||||
}
|
||||
|
||||
Color col = ParseUtils.randColor();
|
||||
textArea.setBackground(col);
|
||||
textArea.setForeground(ParseUtils.getContrastColor(col));
|
||||
@Override
|
||||
public JPanel genContentPane() {
|
||||
JPanel globalPan = new JPanel(new BorderLayout());
|
||||
//globalPan.setBackground(ParseUtils.randColor());
|
||||
textArea = new JTextArea();
|
||||
textArea.setBorder(new EmptyBorder(23,23,23,23));
|
||||
textArea.setText(initTexte);
|
||||
|
||||
//Color col = ParseUtils.randColor();
|
||||
//textArea.setBackground(col);
|
||||
//textArea.setForeground(ParseUtils.getContrastColor(col));
|
||||
|
||||
globalPan.add(new JScrollPane(textArea),BorderLayout.CENTER);
|
||||
return globalPan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlMappingBuilder saveToYaml() {
|
||||
return Yaml.createYamlMappingBuilder().add("texte", textArea!=null?textArea.getText():initTexte);
|
||||
}
|
||||
|
||||
}
|
||||
17
src/main/java/com/bernard/murder/view/minel/objetDnD/NotADropTarget.java
Executable file
17
src/main/java/com/bernard/murder/view/minel/objetDnD/NotADropTarget.java
Executable file
@ -0,0 +1,17 @@
|
||||
package com.bernard.murder.view.minel.objetDnD;
|
||||
|
||||
import java.awt.dnd.DropTarget;
|
||||
import java.awt.dnd.DropTargetDropEvent;
|
||||
|
||||
public class NotADropTarget extends DropTarget {
|
||||
|
||||
private static final long serialVersionUID = -2448755310779755579L;
|
||||
|
||||
public NotADropTarget() {}
|
||||
|
||||
@Override
|
||||
public synchronized void drop(DropTargetDropEvent dtde) {
|
||||
dtde.rejectDrop();
|
||||
}
|
||||
|
||||
}
|
||||
45
src/main/java/com/bernard/murder/view/minel/objetDnD/ObjetDropTarget.java
Executable file
45
src/main/java/com/bernard/murder/view/minel/objetDnD/ObjetDropTarget.java
Executable file
@ -0,0 +1,45 @@
|
||||
package com.bernard.murder.view.minel.objetDnD;
|
||||
|
||||
import java.awt.dnd.DnDConstants;
|
||||
import java.awt.dnd.DropTarget;
|
||||
import java.awt.dnd.DropTargetDropEvent;
|
||||
import java.util.List;
|
||||
|
||||
import com.bernard.murder.game.GameManager;
|
||||
import com.bernard.murder.model.Inventaire;
|
||||
import com.bernard.murder.model.Objet;
|
||||
|
||||
public class ObjetDropTarget extends DropTarget {
|
||||
|
||||
private static final long serialVersionUID = 4114342978115089000L;
|
||||
|
||||
GameManager manager;
|
||||
Inventaire toInv;
|
||||
Runnable[] toUpdate;
|
||||
|
||||
public ObjetDropTarget(GameManager manager,Inventaire toInventaire,Runnable... update) {
|
||||
this.manager = manager;
|
||||
this.toInv = toInventaire;
|
||||
this.toUpdate = update;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void drop(DropTargetDropEvent e) {
|
||||
try {
|
||||
e.acceptDrop(DnDConstants.ACTION_COPY);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Objet> droppedObjets = (List<Objet>) e.getTransferable().getTransferData(ObjetTransferable.objetDataFlavor);
|
||||
|
||||
for(Objet o : droppedObjets) {
|
||||
manager.moveObjet(o,toInv);
|
||||
}
|
||||
for(Runnable runnable : toUpdate)
|
||||
runnable.run();
|
||||
manager.dumpCurrentState();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.bernard.murder.view.minel.objetDnD;
|
||||
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.TransferHandler;
|
||||
|
||||
import com.bernard.murder.model.Objet;
|
||||
|
||||
public class ObjetTransferHandler extends TransferHandler {
|
||||
|
||||
private static final long serialVersionUID = -8817518488023807932L;
|
||||
|
||||
@Override
|
||||
public int getSourceActions(JComponent c) {
|
||||
return TransferHandler.MOVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Transferable createTransferable(JComponent c) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
JList<Objet> liste = (JList<Objet>) c;
|
||||
|
||||
List<Objet> selected = liste.getSelectedValuesList();
|
||||
|
||||
ObjetTransferable transferable = new ObjetTransferable(selected);
|
||||
|
||||
return transferable;
|
||||
}
|
||||
|
||||
}
|
||||
45
src/main/java/com/bernard/murder/view/minel/objetDnD/ObjetTransferable.java
Executable file
45
src/main/java/com/bernard/murder/view/minel/objetDnD/ObjetTransferable.java
Executable file
@ -0,0 +1,45 @@
|
||||
package com.bernard.murder.view.minel.objetDnD;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.bernard.murder.model.Objet;
|
||||
|
||||
public class ObjetTransferable implements Transferable{
|
||||
|
||||
private final List<Objet> objets;
|
||||
private final DataFlavor[] flavors;
|
||||
public static final DataFlavor objetDataFlavor = new DataFlavor(Objet.class, "fichierMurder");
|
||||
|
||||
public ObjetTransferable(Collection<Objet> objets) {
|
||||
this.objets = Collections.unmodifiableList(
|
||||
new ArrayList<Objet>(objets));
|
||||
this.flavors = new DataFlavor[] { ObjetTransferable.objetDataFlavor };
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
return flavors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
return Arrays.stream(flavors).anyMatch(f -> f == flavor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
|
||||
if(isDataFlavorSupported(flavor))
|
||||
return objets;
|
||||
else
|
||||
throw new UnsupportedFlavorException(flavor);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user