Initial server->client full flow implementation
This commit is contained in:
parent
e8dc3265d3
commit
9f1e5e9ae6
3
.gitignore
vendored
3
.gitignore
vendored
@ -5,4 +5,5 @@
|
|||||||
/.settings
|
/.settings
|
||||||
/.classpath
|
/.classpath
|
||||||
/.project
|
/.project
|
||||||
/.vscode
|
/.vscode
|
||||||
|
/dependency-reduced-pom.xml
|
||||||
27
pom.xml
27
pom.xml
@ -34,25 +34,22 @@
|
|||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<version>3.0.0</version>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<configuration>
|
<version>3.2.4</version>
|
||||||
<descriptorRefs>
|
|
||||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
|
||||||
</descriptorRefs>
|
|
||||||
<archive>
|
|
||||||
<manifest>
|
|
||||||
<mainClass>electrosphere.main.Main</mainClass>
|
|
||||||
</manifest>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>make-assembly</id>
|
<phase>package</phase>
|
||||||
<phase>package</phase> <!-- bind to the packaging phase -->
|
|
||||||
<goals>
|
<goals>
|
||||||
<goal>single</goal>
|
<goal>shade</goal>
|
||||||
</goals>
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<transformers>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<mainClass>electrosphere.main.Main</mainClass>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|||||||
@ -19,19 +19,25 @@ import electrosphere.main.targets.TargetFile;
|
|||||||
*/
|
*/
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
static String topLevelFolderPathWindows = "C:\\Users\\satellite\\Documents\\Renderer\\src\\main\\java\\electrosphere";
|
public static String topLevelFolderPathWindows = "C:\\Users\\satellite\\Documents\\Renderer";
|
||||||
static String topLevelFolderPathMac = "/Users/satellite/p/Renderer/src/main/java/electrosphere";
|
static String topLevelFolderPathMac = "/Users/satellite/p/Renderer";
|
||||||
|
|
||||||
public static int bTreeIterator = 0;
|
public static int bTreeIterator = 0;
|
||||||
|
|
||||||
|
//hard-coded white list files to always parse
|
||||||
|
static final String[] ALWAYS_PARSED_CLASSES = new String[]{
|
||||||
|
"ClientSynchronizationManager"
|
||||||
|
};
|
||||||
|
|
||||||
//maps the btree annotation "name" to an id
|
//maps the btree annotation "name" to an id
|
||||||
public static Map<String,Integer> bTreeIdMap = new HashMap<String,Integer>();
|
public static Map<String,Integer> bTreeIdMap = new HashMap<String,Integer>();
|
||||||
|
|
||||||
public static void main(String args[]){
|
public static void main(String args[]){
|
||||||
List<TargetFile> targets = getFilesToModify(topLevelFolderPathMac);
|
List<TargetFile> targets = getFilesToModify(topLevelFolderPathWindows + "/src/main/java/electrosphere");
|
||||||
ProjectStructure structure = new ProjectStructure(targets);
|
ProjectStructure structure = new ProjectStructure(targets, new File(topLevelFolderPathWindows));
|
||||||
structure.parseRichStructure();
|
structure.parseRichStructure();
|
||||||
structure.generate();
|
structure.generate();
|
||||||
|
structure.writeFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,7 +45,7 @@ public class Main {
|
|||||||
* @param content
|
* @param content
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static JavaClassSource parseJavaFile(String content){
|
public static JavaClassSource parseJavaFile(String content){
|
||||||
return Roaster.parse(JavaClassSource.class, content);
|
return Roaster.parse(JavaClassSource.class, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +72,10 @@ public class Main {
|
|||||||
String content = "";
|
String content = "";
|
||||||
try {
|
try {
|
||||||
content = Files.readString(currentFile.toPath());
|
content = Files.readString(currentFile.toPath());
|
||||||
if(content.contains("@SynchronizedBehaviorTree")){
|
if(
|
||||||
|
content.contains("@SynchronizedBehaviorTree") ||
|
||||||
|
isHardCodedAlwaysParse(currentFile.getName())
|
||||||
|
){
|
||||||
//parse
|
//parse
|
||||||
JavaClassSource source = parseJavaFile(content);
|
JavaClassSource source = parseJavaFile(content);
|
||||||
rVal.add(new TargetFile(currentFile.getAbsolutePath(), content, currentFile.getName(), source));
|
rVal.add(new TargetFile(currentFile.getAbsolutePath(), content, currentFile.getName(), source));
|
||||||
@ -91,4 +100,18 @@ public class Main {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a given file is a hard coded case to parse
|
||||||
|
* @param fullFileName The full file name
|
||||||
|
* @return true if should parse, false otherwise
|
||||||
|
*/
|
||||||
|
private static boolean isHardCodedAlwaysParse(String fullFileName){
|
||||||
|
for(String hardCodedCase : ALWAYS_PARSED_CLASSES){
|
||||||
|
if(fullFileName.contains(hardCodedCase)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
74
src/main/java/electrosphere/main/structure/BTreeIdEnum.java
Normal file
74
src/main/java/electrosphere/main/structure/BTreeIdEnum.java
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package electrosphere.main.structure;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
|
||||||
|
import electrosphere.main.util.ClassSourceUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that is a list of every behavior tree and its associated id
|
||||||
|
*/
|
||||||
|
public class BTreeIdEnum {
|
||||||
|
|
||||||
|
//The class name of this class
|
||||||
|
public static final String CLASSNAME = "BehaviorTreeIdEnums";
|
||||||
|
|
||||||
|
//The location of the file
|
||||||
|
public static final String LOCATION = "src/main/java/electrosphere/net/synchronization/BehaviorTreeIdEnums.java";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the qualified path for the b tree id enum
|
||||||
|
* @param structure The project structure
|
||||||
|
* @return The qualified path
|
||||||
|
*/
|
||||||
|
public static String getQualifiedPath(ProjectStructure structure){
|
||||||
|
File outFile = new File(structure.getRootFolder().getAbsolutePath()).toPath().resolve(LOCATION).toFile();
|
||||||
|
return ClassSourceUtils.getPackageSourcePath(structure, outFile) + "." + CLASSNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the import declaration for this class
|
||||||
|
* @param structure The project structure
|
||||||
|
* @return The import declaration
|
||||||
|
*/
|
||||||
|
public static String getImport(ProjectStructure structure){
|
||||||
|
return "import " + getQualifiedPath(structure) + ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a b tree id enum file
|
||||||
|
* @param structure The project structure
|
||||||
|
*/
|
||||||
|
public static void generate(ProjectStructure structure){
|
||||||
|
|
||||||
|
String source = "";
|
||||||
|
File outFile = new File(structure.getRootFolder().getAbsolutePath()).toPath().resolve(LOCATION).toFile();
|
||||||
|
source = source + ClassSourceUtils.getPackageDeclaration(structure, ClassSourceUtils.getPackageSourcePath(structure, outFile));
|
||||||
|
source = source + "\n";
|
||||||
|
source = source + ClassSourceUtils.generateClassHeader("BehaviorTreeIdEnums", "List of enums for each automatically synchronized behavior tree.", true);
|
||||||
|
source = source + "\n";
|
||||||
|
for(BehaviorTree tree : structure.behaviorTrees){
|
||||||
|
source = source + " public static final int " + getTreeIdEnum(tree) + " = " + tree.id + ";\n";
|
||||||
|
}
|
||||||
|
source = source + "\n";
|
||||||
|
source = source + ClassSourceUtils.generateClassEnd();
|
||||||
|
try {
|
||||||
|
Files.write(source.getBytes(), outFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the enum name for this behavior tree
|
||||||
|
* @param tree the tree
|
||||||
|
* @return the name
|
||||||
|
*/
|
||||||
|
public static String getTreeIdEnum(BehaviorTree tree){
|
||||||
|
return "BTREE_" + tree.name.toUpperCase() + "_ID";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package electrosphere.main.structure;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import electrosphere.main.targets.TargetFile;
|
import electrosphere.main.targets.TargetFile;
|
||||||
|
import electrosphere.main.util.TemplateInjectionUtils;
|
||||||
import electrosphere.main.util.Utilities;
|
import electrosphere.main.util.Utilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,6 +17,9 @@ public class BehaviorTree {
|
|||||||
//The name of this tree
|
//The name of this tree
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
|
//the name of the class containing this tree
|
||||||
|
String className;
|
||||||
|
|
||||||
//The name of the tree corresponding to this one
|
//The name of the tree corresponding to this one
|
||||||
String correspondingTreeName;
|
String correspondingTreeName;
|
||||||
|
|
||||||
@ -32,6 +36,7 @@ public class BehaviorTree {
|
|||||||
* Constructor
|
* Constructor
|
||||||
* @param id
|
* @param id
|
||||||
* @param name
|
* @param name
|
||||||
|
* @param className
|
||||||
* @param correspondingTreeName
|
* @param correspondingTreeName
|
||||||
* @param isServer
|
* @param isServer
|
||||||
* @param synchronizedFields
|
* @param synchronizedFields
|
||||||
@ -39,6 +44,7 @@ public class BehaviorTree {
|
|||||||
public BehaviorTree(
|
public BehaviorTree(
|
||||||
int id,
|
int id,
|
||||||
String name,
|
String name,
|
||||||
|
String className,
|
||||||
String correspondingTreeName,
|
String correspondingTreeName,
|
||||||
boolean isServer,
|
boolean isServer,
|
||||||
List<SynchronizedField> synchronizedFields,
|
List<SynchronizedField> synchronizedFields,
|
||||||
@ -46,6 +52,7 @@ public class BehaviorTree {
|
|||||||
){
|
){
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.className = className;
|
||||||
this.correspondingTreeName = correspondingTreeName;
|
this.correspondingTreeName = correspondingTreeName;
|
||||||
this.isServer = isServer;
|
this.isServer = isServer;
|
||||||
this.synchronizedFields = synchronizedFields;
|
this.synchronizedFields = synchronizedFields;
|
||||||
@ -56,6 +63,10 @@ public class BehaviorTree {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getClassName(){
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
public String getCorrespondingTreeName(){
|
public String getCorrespondingTreeName(){
|
||||||
return correspondingTreeName;
|
return correspondingTreeName;
|
||||||
}
|
}
|
||||||
@ -77,23 +88,41 @@ public class BehaviorTree {
|
|||||||
*/
|
*/
|
||||||
public String getAttachMethodName(){
|
public String getAttachMethodName(){
|
||||||
String rVal = "";
|
String rVal = "";
|
||||||
rVal = "attach" + Utilities.camelCase(name);
|
rVal = "attachTree";
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAttachMethodContent(){
|
public String getAttachMethodContent(boolean isServer){
|
||||||
String rVal = "";
|
String templateSource = "/server/AttachBTree.java";
|
||||||
|
if(!isServer){
|
||||||
|
templateSource = "/client/AttachBTree.java";
|
||||||
|
}
|
||||||
|
String rVal = TemplateInjectionUtils.getFragmentWithReplacement(templateSource, this.name.toUpperCase(), "TREE_" + this.name.toUpperCase(), className);
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDetachMethodName(){
|
public String getDetachMethodName(){
|
||||||
String rVal = "";
|
String rVal = "";
|
||||||
rVal = "detach" + Utilities.camelCase(name);
|
rVal = "detachTree";
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDetachMethodContent(){
|
public String getDetachMethodContent(boolean isServer){
|
||||||
String rVal = "";
|
String templateSource = "/server/DetachBTree.java";
|
||||||
|
if(!isServer){
|
||||||
|
templateSource = "/client/DetachBTree.java";
|
||||||
|
}
|
||||||
|
String rVal = TemplateInjectionUtils.getFragmentWithReplacement(templateSource, this.name.toUpperCase());
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEntityFetchMethodName(){
|
||||||
|
String rVal = "get" + className;
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEntityFetchMethodContent(){
|
||||||
|
String rVal = TemplateInjectionUtils.getFragmentWithReplacement("/btree/EntityFetchMethod.java", this.className, "TREE_" + this.name.toUpperCase());
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,61 @@
|
|||||||
|
package electrosphere.main.structure;
|
||||||
|
|
||||||
|
import electrosphere.main.targets.TargetFile;
|
||||||
|
import electrosphere.main.util.ClassSourceUtils;
|
||||||
|
import electrosphere.main.util.TemplateInjectionUtils;
|
||||||
|
|
||||||
|
public class ClientSynchronizationManager {
|
||||||
|
|
||||||
|
|
||||||
|
//The class name of this class
|
||||||
|
public static final String CLASSNAME = "ClientSynchronizationManager";
|
||||||
|
|
||||||
|
//The location of the file
|
||||||
|
public static final String LOCATION = "src/main/java/electrosphere/net/synchronization/ClientSynchronizationManager.java";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the ClientSynchronizationManager with latest data in specific functions
|
||||||
|
* @param structure
|
||||||
|
* @param clientSynchronizationManager
|
||||||
|
*/
|
||||||
|
public static void update(ProjectStructure structure, TargetFile clientSynchronizationManager){
|
||||||
|
String updateCases = "";
|
||||||
|
for(BehaviorTree tree : structure.behaviorTrees){
|
||||||
|
//counterintuitively, want to only update client for server behavior tree ids
|
||||||
|
if(tree.isServer()){
|
||||||
|
BehaviorTree clientEquivalent = structure.getTree(tree.correspondingTreeName);
|
||||||
|
updateCases = updateCases + " case BehaviorTreeIdEnums." + BTreeIdEnum.getTreeIdEnum(tree) + ": {\n";
|
||||||
|
updateCases = updateCases + " switch(message.getfieldId()){\n";
|
||||||
|
for(SynchronizedField field : tree.synchronizedFields){
|
||||||
|
String treeName = clientEquivalent.getClassName();
|
||||||
|
switch(field.typeName){
|
||||||
|
case "int":
|
||||||
|
case "long":
|
||||||
|
case "float":
|
||||||
|
case "double":
|
||||||
|
case "String":
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException("Trying to parse type that is not supported yet");
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
SynchronizedType type = structure.getType(field.typeName);
|
||||||
|
String typeClass = type.getTargetFile().getSource().getName();
|
||||||
|
updateCases = updateCases + " case " + field.id + ":{\n";
|
||||||
|
updateCases = updateCases + " " + treeName + " tree = " + treeName + ".get" + treeName + "(entity);\n";
|
||||||
|
updateCases = updateCases + " tree." + field.getSetterName() + "(" + typeClass + "." + type.getFromShortConversionMethodName() + "((short)message.getbTreeValue()));\n";
|
||||||
|
updateCases = updateCases + " } break;\n";
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateCases = updateCases + " }\n";
|
||||||
|
updateCases = updateCases + " } break;\n";
|
||||||
|
|
||||||
|
//guarantee import
|
||||||
|
ClassSourceUtils.importClass(structure, clientSynchronizationManager, tree.getTargetFile().getQualifiedPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String fullReplacementText = TemplateInjectionUtils.getFragmentWithReplacement("/client/UpdateEntityState.java", updateCases);
|
||||||
|
ClassSourceUtils.addOrReplaceMethod(structure, clientSynchronizationManager, "updateEntityState", fullReplacementText);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package electrosphere.main.structure;
|
package electrosphere.main.structure;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -17,6 +18,9 @@ import electrosphere.main.util.ClassSourceUtils;
|
|||||||
* Container for overall structure of the project
|
* Container for overall structure of the project
|
||||||
*/
|
*/
|
||||||
public class ProjectStructure {
|
public class ProjectStructure {
|
||||||
|
|
||||||
|
//The root folder of the project
|
||||||
|
File rootFolder;
|
||||||
|
|
||||||
|
|
||||||
//The list of files to parse
|
//The list of files to parse
|
||||||
@ -31,12 +35,17 @@ public class ProjectStructure {
|
|||||||
//All types (enums) that can be synchronized
|
//All types (enums) that can be synchronized
|
||||||
List<SynchronizedType> synchronizedTypes = new LinkedList<SynchronizedType>();
|
List<SynchronizedType> synchronizedTypes = new LinkedList<SynchronizedType>();
|
||||||
|
|
||||||
|
//the client synchronization manager
|
||||||
|
TargetFile clientSynchronizationManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param targetFiles The target files to iterate on
|
* @param targetFiles The target files to iterate on
|
||||||
|
* @param rootFolder The root folder of the project
|
||||||
*/
|
*/
|
||||||
public ProjectStructure(List<TargetFile> targetFiles){
|
public ProjectStructure(List<TargetFile> targetFiles, File rootFolder){
|
||||||
this.targetFiles = targetFiles;
|
this.targetFiles = targetFiles;
|
||||||
|
this.rootFolder = rootFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -50,45 +59,69 @@ public class ProjectStructure {
|
|||||||
for(TargetFile target : targetFiles){
|
for(TargetFile target : targetFiles){
|
||||||
AnnotationSource<JavaClassSource> mainAnnotation = target.getSource().getAnnotation("SynchronizedBehaviorTree");
|
AnnotationSource<JavaClassSource> mainAnnotation = target.getSource().getAnnotation("SynchronizedBehaviorTree");
|
||||||
|
|
||||||
String bTreeName = mainAnnotation.getStringValue("name");
|
//parse btrees
|
||||||
String bTreeCorrespondingName = mainAnnotation.getStringValue("correspondingTree");
|
if(mainAnnotation != null){
|
||||||
boolean isServer = Boolean.parseBoolean(mainAnnotation.getStringValue("isServer"));
|
String bTreeName = mainAnnotation.getStringValue("name");
|
||||||
|
String bTreeCorrespondingName = mainAnnotation.getStringValue("correspondingTree");
|
||||||
|
boolean isServer = Boolean.parseBoolean(mainAnnotation.getStringValue("isServer"));
|
||||||
|
|
||||||
|
|
||||||
//parse sync'd fields
|
//parse sync'd fields
|
||||||
List<SynchronizedField> syncedFields = new LinkedList<SynchronizedField>();
|
List<SynchronizedField> syncedFields = new LinkedList<SynchronizedField>();
|
||||||
for(FieldSource<JavaClassSource> fieldSource : target.getSource().getFields()){
|
for(FieldSource<JavaClassSource> fieldSource : target.getSource().getFields()){
|
||||||
AnnotationSource<JavaClassSource> syncAnnotation = fieldSource.getAnnotation("SyncedField");
|
AnnotationSource<JavaClassSource> syncAnnotation = fieldSource.getAnnotation("SyncedField");
|
||||||
if(syncAnnotation != null){
|
if(syncAnnotation != null){
|
||||||
String fieldName = fieldSource.getName();
|
String fieldName = fieldSource.getName();
|
||||||
String typeName = fieldSource.getType().getName();
|
String typeName = fieldSource.getType().getName();
|
||||||
SynchronizedField field = new SynchronizedField(synchronizedFieldIterator,fieldName,typeName,target);
|
SynchronizedField field = new SynchronizedField(synchronizedFieldIterator,fieldName,typeName,target);
|
||||||
this.synchronizedFields.add(field);
|
this.synchronizedFields.add(field);
|
||||||
syncedFields.add(field);
|
syncedFields.add(field);
|
||||||
synchronizedFieldIterator++;
|
synchronizedFieldIterator++;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//parse sync'd enum types
|
|
||||||
for(JavaSource<?> fieldSource : target.getSource().getNestedTypes()){
|
|
||||||
if(fieldSource instanceof JavaEnumSource){
|
|
||||||
JavaEnumSource enumSource = (JavaEnumSource)fieldSource;
|
|
||||||
AnnotationSource<JavaEnumSource> annotation = enumSource.getAnnotation("SynchronizableEnum");
|
|
||||||
if(annotation != null){
|
|
||||||
List<String> values = new LinkedList<String>();
|
|
||||||
for(EnumConstantSource constants: enumSource.getEnumConstants()){
|
|
||||||
values.add(constants.getName());
|
|
||||||
}
|
|
||||||
SynchronizedType type = new SynchronizedType(typeIterator, enumSource.getName(), values,target);
|
|
||||||
synchronizedTypes.add(type);
|
|
||||||
typeIterator++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
BehaviorTree newBehaviorTree = new BehaviorTree(behaviorTreeIdIterator,bTreeName,bTreeCorrespondingName,isServer,syncedFields,target);
|
//parse sync'd enum types
|
||||||
behaviorTrees.add(newBehaviorTree);
|
for(JavaSource<?> fieldSource : target.getSource().getNestedTypes()){
|
||||||
behaviorTreeIdIterator++;
|
if(fieldSource instanceof JavaEnumSource){
|
||||||
|
JavaEnumSource enumSource = (JavaEnumSource)fieldSource;
|
||||||
|
AnnotationSource<JavaEnumSource> annotation = enumSource.getAnnotation("SynchronizableEnum");
|
||||||
|
if(annotation != null){
|
||||||
|
List<String> values = new LinkedList<String>();
|
||||||
|
for(EnumConstantSource constants: enumSource.getEnumConstants()){
|
||||||
|
values.add(constants.getName());
|
||||||
|
}
|
||||||
|
SynchronizedType type = new SynchronizedType(typeIterator, enumSource.getName(), values,target);
|
||||||
|
synchronizedTypes.add(type);
|
||||||
|
typeIterator++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BehaviorTree newBehaviorTree = new BehaviorTree(
|
||||||
|
behaviorTreeIdIterator,
|
||||||
|
bTreeName,
|
||||||
|
target.getSource().getName(),
|
||||||
|
bTreeCorrespondingName,
|
||||||
|
isServer,
|
||||||
|
syncedFields,
|
||||||
|
target
|
||||||
|
);
|
||||||
|
behaviorTrees.add(newBehaviorTree);
|
||||||
|
behaviorTreeIdIterator++;
|
||||||
|
|
||||||
|
//push behavior tree to each field
|
||||||
|
for(SynchronizedField field : syncedFields){
|
||||||
|
field.setParent(newBehaviorTree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//specific cases
|
||||||
|
|
||||||
|
//client synchronization manager
|
||||||
|
if(target.getName().contains("ClientSynchronizationManager")){
|
||||||
|
this.clientSynchronizationManager = target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,15 +132,84 @@ public class ProjectStructure {
|
|||||||
public void generate(){
|
public void generate(){
|
||||||
//generate in-class functions for btrees
|
//generate in-class functions for btrees
|
||||||
for(BehaviorTree tree : behaviorTrees){
|
for(BehaviorTree tree : behaviorTrees){
|
||||||
|
//server side getter + setter
|
||||||
if(tree.isServer){
|
if(tree.isServer){
|
||||||
for(SynchronizedField field : tree.synchronizedFields){
|
for(SynchronizedField field : tree.synchronizedFields){
|
||||||
ClassSourceUtils.addOrReplaceMethod(this, tree, field.getGetterName(), field.getServerGetterContent());
|
ClassSourceUtils.addOrReplaceMethod(this, tree.getTargetFile(), field.getGetterName(), field.getServerGetterContent());
|
||||||
ClassSourceUtils.addOrReplaceMethod(this, tree, field.getSetterName(), field.getServerSetterContent());
|
ClassSourceUtils.addOrReplaceMethod(this, tree.getTargetFile(), field.getSetterName(), field.getServerSetterContent(this));
|
||||||
|
ClassSourceUtils.importClass(this, tree.getTargetFile(), "electrosphere.server.datacell.utils.DataCellSearchUtils");
|
||||||
|
ClassSourceUtils.importClass(this, tree.getTargetFile(), "electrosphere.net.parser.net.message.SynchronizationMessage");
|
||||||
}
|
}
|
||||||
ClassSourceUtils.addOrReplaceMethod(this, tree, tree.getAttachMethodName(), tree.getAttachMethodContent());
|
//attach + detatch methods
|
||||||
ClassSourceUtils.addOrReplaceMethod(this, tree, tree.getDetachMethodName(), tree.getDetachMethodContent());
|
ClassSourceUtils.addOrReplaceMethod(this, tree.getTargetFile(), tree.getAttachMethodName(), tree.getAttachMethodContent(true));
|
||||||
|
ClassSourceUtils.addOrReplaceMethod(this, tree.getTargetFile(), tree.getDetachMethodName(), tree.getDetachMethodContent(true));
|
||||||
|
} else {
|
||||||
|
//attach + detatch methods
|
||||||
|
ClassSourceUtils.addOrReplaceMethod(this, tree.getTargetFile(), tree.getAttachMethodName(), tree.getAttachMethodContent(false));
|
||||||
|
ClassSourceUtils.addOrReplaceMethod(this, tree.getTargetFile(), tree.getDetachMethodName(), tree.getDetachMethodContent(false));
|
||||||
|
}
|
||||||
|
//guarantee entity fetch method
|
||||||
|
ClassSourceUtils.addOrReplaceMethod(this, tree.getTargetFile(), tree.getEntityFetchMethodName(), tree.getEntityFetchMethodContent());
|
||||||
|
//guarantee imports of required files (btree enum, etc)
|
||||||
|
ClassSourceUtils.importClass(this, tree.getTargetFile(), BTreeIdEnum.getQualifiedPath(this));
|
||||||
|
}
|
||||||
|
//generate enums for all synchronized types
|
||||||
|
for(SynchronizedType type : synchronizedTypes){
|
||||||
|
ClassSourceUtils.addOrReplaceMethod(this, type.getTargetFile(), type.getToShortConversionMethodName(), type.getToShortConversionMethodContent());
|
||||||
|
ClassSourceUtils.addOrReplaceMethod(this, type.getTargetFile(), type.getFromShortConversionMethodName(), type.getFromShortConversionMethodContent());
|
||||||
|
}
|
||||||
|
BTreeIdEnum.generate(this);
|
||||||
|
//client sync manager
|
||||||
|
ClientSynchronizationManager.update(this, clientSynchronizationManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes all files that had content change to disk
|
||||||
|
*/
|
||||||
|
public void writeFiles(){
|
||||||
|
for(TargetFile file : this.targetFiles){
|
||||||
|
if(file.isModified()){
|
||||||
|
file.write();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the root folder as a file object
|
||||||
|
* @return The root folder
|
||||||
|
*/
|
||||||
|
public File getRootFolder(){
|
||||||
|
return this.rootFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a synchronized type from a name
|
||||||
|
* @param typeName The name of the type
|
||||||
|
* @return The synchronized type if it exists, null otherwise
|
||||||
|
*/
|
||||||
|
public SynchronizedType getType(String typeName){
|
||||||
|
for(SynchronizedType type : this.synchronizedTypes){
|
||||||
|
if(type.name.equals(typeName)){
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a behavior tree from its name
|
||||||
|
* @param typeName The name of the tree
|
||||||
|
* @return The tree if it exists, null otherwise
|
||||||
|
*/
|
||||||
|
public BehaviorTree getTree(String typeName){
|
||||||
|
for(BehaviorTree tree : this.behaviorTrees){
|
||||||
|
if(tree.name.equals(typeName)){
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package electrosphere.main.structure;
|
package electrosphere.main.structure;
|
||||||
|
|
||||||
import electrosphere.main.targets.TargetFile;
|
import electrosphere.main.targets.TargetFile;
|
||||||
|
import electrosphere.main.util.TemplateInjectionUtils;
|
||||||
import electrosphere.main.util.Utilities;
|
import electrosphere.main.util.Utilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,11 +21,16 @@ public class SynchronizedField {
|
|||||||
//The file this type appears in
|
//The file this type appears in
|
||||||
TargetFile targetFile;
|
TargetFile targetFile;
|
||||||
|
|
||||||
|
//The parent behavior tree
|
||||||
|
BehaviorTree parent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param id
|
* @param id
|
||||||
|
* @param parent
|
||||||
* @param fieldName
|
* @param fieldName
|
||||||
* @param typeName
|
* @param typeName
|
||||||
|
* @param targetFile
|
||||||
*/
|
*/
|
||||||
public SynchronizedField(int id, String fieldName, String typeName, TargetFile targetFile){
|
public SynchronizedField(int id, String fieldName, String typeName, TargetFile targetFile){
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@ -40,7 +46,7 @@ public class SynchronizedField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getServerGetterContent(){
|
public String getServerGetterContent(){
|
||||||
String rVal = "";
|
String rVal = TemplateInjectionUtils.getFragmentWithReplacement("/server/Getter.java", fieldName, Utilities.camelCase(fieldName), typeName);
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +56,19 @@ public class SynchronizedField {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServerSetterContent(){
|
/**
|
||||||
String rVal = "";
|
* Gets parent tree of this field
|
||||||
|
* @param tree
|
||||||
|
*/
|
||||||
|
public void setParent(BehaviorTree tree){
|
||||||
|
this.parent = tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServerSetterContent(ProjectStructure structure){
|
||||||
|
SynchronizedType type = structure.getType(typeName);
|
||||||
|
String packetContentFiller = " int value = " + type.getContainingClassName() + "." + type.getToShortConversionMethodName() + "(state);\n";
|
||||||
|
packetContentFiller = packetContentFiller + " DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), " + parent.id + ", " + id + ", value));";
|
||||||
|
String rVal = TemplateInjectionUtils.getFragmentWithReplacement("/server/Setter.java", fieldName, Utilities.camelCase(fieldName), typeName, packetContentFiller);
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package electrosphere.main.structure;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import electrosphere.main.targets.TargetFile;
|
import electrosphere.main.targets.TargetFile;
|
||||||
|
import electrosphere.main.util.TemplateInjectionUtils;
|
||||||
|
import electrosphere.main.util.Utilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enum type that should have code generated for serializing/deserializing it
|
* An enum type that should have code generated for serializing/deserializing it
|
||||||
@ -40,4 +42,77 @@ public class SynchronizedType {
|
|||||||
this.targetFile = targetFile;
|
this.targetFile = targetFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the target file
|
||||||
|
* @return The target file
|
||||||
|
*/
|
||||||
|
public TargetFile getTargetFile(){
|
||||||
|
return this.targetFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the function that converts this synchronized type TO a short
|
||||||
|
* @return The name
|
||||||
|
*/
|
||||||
|
public String getToShortConversionMethodName(){
|
||||||
|
return "get" + Utilities.camelCase(name) + "EnumAsShort";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the content of the function that converts this synchronized type TO a short
|
||||||
|
* @return The content
|
||||||
|
*/
|
||||||
|
public String getToShortConversionMethodContent(){
|
||||||
|
//get enum switch array
|
||||||
|
String enumSwitchArray = "";
|
||||||
|
int i = 0;
|
||||||
|
for(String value : values){
|
||||||
|
enumSwitchArray = enumSwitchArray + " case " + value + ":\n";
|
||||||
|
enumSwitchArray = enumSwitchArray + " return " + i + ";\n";
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
//chop off last newline
|
||||||
|
enumSwitchArray = enumSwitchArray.substring(0, enumSwitchArray.length() - 1);
|
||||||
|
String rVal = TemplateInjectionUtils.getFragmentWithReplacement("/enum/EnumToShort.java", this.name, this.name, enumSwitchArray);
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the function that converts this synchronized type FROM a short
|
||||||
|
* @return The name
|
||||||
|
*/
|
||||||
|
public String getFromShortConversionMethodName(){
|
||||||
|
return "get" + Utilities.camelCase(name) + "ShortAsEnum";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the content of the function that converts this synchronized type TO a short
|
||||||
|
* @return The content
|
||||||
|
*/
|
||||||
|
public String getFromShortConversionMethodContent(){
|
||||||
|
//get enum switch array
|
||||||
|
String enumSwitchArray = "";
|
||||||
|
int i = 0;
|
||||||
|
for(String value : values){
|
||||||
|
enumSwitchArray = enumSwitchArray + " case " + i + ":\n";
|
||||||
|
enumSwitchArray = enumSwitchArray + " return " + this.name + "." + value + ";\n";
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
//add default case
|
||||||
|
enumSwitchArray = enumSwitchArray + " default:\n";
|
||||||
|
enumSwitchArray = enumSwitchArray + " return " + this.name + "." + values.get(0) + ";\n";
|
||||||
|
//chop off last newline
|
||||||
|
enumSwitchArray = enumSwitchArray.substring(0, enumSwitchArray.length() - 1);
|
||||||
|
String rVal = TemplateInjectionUtils.getFragmentWithReplacement("/enum/ShortToEnum.java", this.name, this.name, enumSwitchArray);
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the class containing the declaration of this type
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getContainingClassName(){
|
||||||
|
return getTargetFile().getName().substring(0, getTargetFile().getName().length() - 5);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,14 @@
|
|||||||
package electrosphere.main.targets;
|
package electrosphere.main.targets;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.jboss.forge.roaster.model.source.JavaClassSource;
|
import org.jboss.forge.roaster.model.source.JavaClassSource;
|
||||||
|
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
|
||||||
|
import electrosphere.main.Main;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A file that will have netcode generation performed on it
|
* A file that will have netcode generation performed on it
|
||||||
*/
|
*/
|
||||||
@ -12,12 +19,15 @@ public class TargetFile {
|
|||||||
//the original content of the file
|
//the original content of the file
|
||||||
String originalContent;
|
String originalContent;
|
||||||
//The content, with any modifications made by the netcode generator
|
//The content, with any modifications made by the netcode generator
|
||||||
String modifiedContent;
|
StringBuilder modifiedContent;
|
||||||
//the Roaster parsed source for the file
|
//the Roaster parsed source for the file
|
||||||
JavaClassSource source;
|
JavaClassSource source;
|
||||||
//the name of the file
|
//the name of the file
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
|
//holds whether the file was edited
|
||||||
|
boolean modified = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param path
|
* @param path
|
||||||
@ -28,7 +38,7 @@ public class TargetFile {
|
|||||||
public TargetFile(String path, String content, String name, JavaClassSource source){
|
public TargetFile(String path, String content, String name, JavaClassSource source){
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.originalContent = content;
|
this.originalContent = content;
|
||||||
this.modifiedContent = content;
|
this.modifiedContent = new StringBuilder(content);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
@ -61,7 +71,7 @@ public class TargetFile {
|
|||||||
* Gets the modified content of the file
|
* Gets the modified content of the file
|
||||||
* @return The modified content
|
* @return The modified content
|
||||||
*/
|
*/
|
||||||
public String getModifiedContent(){
|
public StringBuilder getModifiedContent(){
|
||||||
return modifiedContent;
|
return modifiedContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +80,51 @@ public class TargetFile {
|
|||||||
* @param content The new modified content of the file
|
* @param content The new modified content of the file
|
||||||
*/
|
*/
|
||||||
public void setModifiedContent(String content){
|
public void setModifiedContent(String content){
|
||||||
this.modifiedContent = content;
|
this.setModified(true);
|
||||||
|
this.modifiedContent = new StringBuilder(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-parses the modified content
|
||||||
|
*/
|
||||||
|
public void reparse(){
|
||||||
|
this.source = Main.parseJavaFile(this.modifiedContent.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the modified state of the file
|
||||||
|
* @param modified true if modified, false otherwise
|
||||||
|
*/
|
||||||
|
private void setModified(boolean modified){
|
||||||
|
this.modified = modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the modified state of the file
|
||||||
|
* @returntrue if modified, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isModified(){
|
||||||
|
return this.modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the modified content of the file to disk
|
||||||
|
*/
|
||||||
|
public void write(){
|
||||||
|
try {
|
||||||
|
Files.write(this.modifiedContent.toString().getBytes(), new File(this.path));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the qualified path for this file
|
||||||
|
* @return The qualified path
|
||||||
|
*/
|
||||||
|
public String getQualifiedPath(){
|
||||||
|
String rVal = this.source.getQualifiedName();
|
||||||
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,48 +1,103 @@
|
|||||||
package electrosphere.main.util;
|
package electrosphere.main.util;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jboss.forge.roaster.model.source.Import;
|
||||||
import org.jboss.forge.roaster.model.source.JavaClassSource;
|
import org.jboss.forge.roaster.model.source.JavaClassSource;
|
||||||
import org.jboss.forge.roaster.model.source.MethodSource;
|
import org.jboss.forge.roaster.model.source.MethodSource;
|
||||||
|
|
||||||
|
import electrosphere.main.structure.BTreeIdEnum;
|
||||||
import electrosphere.main.structure.BehaviorTree;
|
import electrosphere.main.structure.BehaviorTree;
|
||||||
import electrosphere.main.structure.ProjectStructure;
|
import electrosphere.main.structure.ProjectStructure;
|
||||||
|
import electrosphere.main.targets.TargetFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities for modifying the source code of a class
|
* Utilities for modifying the source code of a class
|
||||||
*/
|
*/
|
||||||
public class ClassSourceUtils {
|
public class ClassSourceUtils {
|
||||||
|
|
||||||
|
//The default indent for a method, field, etc
|
||||||
|
static final int DEFAULT_INDENT = 4;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds to replaces a method in a given behavior tree
|
* Adds to replaces a method in a given behavior tree
|
||||||
* @param structure The project structure
|
* @param structure The project structure
|
||||||
* @param tree The tree
|
* @param targetFile The targetFile
|
||||||
* @param methodName The name of the method
|
* @param methodName The name of the method
|
||||||
* @param methodContent The content of the method that you want to insert or replace with
|
* @param methodContent The content of the method that you want to insert or replace with
|
||||||
*/
|
*/
|
||||||
public static void addOrReplaceMethod(ProjectStructure structure, BehaviorTree tree, String methodName, String methodContent){
|
public static void addOrReplaceMethod(ProjectStructure structure, TargetFile targetFile, String methodName, String methodContent){
|
||||||
boolean hasMethod;
|
//search for method
|
||||||
//search for setter
|
List<MethodSource<JavaClassSource>> methods = targetFile.getSource().getMethods();
|
||||||
MethodSource<JavaClassSource> methodSource = tree.getTargetFile().getSource().getMethod(methodName);
|
MethodSource<JavaClassSource> methodSource = null;
|
||||||
if(methodSource == null){
|
for(MethodSource<JavaClassSource> methodRaw : methods){
|
||||||
|
if(methodRaw.getName().equals(methodName)){
|
||||||
} else {
|
if(methodSource != null){
|
||||||
throw new UnsupportedOperationException();
|
throw new UnknownError("Two methods in a source file have the same name. This is unsupported by the addOrReplaceMethod function at this time!");
|
||||||
// ClassSourceUtils.addOrReplaceMethod(this, tree, field.getSetterName(), field.getServerSetterContent());
|
}
|
||||||
// System.out.println(new StringBuilder(tree.targetFile.getModifiedContent()).insert(setterMethod.getStartPosition(), "asdf").toString());
|
methodSource = methodRaw;
|
||||||
// System.out.println(setterMethod.getStartPosition());
|
}
|
||||||
}
|
}
|
||||||
|
StringBuilder modifiedContent = targetFile.getModifiedContent();
|
||||||
|
if(methodSource == null){
|
||||||
|
int endOfClass = findEndOfClass(modifiedContent.toString());
|
||||||
|
String indentedFragment = TemplateInjectionUtils.indentFragment(methodContent, DEFAULT_INDENT);
|
||||||
|
//must newline
|
||||||
|
String finalInsertion = indentedFragment + "\n";
|
||||||
|
modifiedContent.insert(endOfClass, finalInsertion);
|
||||||
|
} else {
|
||||||
|
//methodStart is literally the first character of the function's name
|
||||||
|
int methodStart = methodSource.getStartPosition();
|
||||||
|
int indent = getCurrentIndent(modifiedContent.toString(),methodStart - 1);
|
||||||
|
int methodEnd = methodSource.getEndPosition();
|
||||||
|
String indentedFragment = TemplateInjectionUtils.indentFragment(methodContent, indent).trim();
|
||||||
|
modifiedContent.replace(methodStart, methodEnd, indentedFragment);
|
||||||
|
}
|
||||||
|
targetFile.setModifiedContent(modifiedContent.toString());
|
||||||
|
targetFile.reparse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the end of a class file
|
||||||
|
* @param sourceRaw The raw source
|
||||||
|
* @return The index of the final curly brace
|
||||||
|
*/
|
||||||
|
private static int findEndOfClass(String sourceRaw){
|
||||||
|
int curr = sourceRaw.length() - 1;
|
||||||
|
while(sourceRaw.charAt(curr) != '}'){
|
||||||
|
curr--;
|
||||||
|
}
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current indent of the source file at a given location
|
||||||
|
* @param sourceRaw The source file
|
||||||
|
* @param position The position
|
||||||
|
* @return The indent
|
||||||
|
*/
|
||||||
|
private static int getCurrentIndent(String sourceRaw, int position){
|
||||||
|
int indent = 0;
|
||||||
|
int curr = position;
|
||||||
|
while(sourceRaw.charAt(curr) != '\n'){
|
||||||
|
curr--;
|
||||||
|
indent++;
|
||||||
|
}
|
||||||
|
return indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the first part of a class declaration file
|
* Generates the first part of a class declaration file
|
||||||
* @param name The name of the class
|
* @param name The name of the class
|
||||||
|
* @param description The description of the class
|
||||||
* @param isPublic True if public, false otherwise
|
* @param isPublic True if public, false otherwise
|
||||||
* @return The string containing the class header
|
* @return The string containing the class header
|
||||||
*/
|
*/
|
||||||
public static String generateClassHeader(String name, boolean isPublic){
|
public static String generateClassHeader(String name, String description, boolean isPublic){
|
||||||
String rVal = "\t";
|
String rVal = "/**\n * " + description + "\n */\n";
|
||||||
|
rVal = rVal + "";
|
||||||
rVal = rVal + (isPublic ? "public " : "");
|
rVal = rVal + (isPublic ? "public " : "");
|
||||||
rVal = rVal + "class " + name + " {\n";
|
rVal = rVal + "class " + name + " {\n";
|
||||||
return rVal;
|
return rVal;
|
||||||
@ -54,9 +109,31 @@ public class ClassSourceUtils {
|
|||||||
* @param fileObj The raw java file object
|
* @param fileObj The raw java file object
|
||||||
* @return The package declaration
|
* @return The package declaration
|
||||||
*/
|
*/
|
||||||
public static String getPackageSourcePath(File fileObj){
|
public static String getPackageSourcePath(ProjectStructure structure, File fileObj){
|
||||||
String rVal = "";
|
String rVal = "";
|
||||||
throw new UnsupportedOperationException();
|
rVal = structure.getRootFolder().toURI().relativize(fileObj.toURI()).getPath();
|
||||||
|
//delete past last forwardslash
|
||||||
|
int lastSlashIndex = rVal.length() - 1;
|
||||||
|
while(rVal.charAt(lastSlashIndex) != '/'){
|
||||||
|
lastSlashIndex--;
|
||||||
|
}
|
||||||
|
rVal = rVal.substring(0, lastSlashIndex);
|
||||||
|
//delete intro part
|
||||||
|
rVal = rVal.replace("src/main/java/", "");
|
||||||
|
rVal = rVal.replace("/",".");
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the package declaration for a given package path
|
||||||
|
* @param structure The project structure
|
||||||
|
* @param packagePath The package path
|
||||||
|
* @return The declaration line
|
||||||
|
*/
|
||||||
|
public static String getPackageDeclaration(ProjectStructure structure, String packagePath){
|
||||||
|
String rVal = "";
|
||||||
|
rVal = "package " + packagePath + ";\n";
|
||||||
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,4 +144,26 @@ public class ClassSourceUtils {
|
|||||||
return "}\n";
|
return "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guarantees that a given path is imported
|
||||||
|
* @param structure The project structure
|
||||||
|
* @param tree The tree
|
||||||
|
* @param qualifiedPath The qualified name to import
|
||||||
|
*/
|
||||||
|
public static void importClass(ProjectStructure structure, TargetFile targetFile, String qualifiedPath){
|
||||||
|
StringBuilder modifiedContent = targetFile.getModifiedContent();
|
||||||
|
List<Import> imports = targetFile.getSource().getImports();
|
||||||
|
boolean present = false;
|
||||||
|
for(Import currentImport : imports){
|
||||||
|
String importName = currentImport.getQualifiedName();
|
||||||
|
if(importName.equals(qualifiedPath)){
|
||||||
|
present = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!present){
|
||||||
|
Utilities.insertIntoSource(modifiedContent, "import " + qualifiedPath + ";", 3);
|
||||||
|
targetFile.setModifiedContent(modifiedContent.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,9 @@ package electrosphere.main.util;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.sun.tools.javac.Main;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tools for taking files that represent source file fragments and injecting strings to replace portions of the fragment
|
* Tools for taking files that represent source file fragments and injecting strings to replace portions of the fragment
|
||||||
@ -9,21 +12,37 @@ import java.util.List;
|
|||||||
public class TemplateInjectionUtils {
|
public class TemplateInjectionUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a fragment from a source file and replaces all strings with provided ones
|
* Loads a fragment from a source file and replaces all strings with provided ones. Used specifically for filling out template files baked into this tool.
|
||||||
* @param sourceFile The source file relative path
|
* @param sourceFile The source file relative path
|
||||||
* @param replaceStrings The list of strings to replace
|
* @param replaceStrings The list of strings to replace
|
||||||
* @return The properly updated string
|
* @return The properly updated string
|
||||||
*/
|
*/
|
||||||
public static String getFragmentWithReplacement(String sourceFile, String ... replaceStrings){
|
public static String getFragmentWithReplacement(String sourceFile, String ... replaceStrings){
|
||||||
String rVal = "";
|
String rVal = Utilities.readBakedResourceToString(TemplateInjectionUtils.class.getResourceAsStream(sourceFile));
|
||||||
List<String> replaceStringList = Arrays.asList(replaceStrings);
|
List<String> replaceStringList = Arrays.asList(replaceStrings);
|
||||||
int iterator = 0;
|
int iterator = 0;
|
||||||
for(String replaceString : replaceStringList){
|
for(String replaceString : replaceStringList){
|
||||||
rVal = rVal.replace(iterator + "REPLACE_ME", replaceString);
|
rVal = rVal.replace("REPLACE_" + iterator + "_ME", replaceString);
|
||||||
iterator++;
|
iterator++;
|
||||||
}
|
}
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indents a fragment based on an indentation amount
|
||||||
|
* @param fragment The fragment
|
||||||
|
* @param indentAmount The indentation required (in spaces)
|
||||||
|
* @return The indented fragment
|
||||||
|
*/
|
||||||
|
public static String indentFragment(String fragment, int indentAmount){
|
||||||
|
return Arrays.asList(fragment.split("\n")).stream().map((String line) -> {
|
||||||
|
String indent = "";
|
||||||
|
for(int i = 0; i < indentAmount; i++){
|
||||||
|
indent = indent + " ";
|
||||||
|
}
|
||||||
|
return indent + line;
|
||||||
|
}).collect(Collectors.joining("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,7 +96,7 @@ public class Utilities {
|
|||||||
//now move backwards to find the previous line with content on it
|
//now move backwards to find the previous line with content on it
|
||||||
characterPosition = characterPosition - 1;
|
characterPosition = characterPosition - 1;
|
||||||
while(true){
|
while(true){
|
||||||
if(source.charAt(characterPosition)=='\n' && source.charAt(characterPosition + 1)==' '){
|
if(source.charAt(characterPosition)=='\n' && source.charAt(characterPosition + 1)!='\n'){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
characterPosition--;
|
characterPosition--;
|
||||||
|
|||||||
10
src/main/resources/btree/EntityFetchMethod.java
Normal file
10
src/main/resources/btree/EntityFetchMethod.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Gets the REPLACE_0_ME of the entity
|
||||||
|
* </p>
|
||||||
|
* @param entity the entity
|
||||||
|
* @return The REPLACE_0_ME
|
||||||
|
*/
|
||||||
|
public static REPLACE_0_ME getREPLACE_0_ME(Entity entity){
|
||||||
|
return (REPLACE_0_ME)entity.getData(EntityDataStrings.REPLACE_1_ME);
|
||||||
|
}
|
||||||
20
src/main/resources/client/AttachBTree.java
Normal file
20
src/main/resources/client/AttachBTree.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* <p> (initially) Automatically generated </p>
|
||||||
|
* <p> More parameters can be safely added to this method</p>
|
||||||
|
* <p>
|
||||||
|
* Attaches this tree to the entity.
|
||||||
|
* </p>
|
||||||
|
* @param entity The entity to attach to
|
||||||
|
* @param tree The behavior tree to attach
|
||||||
|
*/
|
||||||
|
public static REPLACE_2_ME attachTree(Entity parent){
|
||||||
|
REPLACE_2_ME rVal = new REPLACE_2_ME(parent);
|
||||||
|
//put manual code here (setting params, etc)
|
||||||
|
|
||||||
|
|
||||||
|
//!!WARNING!! from here below should not be touched
|
||||||
|
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
|
||||||
|
parent.putData(EntityDataStrings.REPLACE_1_ME, rVal);
|
||||||
|
Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_REPLACE_0_ME_ID);
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
11
src/main/resources/client/DetachBTree.java
Normal file
11
src/main/resources/client/DetachBTree.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* <p> Automatically generated </p>
|
||||||
|
* <p>
|
||||||
|
* Detatches this tree from the entity.
|
||||||
|
* </p>
|
||||||
|
* @param entity The entity to detach to
|
||||||
|
* @param tree The behavior tree to detach
|
||||||
|
*/
|
||||||
|
public static void detachTree(Entity entity, BehaviorTree tree){
|
||||||
|
Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_REPLACE_0_ME_ID);
|
||||||
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
EntityMessage.constructsetBTreePropertyDoubleMessage(parent.getId(), Main.getCurrentFrame(), REPLACEBTREEID, REPLACEPROPERTYID, REPLACENAMENOTCAMEL)
|
|
||||||
@ -1 +0,0 @@
|
|||||||
EntityMessage.constructsetBTreePropertyEnumMessage(parent.getId(), Main.getCurrentFrame(), REPLACEBTREEID, REPLACEPROPERTYID, getEnumIntValueREPLACENAMECAMEL(REPLACENAMENOTCAMEL))
|
|
||||||
@ -1 +0,0 @@
|
|||||||
EntityMessage.constructsetBTreePropertyFloatMessage(parent.getId(), Main.getCurrentFrame(), REPLACEBTREEID, REPLACEPROPERTYID, REPLACENAMENOTCAMEL)
|
|
||||||
@ -1 +0,0 @@
|
|||||||
EntityMessage.constructsetBTreePropertyIntMessage(parent.getId(), Main.getCurrentFrame(), REPLACEBTREEID, REPLACEPROPERTYID, REPLACENAMENOTCAMEL)
|
|
||||||
@ -1 +0,0 @@
|
|||||||
EntityMessage.constructsetBTreePropertyStringMessage(parent.getId(), Main.getCurrentFrame(), REPLACEBTREEID, REPLACEPROPERTYID, REPLACENAMENOTCAMEL)
|
|
||||||
14
src/main/resources/client/UpdateEntityState.java
Normal file
14
src/main/resources/client/UpdateEntityState.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* <p> Automatically generated </p>
|
||||||
|
* <p>
|
||||||
|
* Updates the state of a given behavior tree on a given entity
|
||||||
|
* </p>
|
||||||
|
* @param entity The entity
|
||||||
|
* @param bTreeId The id of the behavior tree
|
||||||
|
* @param message The raw synchronization message holding the update data
|
||||||
|
*/
|
||||||
|
private void updateEntityState(Entity entity, int bTreeId, SynchronizationMessage message){
|
||||||
|
switch(bTreeId){
|
||||||
|
REPLACE_0_ME
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/main/resources/enum/EnumToShort.java
Normal file
15
src/main/resources/enum/EnumToShort.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* <p> Automatically generated </p>
|
||||||
|
* <p>
|
||||||
|
* Converts this enum type to an equivalent short value
|
||||||
|
* </p>
|
||||||
|
* @param enumVal The enum value
|
||||||
|
* @return The short value
|
||||||
|
*/
|
||||||
|
public static short getREPLACE_0_MEEnumAsShort(REPLACE_1_ME enumVal){
|
||||||
|
switch(enumVal){
|
||||||
|
REPLACE_2_ME
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/main/resources/enum/ShortToEnum.java
Normal file
13
src/main/resources/enum/ShortToEnum.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* <p> Automatically generated </p>
|
||||||
|
* <p>
|
||||||
|
* Converts a short to the equivalent enum value
|
||||||
|
* </p>
|
||||||
|
* @param shortVal The short value
|
||||||
|
* @return The enum value
|
||||||
|
*/
|
||||||
|
public static REPLACE_1_ME getREPLACE_0_MEShortAsEnum(short shortVal){
|
||||||
|
switch(shortVal){
|
||||||
|
REPLACE_2_ME
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/main/resources/server/AttachBTree.java
Normal file
21
src/main/resources/server/AttachBTree.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* <p> (initially) Automatically generated </p>
|
||||||
|
* <p> More parameters can be safely added to this method</p>
|
||||||
|
* <p>
|
||||||
|
* Attaches this tree to the entity.
|
||||||
|
* </p>
|
||||||
|
* @param entity The entity to attach to
|
||||||
|
* @param tree The behavior tree to attach
|
||||||
|
*/
|
||||||
|
public static REPLACE_2_ME attachTree(Entity parent){
|
||||||
|
REPLACE_2_ME rVal = new REPLACE_2_ME(parent);
|
||||||
|
//put manual code here (setting params, etc)
|
||||||
|
|
||||||
|
|
||||||
|
//!!WARNING!! from here below should not be touched
|
||||||
|
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
|
||||||
|
ServerBehaviorTreeUtils.attachBTreeToEntity(parent, rVal);
|
||||||
|
parent.putData(EntityDataStrings.REPLACE_1_ME, rVal);
|
||||||
|
Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_REPLACE_0_ME_ID);
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
11
src/main/resources/server/DetachBTree.java
Normal file
11
src/main/resources/server/DetachBTree.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* <p> Automatically generated </p>
|
||||||
|
* <p>
|
||||||
|
* Detatches this tree from the entity.
|
||||||
|
* </p>
|
||||||
|
* @param entity The entity to detach to
|
||||||
|
* @param tree The behavior tree to detach
|
||||||
|
*/
|
||||||
|
public static void detachTree(Entity entity, BehaviorTree tree){
|
||||||
|
Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_REPLACE_0_ME_ID);
|
||||||
|
}
|
||||||
9
src/main/resources/server/Getter.java
Normal file
9
src/main/resources/server/Getter.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* <p> Automatically generated </p>
|
||||||
|
* <p>
|
||||||
|
* Gets REPLACE_0_ME.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public REPLACE_2_ME getREPLACE_1_ME(){
|
||||||
|
return REPLACE_0_ME;
|
||||||
|
}
|
||||||
@ -1,13 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* <p> Automatically generated </p>
|
* <p> Automatically generated </p>
|
||||||
* <p>
|
* <p>
|
||||||
* Sets REPLACENAMENOTCAMEL and handles the synchronization logic for it.
|
* Sets REPLACE_0_ME and handles the synchronization logic for it.
|
||||||
* </p>
|
* </p>
|
||||||
* @param REPLACENAMENOTCAMEL The value to set REPLACENAMENOTCAMEL to.
|
* @param REPLACE_0_ME The value to set REPLACE_0_ME to.
|
||||||
*/
|
*/
|
||||||
public void setREPLACENAMECAMEL(REPLACETYPE REPLACENAMENOTCAMEL){
|
public void setREPLACE_1_ME(REPLACE_2_ME REPLACE_0_ME){
|
||||||
this.REPLACENAMENOTCAMEL = REPLACENAMENOTCAMEL;
|
this.REPLACE_0_ME = REPLACE_0_ME;
|
||||||
Globals.entityDataCellMapper.getEntityDataCell(parent).broadcastNetworkMessage(
|
REPLACE_3_ME
|
||||||
REPLACEMESSAGECONSTRUCTOR
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
EntityMessage.constructsetBTreePropertyDoubleMessage(parent.getId(), Main.getCurrentFrame(), REPLACEBTREEID, REPLACEPROPERTYID, REPLACENAMENOTCAMEL)
|
|
||||||
@ -1 +0,0 @@
|
|||||||
EntityMessage.constructsetBTreePropertyEnumMessage(parent.getId(), Main.getCurrentFrame(), REPLACEBTREEID, REPLACEPROPERTYID, getEnumIntValueREPLACENAMECAMEL(REPLACENAMENOTCAMEL))
|
|
||||||
@ -1 +0,0 @@
|
|||||||
EntityMessage.constructsetBTreePropertyFloatMessage(parent.getId(), Main.getCurrentFrame(), REPLACEBTREEID, REPLACEPROPERTYID, REPLACENAMENOTCAMEL)
|
|
||||||
@ -1 +0,0 @@
|
|||||||
EntityMessage.constructsetBTreePropertyIntMessage(parent.getId(), Main.getCurrentFrame(), REPLACEBTREEID, REPLACEPROPERTYID, REPLACENAMENOTCAMEL)
|
|
||||||
@ -1 +0,0 @@
|
|||||||
EntityMessage.constructsetBTreePropertyStringMessage(parent.getId(), Main.getCurrentFrame(), REPLACEBTREEID, REPLACEPROPERTYID, REPLACENAMENOTCAMEL)
|
|
||||||
@ -24,7 +24,7 @@ Client receives a behavior tree update packet
|
|||||||
|
|
||||||
client sends this packet to a behavior tree synchronization manager
|
client sends this packet to a behavior tree synchronization manager
|
||||||
|
|
||||||
the manager finds the client with the correct id
|
the manager finds the entity with the correct id
|
||||||
|
|
||||||
it then does a lookup against a table generated by the code gen tool
|
it then does a lookup against a table generated by the code gen tool
|
||||||
the table points behavior tree id to class
|
the table points behavior tree id to class
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user