Skip to content

Commit

Permalink
Merge pull request #26 from OnapleRPG/feature/conf-folder-issue-22
Browse files Browse the repository at this point in the history
Allow multiple conf files
  • Loading branch information
zessirb authored Jul 18, 2020
2 parents 866f5fa + 3dcc084 commit 14ce7cf
Show file tree
Hide file tree
Showing 13 changed files with 100 additions and 32 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ scripts
*.iml
gradlew.bat
gradle
.classpath
.project
.settings
.vscode
bin
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ Permission : *itemizer.command.reload*

## Configuration files

All configuration files use HOCON format. they are loaded at the plugin start. you can force a reload with the command `/reload-itemizer`
> I higly recommend you to backup your files to avoid any loss.
All configuration files use HOCON format. They are loaded at plugin start. You can force a reload with the command `/reload-itemizer` (crafts will require a server restart).
The configuration files are stored in the *config/itemizer* folder of your server. Default configuration files will be generated if they do not exist. You can also use a folder instead of a plain file, the plugin will then read every files within it (for instance, create a folder *items* instead of the *items.conf*, and put every HOCON files within it).
> I highly recommend you backup your files to avoid any loss.
### Global configuration
In the global configuration file you can change plugin settings :
Expand All @@ -44,7 +45,7 @@ You can chose to rewrite them manually. set `False` to let default look or `True

You can chose to edit the config file or use `/configure <Type> <Key> [value]` command.

__Be careful the command override the file change__
__Be careful using the command, it overrides the file__


### Item creation
Expand Down Expand Up @@ -105,7 +106,7 @@ An example of an battle axe indexed as _barbarian_axe_ with some attribute modif
display {
Lore=[
"Nobody have whet this blade yet",
"however it still can sharp your finger"
"Nonetheless it is sharp on your finger"
]
Name="Barbarian Axe"
}
Expand Down
8 changes: 4 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ versioning {
patch = 1
}
group = 'com.onaple'
version = "3.6.1"
version = "3.7.0"

repositories {
mavenCentral()
Expand Down Expand Up @@ -75,9 +75,9 @@ bintray {
licenses = ['Apache-2.0']
vcsUrl = '[email protected]:OnapleRPG/Itemizer.git'
version {
name = '3.6.1'
name = '3.7.0'
released = new Date()
vcsTag = '3.6.1'
vcsTag = '3.7.0'
}
}
}
Expand All @@ -87,7 +87,7 @@ publishing {
from components.java
groupId 'com.onaple'
artifactId 'itemizer'
version '3.6.1'
version '3.7.0'
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/com/onaple/itemizer/Itemizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -146,14 +146,14 @@ public void gameConstruct(GameConstructionEvent event) {
.dataClass(IdDataManipulator.class)
.immutableClass(IdDataManipulator.Immutable.class)
.builder(new IdDataManipulator.Builder())
.buildAndRegister(getInstance());
.build();
this.basenameDataRegistration = DataRegistration.builder()
.name("item base name")
.id("item.basename")
.dataClass(BaseNameDataManipulator.class)
.immutableClass(BaseNameDataManipulator.Immutable.class)
.builder(new BaseNameDataManipulator.Builder())
.buildAndRegister(getInstance());
.build();
loadConfiguration();
}

Expand All @@ -166,7 +166,7 @@ public void onCraftRegistration(GameRegistryEvent.Register<CraftingRecipe> event
i++;
}
}
getLogger().info("registered {} crafting recipes",i);
getLogger().info("Registered {} crafting recipes",i);
}
@Listener
public void onSmeltingRegistration(GameRegistryEvent.Register<SmeltingRecipe> event) {
Expand All @@ -177,7 +177,7 @@ public void onSmeltingRegistration(GameRegistryEvent.Register<SmeltingRecipe> ev
i++;
}
}
getLogger().info("registered {} smelting recipes",i);
getLogger().info("Registered {} smelting recipes",i);
}

public void loadConfiguration(){
Expand All @@ -191,13 +191,13 @@ public void loadConfiguration(){
}
try {
int size = configurationHandler.readItemsConfiguration();
getLogger().info("{} items loaded from configuration.", size);
getLogger().info("{} items loaded from configuration.", size);
} catch (ObjectMappingException | IOException e) {
Itemizer.getLogger().warn("Error while reading configuration 'items'.", e);
}
try {
int size = configurationHandler.readPoolsConfiguration();
getLogger().info("{} pools loaded from configuration.", size);
getLogger().info("{} pools loaded from configuration.", size);
} catch (ObjectMappingException | IOException e) {
Itemizer.getLogger().warn("Error while reading configuration 'pools'.", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public IdElement(@Nullable Text key) {
protected Object parseValue(CommandSource source, CommandArgs args) throws ArgumentParseException {
String id = args.next();
Optional<ItemBean> itemBeanOptional =Itemizer.getItemDAO().getItem(id);
return itemBeanOptional.orElseThrow(() -> new ArgumentParseException(Text.of("Id not found"),source.getName(),1));
return itemBeanOptional.orElseThrow(() -> new ArgumentParseException(Text.of("Id not found"), id, 1));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

public class LoreManagerCommand implements CommandExecutor {
@Override
@SuppressWarnings("unchecked")
public CommandResult execute(CommandSource src, CommandContext args) throws CommandException {
Optional<ItemBean> item= args.getOne("id");
List<Text> lore = args.<List>getOne("lore").orElse(new ArrayList<>());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class ShapedCrafting extends AbstractCraftingRecipe {


@Override
@SuppressWarnings("unchecked")
public void register(GameRegistryEvent.Register event) {
CraftingRecipe r = shapedBuilder().
aisle(this.pattern.stream().toArray(String[]::new)).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class ShapelessCrafting extends AbstractCraftingRecipe {
protected String content;

@Override
@SuppressWarnings("unchecked")
public void register(GameRegistryEvent.Register event) {
Recipe r = CraftingRecipe.shapelessBuilder()
.addIngredient(Ingredient.builder().with(isMatchingId(content)).build())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class Smelting extends AbstractCraftingRecipe {
private String ref;

@Override
@SuppressWarnings("unchecked")
public void register(GameRegistryEvent.Register event) {
Recipe r = SmeltingRecipe.builder().
ingredient(isSnapshotMatchingId(ref) ,ingredient.createSnapshot()).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,30 +87,39 @@ public void createItemizerDirectory() {
}
}

private <T> T readConfiguration(String file, Class<T> clazz) throws IOException, ObjectMappingException {
Path path = Paths.get(configDir + "/itemizer/", file);
initDefaultConfig(path);
T root = ConfigUtils.load(clazz, path);
if (root != null) {
return root;
private <T> List<T> readConfiguration(String file, Class<T> clazz) throws IOException, ObjectMappingException {
Path path = Paths.get(configDir + "/itemizer/", file + ".conf");
Path folderPath = Paths.get(configDir + "/itemizer/" + file + "/");
List<T> rootList = new ArrayList<>();
if (!folderPath.toFile().exists()) {
initDefaultConfig(path);
rootList.add(ConfigUtils.load(clazz, path));
} else {
getLogger().warn("Empty config file");
throw new IOException();
rootList = ConfigUtils.loadMultiple(clazz, folderPath);
if (path.toFile().exists()) {
try {
rootList.add(ConfigUtils.load(clazz, path));
} catch (IOException | ObjectMappingException e) {
Itemizer.getLogger().warn("Error while reading " + file + ".conf config file", e);
}
}
}
rootList.removeIf(root -> root == null);
return rootList;
}

/**
* Read items configuration and interpret it
*/
public int readItemsConfiguration() throws IOException, ObjectMappingException {
itemList.clear();
itemList.addAll(readConfiguration("items.conf", ItemsRoot.class).getItems());
readConfiguration("items", ItemsRoot.class).forEach(itemRoot -> itemList.addAll(itemRoot.getItems()));
return itemList.size();
}

public int readAffixConfiguration() throws IOException, ObjectMappingException {
affixBeans.clear();
affixBeans.addAll(readConfiguration("affix.conf", AffixRoot.class).getAffixes());
readConfiguration("affix", AffixRoot.class).forEach(affixRoot -> affixBeans.addAll(affixRoot.getAffixes()));
return affixBeans.size();
}

Expand All @@ -119,7 +128,7 @@ public int readAffixConfiguration() throws IOException, ObjectMappingException {
*/
public int readCraftConfiguration() throws ObjectMappingException, IOException {
craftList.clear();
craftList.addAll(readConfiguration("crafts.conf", CraftsRoot.class).getCraftingRecipes());
readConfiguration("crafts", CraftsRoot.class).forEach(craftRoot -> craftList.addAll(craftRoot.getCraftingRecipes()));
return craftList.size();
}

Expand All @@ -128,7 +137,7 @@ public int readCraftConfiguration() throws ObjectMappingException, IOException {
*/
public int readPoolsConfiguration() throws ObjectMappingException, IOException {
poolList.clear();
poolList.addAll(readConfiguration("pools.conf", PoolsRoot.class).getPoolList());
readConfiguration("pools", PoolsRoot.class).forEach(poolRoot -> poolList.addAll(poolRoot.getPoolList()));
return poolList.size();
}

Expand Down Expand Up @@ -173,10 +182,9 @@ private void initDefaultConfig(Path path) {
PluginContainer pluginInstance = Itemizer.getInstance();
if (pluginInstance != null) {
Optional<Asset> itemsDefaultConfigFile = pluginInstance.getAsset(path.getFileName().toString());
getLogger().info("No config file set for {} default config will be loaded", path);
getLogger().info("No config file set for {}. default config will be loaded", path);
if (itemsDefaultConfigFile.isPresent()) {
try {

itemsDefaultConfigFile.get().copyToFile(path);
} catch (IOException e) {
getLogger().error("Error while setting default configuration : ", e);
Expand All @@ -188,3 +196,4 @@ private void initDefaultConfig(Path path) {
}
}
}

49 changes: 49 additions & 0 deletions src/main/java/com/onaple/itemizer/utils/ConfigUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.onaple.itemizer.Itemizer;

import static org.checkerframework.checker.units.UnitsTools.s;

Expand All @@ -23,4 +29,47 @@ public static <T> T load(Class<T> clazz, Path path) throws IOException, ObjectMa
throw new RuntimeException("Could not load file " + s, e);
}
}

/**
* Replicates "load" method but allowing folders
**/
@SuppressWarnings("unchecked")
public static <T> List<T> loadMultiple(Class<T> clazz, Path initialPath) throws IOException, ObjectMappingException {
List<T> loadedFiles = new ArrayList<>();
List<Path> paths = getFilesFromPath(initialPath);
paths.forEach(path -> {
try {
ObjectMapper mapper = NotSoStupidObjectMapper.forClass(clazz);
HoconConfigurationLoader hcl = HoconConfigurationLoader.builder().setPath(path).build();
loadedFiles.add((T) mapper.bind(clazz.getConstructor().newInstance()).populate(hcl.load()));
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException | ObjectMappingException | IOException e) {
Itemizer.getLogger().error("Could not load file " + path.getFileName(), e);
}
});
return loadedFiles;
}

/**
* Recursion limit to avoid unexpected long loops
**/
private static int READ_RECURSION_LIMIT = 3;
/**
/**
* Get all config Files or subfolders until recursion is reached
**/
private static List<Path> getFilesFromPath(Path path) {
List<Path> filesFound = new ArrayList<>();
if (Files.exists(path)) {
try {
filesFound.addAll(Files.walk(path, READ_RECURSION_LIMIT)
.filter(Files::isRegularFile)
.distinct()
.collect(Collectors.toList()));
} catch (IOException e) {
Itemizer.getLogger().error("Error when reading configuration files from folder", e);
}
}
return filesFound;
}
}

2 changes: 1 addition & 1 deletion src/main/resources/assets/itemizer/items.conf
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ items=[
display {
Lore=[
"Nobody have whet this blade yet",
"however it still can sharp your finger"
"Nonetheless it is sharp on your finger"
]
Name="Barbarian Axe"
}
Expand Down
4 changes: 2 additions & 2 deletions version.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#Sat May 09 14:54:47 CEST 2020
#Sat Jul 18 12:41:03 CEST 2020
MAJOR=3
MINOR=3
PATCH=1
PRE_RELEASE=
BUILD=200
BUILD=223
CODE=0

0 comments on commit 14ce7cf

Please sign in to comment.