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
|
.classpath
|
||||||
.settings
|
.settings
|
||||||
.project
|
.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
|
* User Manual available at https://docs.gradle.org/6.0/userguide/java_library_plugin.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
plugins {
|
apply plugin: 'java'
|
||||||
// Apply the java-library plugin to add support for Java Library
|
apply plugin: 'eclipse'
|
||||||
id 'java-library'
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// Use jcenter for resolving dependencies.
|
// Use jcenter for resolving dependencies.
|
||||||
@ -18,16 +16,20 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
manifest {
|
||||||
|
attributes(
|
||||||
|
'Main-Class': 'com.bernard.murder.view.LauncherFrame'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
from {
|
||||||
|
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
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.awt.Color;
|
||||||
import java.io.IOException;
|
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.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Spliterator;
|
import java.util.Spliterator;
|
||||||
@ -15,11 +19,14 @@ import java.util.stream.StreamSupport;
|
|||||||
|
|
||||||
import com.amihaiemil.eoyaml.Yaml;
|
import com.amihaiemil.eoyaml.Yaml;
|
||||||
import com.amihaiemil.eoyaml.YamlMapping;
|
import com.amihaiemil.eoyaml.YamlMapping;
|
||||||
|
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||||
import com.amihaiemil.eoyaml.YamlNode;
|
import com.amihaiemil.eoyaml.YamlNode;
|
||||||
import com.amihaiemil.eoyaml.YamlSequence;
|
import com.amihaiemil.eoyaml.YamlSequence;
|
||||||
|
import com.amihaiemil.eoyaml.YamlSequenceBuilder;
|
||||||
|
|
||||||
public class ParseUtils {
|
public class ParseUtils {
|
||||||
|
|
||||||
|
|
||||||
static Pattern timeLengthPattern = Pattern.compile("^(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s?)?$");
|
static Pattern timeLengthPattern = Pattern.compile("^(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s?)?$");
|
||||||
|
|
||||||
public static long parseTimeLength(String tl) {
|
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 h = mtch.group(2)==null?0:Integer.parseInt(mtch.group(2));
|
||||||
int m = mtch.group(4)==null?0:Integer.parseInt(mtch.group(4));
|
int m = mtch.group(4)==null?0:Integer.parseInt(mtch.group(4));
|
||||||
int s = mtch.group(6)==null?0:Integer.parseInt(mtch.group(6));
|
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){
|
public static <T> Set<T> union(Collection<T> c1, Collection<T> c2){
|
||||||
Set<T> out = c1.stream().collect(Collectors.toSet());
|
Set<T> out = c1.stream().collect(Collectors.toSet());
|
||||||
out.addAll(c2);
|
out.addAll(c2);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<String> mappingKeys(YamlMapping mapping) throws IOException{
|
public static boolean isSubWord(String word, String subword) {
|
||||||
return mapping.keys().stream().map(n ->{
|
int i=0,j=0;
|
||||||
try {
|
while(true) {
|
||||||
return Yaml.createYamlInput(n.toString()).readYamlSequence().string(0);
|
if(i==subword.length())return true;
|
||||||
} catch (IOException e) {
|
if(j==word.length())return false;
|
||||||
e.printStackTrace();
|
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){
|
public static boolean and(boolean[] bb) {
|
||||||
try {
|
for(boolean b : bb)
|
||||||
return Yaml.createYamlInput(n.toString()).readYamlSequence().string(0);
|
if(!b)return false;
|
||||||
} catch (IOException e) {
|
return true;
|
||||||
e.printStackTrace();
|
}
|
||||||
}
|
|
||||||
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){
|
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() {
|
public static Color randColor() {
|
||||||
return Color.getHSBColor((float) Math.random(), 1.0f, 1.0f);
|
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) {
|
public static Color getContrastColor(Color color) {
|
||||||
double y = (299 * color.getRed() + 587 * color.getGreen() + 114 * color.getBlue()) / 1000;
|
double y = (299 * color.getRed() + 587 * color.getGreen() + 114 * color.getBlue()) / 1000;
|
||||||
return y >= 128 ? Color.black : Color.white;
|
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;
|
package com.bernard.murder.game;
|
||||||
|
|
||||||
import static com.bernard.murder.ParseUtils.mappingKeys;
|
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.parseTimeLength;
|
||||||
import static com.bernard.murder.ParseUtils.sequenceStream;
|
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.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Spliterator;
|
import java.util.Spliterator;
|
||||||
@ -16,10 +24,13 @@ import java.util.stream.Collectors;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import com.amihaiemil.eoyaml.Node;
|
||||||
import com.amihaiemil.eoyaml.Yaml;
|
import com.amihaiemil.eoyaml.Yaml;
|
||||||
import com.amihaiemil.eoyaml.YamlInput;
|
import com.amihaiemil.eoyaml.YamlInput;
|
||||||
import com.amihaiemil.eoyaml.YamlMapping;
|
import com.amihaiemil.eoyaml.YamlMapping;
|
||||||
|
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||||
import com.amihaiemil.eoyaml.YamlNode;
|
import com.amihaiemil.eoyaml.YamlNode;
|
||||||
|
import com.amihaiemil.eoyaml.YamlPrinter;
|
||||||
import com.amihaiemil.eoyaml.YamlSequence;
|
import com.amihaiemil.eoyaml.YamlSequence;
|
||||||
import com.bernard.murder.ParseUtils;
|
import com.bernard.murder.ParseUtils;
|
||||||
import com.bernard.murder.model.Action;
|
import com.bernard.murder.model.Action;
|
||||||
@ -31,89 +42,89 @@ import com.bernard.murder.model.Status;
|
|||||||
|
|
||||||
public class GameCreator {
|
public class GameCreator {
|
||||||
|
|
||||||
|
|
||||||
public static Partie genFromFile(File toread) throws IOException{
|
public static Partie genFromFile(File toread) throws IOException{
|
||||||
|
|
||||||
YamlInput input = Yaml.createYamlInput(toread);
|
YamlInput input = Yaml.createYamlInput(toread);
|
||||||
YamlMapping globalMap = input.readYamlMapping();
|
YamlMapping globalMap = input.readYamlMapping();
|
||||||
|
|
||||||
YamlMapping yjoueurs = globalMap.yamlMapping("joueurs");
|
YamlMapping yjoueurs = getMapping(globalMap.value("joueurs"));
|
||||||
System.out.println(yjoueurs);
|
|
||||||
|
|
||||||
// Pour pouvoir créer les objets et les espaces personnels
|
// Pour pouvoir créer les objets et les espaces personnels
|
||||||
Set<String> playerNames = mappingKeys(yjoueurs).stream().map(n -> n.toString()).collect(Collectors.toSet());
|
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()
|
Set<Action> actions = yactions.keys()
|
||||||
.stream()
|
.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());
|
.collect(Collectors.toSet());
|
||||||
Map<String,Set<Action>> persActions = playerNames.stream()
|
Map<String,Set<Action>> persActions = playerNames.stream()
|
||||||
.collect(Collectors.toMap(Function.identity(), s -> actions.stream().map(Action::clone).collect(Collectors.toSet())));
|
.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)
|
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());
|
.collect(Collectors.toSet());
|
||||||
Map<String,Set<Objet>> persObjets = playerNames.stream()
|
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())));
|
.collect(Collectors.toMap(Function.identity(),p -> objets.stream().map(o ->new Objet(String.format(o,p))).collect(Collectors.toSet())));
|
||||||
|
|
||||||
YamlSequence ystatus = globalMap.yamlSequence("status");
|
YamlSequence ystatus = getSequence(globalMap.value("status"));
|
||||||
Set<Status> status = sequenceStream(ystatus).map(n -> new Status(node(n))).collect(Collectors.toSet());
|
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(
|
Map<String, Map<Objet, Integer>> objetsDansEspaces = yespaces.keys().stream().collect(Collectors.toMap(
|
||||||
n -> node(n),
|
n -> n.asScalar().value(),
|
||||||
n-> parseHiddenObjects(yespaces.yamlSequence(n))
|
n-> parseHiddenObjects(getSequence(yespaces.value(n)))
|
||||||
));
|
));
|
||||||
Set<Piece> espaceObjets = yespaces.keys().stream()
|
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());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
YamlMapping yespacesPersos = globalMap.yamlMapping("espacesPersos");
|
YamlMapping yespacesPersos = getMapping(globalMap.value("espacesPersos"));
|
||||||
|
|
||||||
Map<String,Set<Piece>> persespacesPersos = playerNames.stream().collect(Collectors.toMap(
|
Map<String,Set<Piece>> persespacesPersos = playerNames.stream().collect(Collectors.toMap(
|
||||||
Function.identity(),
|
Function.identity(),
|
||||||
p -> yespacesPersos.keys().stream()
|
p -> yespacesPersos.keys().stream()
|
||||||
.map(e -> new Piece(
|
.map(e -> new Piece(
|
||||||
String.format(node(e), p),
|
String.format(e.asScalar().value(), p),
|
||||||
parseHiddenObjects(yespacesPersos.yamlSequence(e),p)
|
parseHiddenObjects(getSequence(yespacesPersos.value(e)),p)
|
||||||
))
|
))
|
||||||
.collect(Collectors.toSet())
|
.collect(Collectors.toSet())
|
||||||
));
|
));
|
||||||
|
|
||||||
//Per perso settings
|
//Per perso settings
|
||||||
for(YamlNode pn : yjoueurs.keys()) {
|
for(YamlNode pn : yjoueurs.keys()) {
|
||||||
String pname = node(pn);
|
String pname = pn.asScalar().value();
|
||||||
System.out.println(pn);
|
|
||||||
System.out.println(yjoueurs.yamlMapping(pn));
|
|
||||||
persActions.get(pname).addAll(
|
persActions.get(pname).addAll(
|
||||||
yjoueurs.yamlMapping(pn).yamlMapping("actions").keys()
|
getMapping(getMapping(yjoueurs.value(pn)).value("actions")).keys()
|
||||||
.stream()
|
.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())
|
.collect(Collectors.toSet())
|
||||||
);
|
);
|
||||||
persObjets.get(pname).addAll(
|
persObjets.get(pname).addAll(
|
||||||
StreamSupport.stream(Spliterators.spliteratorUnknownSize(yjoueurs.yamlMapping(pn).yamlSequence("inventaire").iterator(),Spliterator.ORDERED),false)
|
StreamSupport.stream(Spliterators.spliteratorUnknownSize(getSequence(getMapping(yjoueurs.value(pn)).value("inventaire")).iterator(),Spliterator.ORDERED),false)
|
||||||
.map(n ->ParseUtils.node(n))
|
.map(n ->n.asScalar().value())
|
||||||
.map(o ->new Objet(o))
|
.map(o ->new Objet(o))
|
||||||
.collect(Collectors.toSet())
|
.collect(Collectors.toSet())
|
||||||
);
|
);
|
||||||
if(yjoueurs.yamlMapping(pn).yamlMapping("espacePerso")!= null)
|
if(isMapping(getMapping(yjoueurs.value(pn)).value("espacePerso")))
|
||||||
// Plusieurs espaces
|
// Plusieurs espaces
|
||||||
yjoueurs.yamlMapping(pn).yamlMapping("espacePerso").keys().forEach(n ->
|
getMapping(getMapping(yjoueurs.value(pn)).value("espacePerso")).keys().forEach(n ->
|
||||||
persespacesPersos.get(pname)
|
persespacesPersos.get(pname)
|
||||||
.stream()
|
.stream()
|
||||||
.filter(p -> p.getNom().contentEquals(node(n)))
|
.filter(p -> p.getNom().contentEquals(n.asScalar().value()))
|
||||||
.findAny()
|
.findAny()
|
||||||
.orElseGet(() -> new Piece(node(n)))
|
.orElseGet(() -> new Piece(n.asScalar().value()))
|
||||||
.insertObjects(parseHiddenObjects(yjoueurs.yamlMapping(pn).yamlMapping("espacePerso").yamlSequence(n)))
|
.insertObjects(parseHiddenObjects(getSequence(getMapping(getMapping(yjoueurs.value(pn)).value("espacePerso")).value(n))))
|
||||||
|
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
((persespacesPersos.get(pname).isEmpty())?
|
((persespacesPersos.get(pname).isEmpty())?
|
||||||
Stream.of(new Piece(String.format("Espace de %s",pname))):persespacesPersos.get(pname).stream())
|
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),
|
persActions.get(p),
|
||||||
status.stream().filter(st -> sequenceStream(ystatus)
|
status.stream().filter(st -> sequenceStream(ystatus)
|
||||||
.filter(n -> n instanceof YamlMapping)
|
.filter(n -> n instanceof YamlMapping)
|
||||||
.filter(n -> ((YamlMapping)n).string(st.getName())!=null)
|
.filter(n -> getMapping(n).string(st.getName())!=null)
|
||||||
.filter(n -> ((YamlMapping)((YamlMapping)n).yamlMapping(st.getName())).string("onStart").contentEquals("true"))
|
.filter(n -> getMapping(getMapping(n).value(st.getName())).string("onStart").contentEquals("true"))
|
||||||
.findAny().isPresent())
|
.findAny().isPresent())
|
||||||
.collect(Collectors.toSet()),
|
.collect(Collectors.toSet()),
|
||||||
persespacesPersos.get(p)
|
persespacesPersos.get(p)
|
||||||
@ -138,12 +149,130 @@ public class GameCreator {
|
|||||||
|
|
||||||
private static Map<Objet,Integer> parseHiddenObjects(YamlSequence sequence,Object... nameFormat){
|
private static Map<Objet,Integer> parseHiddenObjects(YamlSequence sequence,Object... nameFormat){
|
||||||
return sequenceStream(sequence).collect(Collectors.toMap(
|
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 -> 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 instanceof YamlMapping)?(((YamlMapping)on).integer(((YamlMapping)on).keys().stream().findAny().get())):-1)
|
on -> ((on.type()==Node.MAPPING)?(on.asMapping().integer(on.asMapping().keys().stream().findAny().get())):-1)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
private static Map<Objet,Integer> parseHiddenObjects(YamlSequence sequence){
|
private static Map<Objet,Integer> parseHiddenObjects(YamlSequence sequence){
|
||||||
return parseHiddenObjects(sequence, new Object[0]);
|
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;
|
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.Partie;
|
||||||
|
import com.bernard.murder.model.Personnage;
|
||||||
|
|
||||||
public class GameManager {
|
public class GameManager {
|
||||||
|
|
||||||
Partie partie;
|
Partie partie;
|
||||||
|
Map<Inventaire,Set<Runnable>> inventoryUpdateListeners;
|
||||||
|
|
||||||
|
long startTime;
|
||||||
|
|
||||||
|
Timer quickSaver;
|
||||||
|
|
||||||
|
Supplier<YamlMapping> minelsQuicksaver;
|
||||||
|
|
||||||
public GameManager(Partie partie) {
|
public GameManager(Partie partie) {
|
||||||
this.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) {
|
public Action(String action, long basetime) {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
this.basetime = basetime;
|
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
|
@Override
|
||||||
public Action clone() {
|
public Action clone() {
|
||||||
Action actions = new Action(action, basetime);
|
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) + "]";
|
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();
|
Set<Objet> getObjects();
|
||||||
|
|
||||||
|
void removeObjet(Objet o);
|
||||||
|
|
||||||
|
void addObjet(Objet o);
|
||||||
|
|
||||||
|
String getInventoryName();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
package com.bernard.murder.model;
|
package com.bernard.murder.model;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class Partie {
|
public class Partie {
|
||||||
|
|
||||||
|
|
||||||
Set<Personnage> personnages;
|
Set<Personnage> personnages;
|
||||||
Set<Status> statuz;
|
Set<Status> statuz;
|
||||||
Set<Piece> piece;
|
Set<Piece> piece;
|
||||||
@ -34,6 +36,35 @@ public class Partie {
|
|||||||
return "Partie [personnages=" + personnages + ", statuz=" + statuz + ", piece=" + piece + "]";
|
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;
|
return inventaire;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<Action> getActions() {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
public Stream<Piece> streamEspacesPersos(){
|
public Stream<Piece> streamEspacesPersos(){
|
||||||
return espacesPersos.stream();
|
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.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class Piece implements Inventaire{
|
public class Piece implements Inventaire{
|
||||||
|
|
||||||
@ -37,6 +39,24 @@ public class Piece implements Inventaire{
|
|||||||
contenu.putAll(objs);
|
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;
|
package com.bernard.murder.view;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -7,35 +9,51 @@ import java.util.Map;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
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.game.GameManager;
|
||||||
import com.bernard.murder.model.Partie;
|
import com.bernard.murder.model.Partie;
|
||||||
import com.bernard.murder.model.Personnage;
|
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.InventaireMinel;
|
||||||
import com.bernard.murder.view.minel.Minel;
|
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;
|
import com.bernard.murder.view.minel.TextPanMinel;
|
||||||
|
|
||||||
public class MinelsCreator {
|
public class MinelsCreator {
|
||||||
|
|
||||||
public static Map<String, List<Minel>> genSupMinels(Partie partie, GameManager manager) {
|
public static Map<String, List<Minel>> genSupMinels(Partie qpartie, GameManager manager) {
|
||||||
Map<String, List<Minel>> outPute = new HashMap<String, List<Minel>>();
|
|
||||||
|
|
||||||
|
Map<String, List<Minel>> outPute = new HashMap<String, List<Minel>>();
|
||||||
List<Minel> generalMinels = new ArrayList<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 TextPanMinel(manager));
|
||||||
|
generalMinels.add(new ObjetSearchMinel(manager, manager.getEveryInventaire()));
|
||||||
|
generalMinels.add(new ServeurMinel(manager));
|
||||||
|
|
||||||
outPute.put("Général", generalMinels);
|
outPute.put("Général", generalMinels);
|
||||||
|
outPute.put("Pièces", piecesMinels);
|
||||||
return outPute;
|
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)));
|
return partie.personnagesStream().collect(Collectors.toMap(Function.identity(), p -> genMinelsForPerso(partie,manager,p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Minel> genMinelsForPerso(Partie partie, GameManager manager, Personnage personnage){
|
private static List<Minel> genMinelsForPerso(Partie partie, GameManager manager, Personnage personnage){
|
||||||
List<Minel> minels = new ArrayList<Minel>();
|
List<Minel> minels = new ArrayList<Minel>();
|
||||||
|
|
||||||
|
minels.add(new ActionsMinel(manager, personnage));
|
||||||
|
|
||||||
minels.add(new InventaireMinel(manager, personnage));
|
minels.add(new InventaireMinel(manager, personnage));
|
||||||
personnage.streamEspacesPersos().map(p -> new InventaireMinel(manager, p)).forEach(m -> minels.add(m));
|
personnage.streamEspacesPersos().map(p -> new InventaireMinel(manager, p)).forEach(m -> minels.add(m));
|
||||||
|
|
||||||
@ -45,5 +63,83 @@ public class MinelsCreator {
|
|||||||
return minels;
|
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;
|
package com.bernard.murder.view.minel;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Font;
|
||||||
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.JPanel;
|
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.game.GameManager;
|
||||||
import com.bernard.murder.model.Inventaire;
|
import com.bernard.murder.model.Inventaire;
|
||||||
import com.bernard.murder.model.Objet;
|
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 {
|
public class InventaireMinel extends Minel {
|
||||||
|
|
||||||
@ -19,27 +26,40 @@ public class InventaireMinel extends Minel {
|
|||||||
this.inv = inv;
|
this.inv = inv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InventaireMinel(GameManager gm, YamlMapping ym) {
|
||||||
|
this(gm,gm.getInventoryByName(ym.string("inventaire")));
|
||||||
|
}
|
||||||
|
|
||||||
JList<Objet> objets;
|
JList<Objet> objets;
|
||||||
Inventaire inv;
|
Inventaire inv;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JPanel genContentPane(GlobalUIManager guim) {
|
public JPanel genContentPane() {
|
||||||
JPanel globalpan = new JPanel(new BorderLayout());
|
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();
|
JPanel inventaire = new JPanel();
|
||||||
inventaire.setBackground(ParseUtils.randColor());
|
|
||||||
|
|
||||||
JButton voler = new JButton("RandomItem");
|
JButton voler = new JButton("RandomItem");
|
||||||
voler.addActionListener(e -> {
|
voler.addActionListener(e -> {
|
||||||
objets.setSelectedIndex((int) (Math.random() * objets.getModel().getSize()));
|
objets.setSelectedIndex((int) (Math.random() * objets.getModel().getSize()));
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO dragndrop multiple items
|
|
||||||
objets = new JList<Objet>();
|
objets = new JList<Objet>();
|
||||||
objets.addMouseListener(guim);
|
objets.setCellRenderer(new ObjetListCellRenderer());
|
||||||
|
objets.setDragEnabled(true);
|
||||||
|
objets.setTransferHandler(new ObjetTransferHandler());
|
||||||
updateObjets();
|
updateObjets();
|
||||||
|
final ObjetDropTarget odt = new ObjetDropTarget(manager, inv, this::updateObjets);
|
||||||
|
objets.setDropTarget(odt);
|
||||||
|
globalpan.setDropTarget(odt);
|
||||||
|
|
||||||
|
manager.addInventoryUpdateListener(inv, this::updateObjets);
|
||||||
|
|
||||||
inventaire.add(objets);
|
inventaire.add(objets);
|
||||||
|
|
||||||
@ -50,9 +70,40 @@ public class InventaireMinel extends Minel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateObjets() {
|
private void updateObjets() {
|
||||||
|
System.out.print("Updating "+inv+" with");
|
||||||
|
manager.dumpCurrentState();
|
||||||
Objet[] objz = new Objet[inv.getObjects().size()];
|
Objet[] objz = new Objet[inv.getObjects().size()];
|
||||||
objz = inv.getObjects().toArray(objz);
|
objz = inv.getObjects().toArray(objz);
|
||||||
objets.setListData(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 javax.swing.JPanel;
|
||||||
|
|
||||||
|
import com.amihaiemil.eoyaml.YamlMapping;
|
||||||
|
import com.amihaiemil.eoyaml.YamlMappingBuilder;
|
||||||
import com.bernard.murder.game.GameManager;
|
import com.bernard.murder.game.GameManager;
|
||||||
import com.bernard.murder.view.GlobalUIManager;
|
|
||||||
|
|
||||||
public abstract class Minel{
|
public abstract class Minel{
|
||||||
|
|
||||||
@ -15,7 +16,12 @@ public abstract class Minel{
|
|||||||
this.manager = manager;
|
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;
|
package com.bernard.murder.view.minel;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
import javax.swing.border.EmptyBorder;
|
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.game.GameManager;
|
||||||
import com.bernard.murder.view.GlobalUIManager;
|
|
||||||
|
|
||||||
public class TextPanMinel extends Minel {
|
public class TextPanMinel extends Minel {
|
||||||
|
|
||||||
|
String initTexte = "";
|
||||||
|
JTextArea textArea;
|
||||||
|
|
||||||
public TextPanMinel(GameManager manager) {
|
public TextPanMinel(GameManager manager) {
|
||||||
super(manager);
|
super(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public TextPanMinel(GameManager gm, YamlMapping ym) {
|
||||||
public JPanel genContentPane(GlobalUIManager guim) {
|
super(gm);
|
||||||
JPanel globalPan = new JPanel(new BorderLayout());
|
initTexte = ym.string("texte");
|
||||||
globalPan.setBackground(ParseUtils.randColor());
|
}
|
||||||
JTextArea textArea = new JTextArea();
|
|
||||||
textArea.setBorder(new EmptyBorder(23,23,23,23));
|
|
||||||
|
|
||||||
Color col = ParseUtils.randColor();
|
@Override
|
||||||
textArea.setBackground(col);
|
public JPanel genContentPane() {
|
||||||
textArea.setForeground(ParseUtils.getContrastColor(col));
|
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);
|
globalPan.add(new JScrollPane(textArea),BorderLayout.CENTER);
|
||||||
return globalPan;
|
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