diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..1dffa06 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,53 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG]" +labels: Bug +assignees: '' + +--- + +## Describe the bug (REQUIRED) + + + +## Expected behaviour (REQUIRED) + + + +## Steps to Reproduce Issue (REQUIRED) + + + +1. +2. +3. + + +## Environment (REQUIRED) + + + + + + +- Server Software: +- Minecraft Version: +- Craftory Version: +- Other Craftory Plugins: + +## Server Log (OPTIONAL) + + + + + + +## Estimated Difficulty (OPTIONAL) + + + + + +## Additional context (OPTIONAL) + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..09061fc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,28 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[Suggestion] " +labels: Feature, Suggestion +assignees: '' + +--- + + + + + + + +## Description of Feature (REQUIRED) + + + +## Details of Benefit (REQUIRED) + + + + +## Estimated Difficulty (OPTIONAL) + + + diff --git a/.github/workflows/release-notes.yaml b/.github/workflows/release-notes.yaml new file mode 100644 index 0000000..92ffc9d --- /dev/null +++ b/.github/workflows/release-notes.yaml @@ -0,0 +1,21 @@ +name: Release-Notes-Preview + +on: + pull_request: + branches: [ master ] + issue_comment: + types: [ edited ] + +jobs: + preview: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: | + git fetch --prune --unshallow --tags + - uses: snyk/release-notes-preview@v1.6.1 + with: + releaseBranch: master + env: + GITHUB_PR_USERNAME: ${{ github.actor }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..cba4633 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,18 @@ +name: Publish package to GitHub Packages +on: + release: + types: [created] +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Change Project + run: cd api + - name: Publish package + run: mvn --batch-mode deploy + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/api/pom.xml b/api/pom.xml index d90897d..a589a5a 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -15,11 +15,20 @@ craftorystudios_Craftory_Core craftorystudios https://sonarcloud.io + false craftory-api jar + + + github + GitHub CraftoryStudios Apache Maven Packages + https://maven.pkg.github.com/CraftoryStudios/Craftory + + + diff --git a/api/src/main/java/studio/craftory/core/Craftory.java b/api/src/main/java/studio/craftory/core/Craftory.java index 15294b4..8698e6b 100644 --- a/api/src/main/java/studio/craftory/core/Craftory.java +++ b/api/src/main/java/studio/craftory/core/Craftory.java @@ -11,6 +11,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPluginLoader; import studio.craftory.core.api.CustomBlockAPI; +import studio.craftory.core.blocks.BlockRenderManager; import studio.craftory.core.blocks.CustomBlockManager; import studio.craftory.core.blocks.CustomBlockRegistry; import studio.craftory.core.commands.SpawnItemCommand; @@ -22,6 +23,7 @@ import studio.craftory.core.listeners.CustomBlockListener; import studio.craftory.core.listeners.WorldListener; import studio.craftory.core.recipes.RecipeManager; +import studio.craftory.core.resourcepack.AssetLinker; import studio.craftory.core.utils.Log; public final class Craftory extends JavaPlugin { @@ -34,19 +36,18 @@ public final class Craftory extends JavaPlugin { private AsyncExecutionManager asyncExecutionManager; private SyncExecutionManager syncExecutionManager; private CustomBlockManager customBlockManager; + private BlockRenderManager blockRenderManager; + //External private CustomItemManager customItemManager; private RecipeManager recipeManager; - - //External API - @Getter - CustomBlockAPI customBlockAPI; - + private CustomBlockAPI customBlockAPI; public static CustomItemManager getCustomItemManager() { return instance.customItemManager; } public static RecipeManager getRecipeManager() { return instance.recipeManager; } + public static CustomBlockAPI getCustomBlockAPI() {return instance.customBlockAPI; } @Override public void onLoad() { @@ -65,6 +66,7 @@ public void onLoad() { //Custom Block injector.getSingleton(CustomBlockRegistry.class); + blockRenderManager = injector.getSingleton(BlockRenderManager.class); customBlockManager = injector.getSingleton(CustomBlockManager.class); //API @@ -80,17 +82,22 @@ public void onEnable() { //Register Events PluginManager pluginManager = getServer().getPluginManager(); + pluginManager.registerEvents(blockRenderManager, instance); pluginManager.registerEvents(injector.getSingleton(CustomBlockListener.class), instance); pluginManager.registerEvents(injector.getSingleton(WorldListener.class), instance); pluginManager.registerEvents(injector.getSingleton(ChunkListener.class), instance); pluginManager.registerEvents(injector.getSingleton(ItemEventManager.class), instance); pluginManager.registerEvents(recipeManager, instance); + //Executor asyncExecutionManager.runTaskTimer(this, 20L, 1L); syncExecutionManager.runTaskTimer(this, 20L,1L); getServer().getPluginManager().registerEvents(new ItemEventManager(), this); + AssetLinker linker = injector.getSingleton(AssetLinker.class); + linker.runTaskLater(this, 1); + //Commands PluginCommand spawnCommand = this.getCommand("spawnItem"); if(spawnCommand!=null) { diff --git a/api/src/main/java/studio/craftory/core/CraftoryAddon.java b/api/src/main/java/studio/craftory/core/CraftoryAddon.java index d6b45dd..7e156dd 100644 --- a/api/src/main/java/studio/craftory/core/CraftoryAddon.java +++ b/api/src/main/java/studio/craftory/core/CraftoryAddon.java @@ -1,4 +1,12 @@ package studio.craftory.core; +import java.net.URL; + public interface CraftoryAddon { + + URL getAddonResources(); + + default void craftoryOnEnable() { + + } } diff --git a/api/src/main/java/studio/craftory/core/annotations/CustomBlock.java b/api/src/main/java/studio/craftory/core/annotations/CustomBlock.java deleted file mode 100644 index c373ab9..0000000 --- a/api/src/main/java/studio/craftory/core/annotations/CustomBlock.java +++ /dev/null @@ -1,13 +0,0 @@ -package studio.craftory.core.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import studio.craftory.core.blocks.renders.Renderers; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.SOURCE) -public @interface CustomBlock { - Renderers[] renders() default {Renderers.BLOCK_STATE_RENDER}; -} diff --git a/api/src/main/java/studio/craftory/core/annotations/RenderData.java b/api/src/main/java/studio/craftory/core/annotations/DefaultRendersData.java similarity index 81% rename from api/src/main/java/studio/craftory/core/annotations/RenderData.java rename to api/src/main/java/studio/craftory/core/annotations/DefaultRendersData.java index edb0c3f..43dc805 100644 --- a/api/src/main/java/studio/craftory/core/annotations/RenderData.java +++ b/api/src/main/java/studio/craftory/core/annotations/DefaultRendersData.java @@ -7,12 +7,11 @@ @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) -public @interface RenderData { +public @interface DefaultRendersData { String northFacingModel() default ""; String southFacingModel() default ""; String eastFacingModel() default ""; String westFacingModel() default ""; - String upFacingModel() default ""; - String downFacingModel() default ""; String headModel() default ""; + String all() default ""; } diff --git a/api/src/main/java/studio/craftory/core/api/CustomBlockAPI.java b/api/src/main/java/studio/craftory/core/api/CustomBlockAPI.java index 04ca8a0..d591f42 100644 --- a/api/src/main/java/studio/craftory/core/api/CustomBlockAPI.java +++ b/api/src/main/java/studio/craftory/core/api/CustomBlockAPI.java @@ -7,10 +7,13 @@ import org.bukkit.plugin.Plugin; import studio.craftory.core.blocks.CustomBlockManager; import studio.craftory.core.blocks.CustomBlockRegistry; +import studio.craftory.core.blocks.rendering.CraftoryRenderer; +import studio.craftory.core.blocks.rendering.renderers.DefaultRenderer; import studio.craftory.core.blocks.templates.BaseCustomBlock; import studio.craftory.core.data.CraftoryDirection; import studio.craftory.core.data.keys.CraftoryDataKey; import studio.craftory.core.data.keys.CraftoryBlockKey; +import studio.craftory.core.resourcepack.AssetLinker; import studio.craftory.core.utils.Log; public class CustomBlockAPI { @@ -19,9 +22,18 @@ public class CustomBlockAPI { public CustomBlockRegistry blockRegister; @Inject public CustomBlockManager customBlockManager; + @Inject + public AssetLinker assetLinker; + + public void registerCustomBlock(@NonNull Plugin plugin, @NonNull Class customBlock, + @NonNull String[] textures, @NonNull Class renderer) { + CraftoryBlockKey blockKey = blockRegister.registerCustomBlockClass(plugin, customBlock); + assetLinker.registerBlockAssets(blockKey, renderer, textures); + } - public void registerCustomBlock(@NonNull Plugin plugin, @NonNull Class customBlock) { - blockRegister.registerCustomBlockClass(plugin, customBlock); + public void registerCustomBlock(@NonNull Plugin plugin, @NonNull Class customBlock, + @NonNull String[] textures) { + registerCustomBlock(plugin, customBlock, textures, DefaultRenderer.class); } public Optional placeCustomBlock(@NonNull Location location, @NonNull Class customBlockClazz, diff --git a/api/src/main/java/studio/craftory/core/blocks/BlockRenderManager.java b/api/src/main/java/studio/craftory/core/blocks/BlockRenderManager.java index 70b921f..5ba8dba 100644 --- a/api/src/main/java/studio/craftory/core/blocks/BlockRenderManager.java +++ b/api/src/main/java/studio/craftory/core/blocks/BlockRenderManager.java @@ -11,40 +11,49 @@ import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import lombok.Getter; import lombok.NonNull; import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import studio.craftory.core.Craftory; -import studio.craftory.core.blocks.renders.BlockStateRenderer; -import studio.craftory.core.blocks.renders.CraftoryRenderer; -import studio.craftory.core.blocks.renders.RenderData; -import studio.craftory.core.blocks.renders.Renderers; +import studio.craftory.core.blocks.rendering.renderers.DefaultRenderer; +import studio.craftory.core.blocks.rendering.CraftoryRenderer; +import studio.craftory.core.blocks.rendering.renderers.DefaultRotationalRenderer; +import studio.craftory.core.data.RenderData; import studio.craftory.core.data.CraftoryDirection; +import studio.craftory.core.data.events.ResourcePackBuilt; import studio.craftory.core.data.keys.CraftoryBlockKey; import studio.craftory.core.utils.Log; -public class BlockRenderManager { +public class BlockRenderManager implements Listener { private final ObjectMapper mapper; + @Getter private Map renderers = new HashMap<>(); private Map blockToRenderDataMap = new HashMap<>(); public BlockRenderManager() { mapper = new ObjectMapper(); - registerDefaultRenders(); + } + + @EventHandler + public void onResourcePackBuilt(ResourcePackBuilt event) { loadRenderData(); } private void registerDefaultRenders() { - registerRenderer(Renderers.BLOCK_STATE_RENDER, new BlockStateRenderer()); - registerRenderer(Renderers.TRANSPARENT_BLOCK_STATE_RENDER, new BlockStateRenderer()); + registerRenderer(DefaultRenderer.class); + registerRenderer(DefaultRotationalRenderer.class); } - public void registerRenderer(String key, CraftoryRenderer renderer) { - renderers.putIfAbsent(key, renderer); - } - public void registerRenderer(Renderers key, CraftoryRenderer renderer) { - registerRenderer(key.value, renderer); + public void registerRenderer(@NonNull Class renderer) { + try { + renderers.putIfAbsent(renderer.getSimpleName(), renderer.getDeclaredConstructor().newInstance()); + } catch (Exception e ) { + Log.error("Couldn't register renderer ", renderer.getName()); + } } public void renderCustomBlock(CraftoryBlockKey blockKey, Block block, CraftoryDirection direction) { diff --git a/api/src/main/java/studio/craftory/core/blocks/CustomBlockManager.java b/api/src/main/java/studio/craftory/core/blocks/CustomBlockManager.java index 1f9e766..95b9e43 100644 --- a/api/src/main/java/studio/craftory/core/blocks/CustomBlockManager.java +++ b/api/src/main/java/studio/craftory/core/blocks/CustomBlockManager.java @@ -24,24 +24,25 @@ public class CustomBlockManager { - private CustomBlockRegistry blockRegister; - private AsyncExecutionManager asyncExecutionManager; - private SyncExecutionManager syncExecutionManager; - private BlockRenderManager blockRenderManager; + private final CustomBlockRegistry blockRegister; + private final AsyncExecutionManager asyncExecutionManager; + private final SyncExecutionManager syncExecutionManager; + private final BlockRenderManager blockRenderManager; @Getter - private DataStorageManager dataStorageManager; + private final DataStorageManager dataStorageManager; @Getter - private Map> customBlocks; + private final Map> customBlocks; @Inject - public CustomBlockManager (CustomBlockRegistry blockRegister, AsyncExecutionManager asyncExecutionManager, SyncExecutionManager syncExecutionManager) { + public CustomBlockManager (CustomBlockRegistry blockRegister, AsyncExecutionManager asyncExecutionManager, + SyncExecutionManager syncExecutionManager, BlockRenderManager blockRenderManager) { this.blockRegister = blockRegister; this.syncExecutionManager = syncExecutionManager; this.asyncExecutionManager = asyncExecutionManager; - this.dataStorageManager = new DataStorageManager(this, blockRegister); - this.blockRenderManager = new BlockRenderManager(); + this.blockRenderManager = blockRenderManager; + this.dataStorageManager = new DataStorageManager(this, blockRegister); this.customBlocks = new ConcurrentHashMap<>(); } @@ -153,6 +154,20 @@ public Optional getLoadedCustomBlockAt(@NonNull final Location return Optional.ofNullable(loadedBlockInChunk.get(location)); } + /** + * Check if location contains custom block + */ + @Synchronized + public boolean containsCustomBlock(@NonNull final Location location) { + if (location.getChunk().isLoaded()) { + Map chunkData = customBlocks.get(location.getChunk()); + if (chunkData != null) { + return chunkData.containsKey(location); + } + } + return false; + } + /** * Get the CustomBlock in the given loaded chunk * diff --git a/api/src/main/java/studio/craftory/core/blocks/CustomBlockRegistry.java b/api/src/main/java/studio/craftory/core/blocks/CustomBlockRegistry.java index 6508afe..ad57b61 100644 --- a/api/src/main/java/studio/craftory/core/blocks/CustomBlockRegistry.java +++ b/api/src/main/java/studio/craftory/core/blocks/CustomBlockRegistry.java @@ -1,6 +1,6 @@ package studio.craftory.core.blocks; -import static studio.craftory.core.utils.Constants.Keys.blockItemDataKey; +import static studio.craftory.core.utils.Constants.Keys.BLOCK_ITEM_DATA_KEY; import java.lang.reflect.Constructor; import java.util.HashMap; @@ -39,7 +39,7 @@ public class CustomBlockRegistry { private final Map craftoryBlockKeyMap = new HashMap<>(); @Synchronized - public void registerCustomBlockClass(@NonNull Plugin plugin, @NonNull Class block) { + public CraftoryBlockKey registerCustomBlockClass(@NonNull Plugin plugin, @NonNull Class block) { CraftoryBlockKey craftoryBlockKey = new CraftoryBlockKey(plugin, block); if (!blockTypes.containsKey(craftoryBlockKey)) { @@ -50,7 +50,7 @@ public void registerCustomBlockClass(@NonNull Plugin plugin, @NonNull Class b registerCustomBlockTickables((Class) block); CustomItem.builder().name(craftoryBlockKey.getName()).displayName( - craftoryBlockKey.getName()).attribute(blockItemDataKey, craftoryBlockKey.toString()).material( + craftoryBlockKey.getName()).attribute(BLOCK_ITEM_DATA_KEY, craftoryBlockKey.toString()).material( Material.STONE).build().register(plugin); Log.debug("CustomBlock Register: " + block.getName()); } else { @@ -60,6 +60,7 @@ public void registerCustomBlockClass(@NonNull Plugin plugin, @NonNull Class b } else { Log.warn("Trying to re-register known key of Custom Block: " + craftoryBlockKey.getName()); } + return craftoryBlockKey; } @Synchronized diff --git a/api/src/main/java/studio/craftory/core/blocks/WorldDataStorage.java b/api/src/main/java/studio/craftory/core/blocks/WorldDataStorage.java index 88d2c5c..5a370c3 100644 --- a/api/src/main/java/studio/craftory/core/blocks/WorldDataStorage.java +++ b/api/src/main/java/studio/craftory/core/blocks/WorldDataStorage.java @@ -43,19 +43,20 @@ public WorldDataStorage(@NonNull final World world, CustomBlockRegistry blockReg this.world = world; this.blockRegister = blockRegister; this.mapper = mapper; - file = new File(world.getWorldFolder(), "craftory"); + file = new File(world.getWorldFolder(), "craftory/worldStorage.json"); setupSaveFile(); } private void setupSaveFile() { if (!file.exists()) { - file.mkdirs(); + file.getParentFile().mkdirs(); try { if(!file.createNewFile()) { Log.error("Couldn't create save file"); } } catch (IOException e) { Log.error("Couldn't create save file"); + Log.error(e.toString()); } } file = new File(file, "blocks.json"); diff --git a/api/src/main/java/studio/craftory/core/blocks/rendering/CraftoryRenderer.java b/api/src/main/java/studio/craftory/core/blocks/rendering/CraftoryRenderer.java new file mode 100644 index 0000000..821fd09 --- /dev/null +++ b/api/src/main/java/studio/craftory/core/blocks/rendering/CraftoryRenderer.java @@ -0,0 +1,12 @@ +package studio.craftory.core.blocks.rendering; + +import org.bukkit.block.Block; +import studio.craftory.core.data.RenderData; +import studio.craftory.core.data.CraftoryDirection; +import studio.craftory.core.resourcepack.BlockAssetGenerator; + +public interface CraftoryRenderer { + void render(Block block, CraftoryDirection direction, RenderData renderData); + + void generateAssets(String blockKey, String[] assetsData, BlockAssetGenerator blockAssetGenerator); +} diff --git a/api/src/main/java/studio/craftory/core/blocks/renders/BlockStateRenderer.java b/api/src/main/java/studio/craftory/core/blocks/rendering/renderers/DefaultRenderer.java similarity index 65% rename from api/src/main/java/studio/craftory/core/blocks/renders/BlockStateRenderer.java rename to api/src/main/java/studio/craftory/core/blocks/rendering/renderers/DefaultRenderer.java index c2392d2..af829a8 100644 --- a/api/src/main/java/studio/craftory/core/blocks/renders/BlockStateRenderer.java +++ b/api/src/main/java/studio/craftory/core/blocks/rendering/renderers/DefaultRenderer.java @@ -1,5 +1,7 @@ -package studio.craftory.core.blocks.renders; +package studio.craftory.core.blocks.rendering.renderers; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; import lombok.NonNull; import org.bukkit.Instrument; import org.bukkit.Material; @@ -9,22 +11,27 @@ import org.bukkit.block.data.BlockData; import org.bukkit.block.data.MultipleFacing; import org.bukkit.block.data.type.NoteBlock; +import studio.craftory.core.blocks.rendering.CraftoryRenderer; import studio.craftory.core.data.CraftoryDirection; +import studio.craftory.core.data.RenderData; +import studio.craftory.core.resourcepack.BlockAssetGenerator; import studio.craftory.core.utils.Log; -public class BlockStateRenderer implements CraftoryRenderer{ +public class DefaultRenderer implements CraftoryRenderer { @Override public void render(@NonNull Block block, @NonNull CraftoryDirection direction, @NonNull RenderData renderData) { int directionKey = direction.label; - //Must have render data for every CraftoryDirection - if (renderData.getData().size() != 6) { - Log.warn("Incomplete render data"); - return; + String data = ""; + int dataSize = renderData.getData().size(); + + if (dataSize == 6) { + data = renderData.getData().get(directionKey); + } else if (dataSize == 1) { + data = renderData.getData().get(0); } - String data = renderData.getData().get(directionKey); if (data.isEmpty()) { //Block doesn't use directions so default to NORTH data = renderData.getData().get(0); @@ -55,27 +62,45 @@ public void render(@NonNull Block block, @NonNull CraftoryDirection direction, @ } } - private void renderChorusPlant(@NonNull String stateData, Block block) { + @Override + public void generateAssets(String blockKey, String[] assetsData, BlockAssetGenerator blockAssetGenerator) { + ObjectMapper mapper = new ObjectMapper(); + + if (assetsData.length == 1 || assetsData.length == 6) { + ArrayNode renderFileData = mapper.createArrayNode(); + renderFileData.add(this.getClass().getSimpleName()); + for (int i = 0; i < assetsData.length; i++) { + String data = blockAssetGenerator.generateBlockState(); + renderFileData.add(data); + blockAssetGenerator.addBlockStateToPack(data, assetsData[i], CraftoryDirection.NORTH); + } + blockAssetGenerator.addToRenderFile(blockKey, renderFileData); + } else { + Log.warn("Bad data for asset gen"); + } + } + + protected void renderChorusPlant(@NonNull String stateData, Block block) { setType(block, Material.CHORUS_PLANT); setData(block, getMutlifacingData(stateData, block)); } - private void renderRedMushroom(@NonNull String stateData, Block block) { + protected void renderRedMushroom(@NonNull String stateData, Block block) { setType(block, Material.RED_MUSHROOM_BLOCK); setData(block, getMutlifacingData(stateData, block)); } - private void renderBrownMushroom(@NonNull String stateData, Block block) { + protected void renderBrownMushroom(@NonNull String stateData, Block block) { setType(block, Material.BROWN_MUSHROOM_BLOCK); setData(block, getMutlifacingData(stateData, block)); } - private void renderStem(@NonNull String stateData, Block block) { + protected void renderStem(@NonNull String stateData, Block block) { setType(block, Material.MUSHROOM_STEM); setData(block, getMutlifacingData(stateData, block)); } - private void renderNoteBlock(@NonNull String stateData, Block block) { + protected void renderNoteBlock(@NonNull String stateData, Block block) { String instrument = stateData.substring(0,1); int note = Integer.parseInt(stateData.substring(1,3)); String powered = stateData.substring(3,4); @@ -92,7 +117,7 @@ private void setData(@NonNull Block block, @NonNull BlockData blockData) { block.setBlockData(blockData, false); } - private BlockData getNoteBlockData(Block block, String instrument, int note, String powered) { + protected BlockData getNoteBlockData(Block block, String instrument, int note, String powered) { NoteBlock blockData = (NoteBlock) block.getBlockData(); blockData.setInstrument(getInstrument(instrument)); @@ -101,7 +126,7 @@ private BlockData getNoteBlockData(Block block, String instrument, int note, Str return blockData; } - private Instrument getInstrument(@NonNull String instrument) { + protected Instrument getInstrument(@NonNull String instrument) { switch (instrument) { case "a": return Instrument.BANJO; @@ -126,7 +151,7 @@ private Instrument getInstrument(@NonNull String instrument) { case "k": return Instrument.IRON_XYLOPHONE; case "l": - return Instrument.PIANO; + return Instrument.PLING; case "m": return Instrument.SNARE_DRUM; case "n": @@ -138,7 +163,7 @@ private Instrument getInstrument(@NonNull String instrument) { } } - private static MultipleFacing getMutlifacingData(@NonNull String stateData, Block block) { + protected static MultipleFacing getMutlifacingData(@NonNull String stateData, Block block) { MultipleFacing blockData = (MultipleFacing) block.getBlockData(); String[] states = stateData.split(""); diff --git a/api/src/main/java/studio/craftory/core/blocks/rendering/renderers/DefaultRotationalRenderer.java b/api/src/main/java/studio/craftory/core/blocks/rendering/renderers/DefaultRotationalRenderer.java new file mode 100644 index 0000000..2f831b4 --- /dev/null +++ b/api/src/main/java/studio/craftory/core/blocks/rendering/renderers/DefaultRotationalRenderer.java @@ -0,0 +1,29 @@ +package studio.craftory.core.blocks.rendering.renderers; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import studio.craftory.core.data.CraftoryDirection; +import studio.craftory.core.resourcepack.BlockAssetGenerator; +import studio.craftory.core.utils.Log; + +public class DefaultRotationalRenderer extends DefaultRenderer { + + @Override + public void generateAssets(String blockKey, String[] assetsData, BlockAssetGenerator blockAssetGenerator) { + ObjectMapper mapper = new ObjectMapper(); + + if (assetsData.length == 1) { + ArrayNode renderFileData = mapper.createArrayNode(); + renderFileData.add(this.getClass().getSimpleName()); + for (int i = 0; i < 6; i++) { + String data = blockAssetGenerator.generateBlockState(); + renderFileData.add(data); + blockAssetGenerator.addBlockStateToPack(data, assetsData[0], CraftoryDirection.valueOfLabel(i)); + } + blockAssetGenerator.addToRenderFile(blockKey, renderFileData); + } else { + Log.warn("Bad data for asset gen"); + } + } + +} diff --git a/api/src/main/java/studio/craftory/core/blocks/renders/CraftoryRenderer.java b/api/src/main/java/studio/craftory/core/blocks/renders/CraftoryRenderer.java deleted file mode 100644 index 20115fe..0000000 --- a/api/src/main/java/studio/craftory/core/blocks/renders/CraftoryRenderer.java +++ /dev/null @@ -1,8 +0,0 @@ -package studio.craftory.core.blocks.renders; - -import org.bukkit.block.Block; -import studio.craftory.core.data.CraftoryDirection; - -public interface CraftoryRenderer { - void render(Block block, CraftoryDirection direction, RenderData renderData); -} diff --git a/api/src/main/java/studio/craftory/core/blocks/renders/Renderers.java b/api/src/main/java/studio/craftory/core/blocks/renders/Renderers.java deleted file mode 100644 index 650e93f..0000000 --- a/api/src/main/java/studio/craftory/core/blocks/renders/Renderers.java +++ /dev/null @@ -1,12 +0,0 @@ -package studio.craftory.core.blocks.renders; - -public enum Renderers { - BLOCK_STATE_RENDER("b"), - TRANSPARENT_BLOCK_STATE_RENDER("t"), - ENTITY_SPAWNER_RENDER("e"), - HEAD_RENDER("h"); - - public final String value; - - Renderers(String value) { this.value = value;} -} diff --git a/api/src/main/java/studio/craftory/core/blocks/renders/RenderData.java b/api/src/main/java/studio/craftory/core/data/RenderData.java similarity index 74% rename from api/src/main/java/studio/craftory/core/blocks/renders/RenderData.java rename to api/src/main/java/studio/craftory/core/data/RenderData.java index 50b2298..33b945b 100644 --- a/api/src/main/java/studio/craftory/core/blocks/renders/RenderData.java +++ b/api/src/main/java/studio/craftory/core/data/RenderData.java @@ -1,7 +1,8 @@ -package studio.craftory.core.blocks.renders; +package studio.craftory.core.data; import java.util.List; import lombok.Getter; +import studio.craftory.core.blocks.rendering.CraftoryRenderer; public class RenderData { @Getter diff --git a/api/src/main/java/studio/craftory/core/data/events/ResourcePackBuilt.java b/api/src/main/java/studio/craftory/core/data/events/ResourcePackBuilt.java new file mode 100644 index 0000000..667491b --- /dev/null +++ b/api/src/main/java/studio/craftory/core/data/events/ResourcePackBuilt.java @@ -0,0 +1,22 @@ +package studio.craftory.core.data.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class ResourcePackBuilt extends Event { + + public ResourcePackBuilt() { + + } + + private static final HandlerList HANDLERS = new HandlerList(); + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } +} diff --git a/api/src/main/java/studio/craftory/core/executors/ExecutorUtils.java b/api/src/main/java/studio/craftory/core/executors/ExecutorUtils.java index 9498a0e..5a765f1 100644 --- a/api/src/main/java/studio/craftory/core/executors/ExecutorUtils.java +++ b/api/src/main/java/studio/craftory/core/executors/ExecutorUtils.java @@ -11,6 +11,7 @@ import lombok.experimental.UtilityClass; import studio.craftory.core.annotations.Tickable; import studio.craftory.core.blocks.templates.BaseCustomBlock; +import studio.craftory.core.utils.Log; import studio.craftory.core.utils.Reflections; @UtilityClass @@ -53,7 +54,7 @@ public static void runMethods(@NonNull Set tickGroups, @NonNull int t try { method.invoke(tickable); } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); + Log.error(e.toString()); } } } diff --git a/api/src/main/java/studio/craftory/core/items/ItemEventManager.java b/api/src/main/java/studio/craftory/core/items/ItemEventManager.java index 4cbbd8f..306f85c 100644 --- a/api/src/main/java/studio/craftory/core/items/ItemEventManager.java +++ b/api/src/main/java/studio/craftory/core/items/ItemEventManager.java @@ -22,6 +22,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.potion.PotionEffect; +import studio.craftory.core.utils.Log; public class ItemEventManager implements Listener { @@ -85,7 +86,7 @@ private void handleSmartEvent(Event event) { try { smartEvents.get(itemSmartEvent).get(triggerItemName).accept(event); } catch (Exception e) { - e.printStackTrace(); + Log.error(e.toString()); } } } diff --git a/api/src/main/java/studio/craftory/core/listeners/CustomBlockListener.java b/api/src/main/java/studio/craftory/core/listeners/CustomBlockListener.java index 50a7dd7..da7ea9f 100644 --- a/api/src/main/java/studio/craftory/core/listeners/CustomBlockListener.java +++ b/api/src/main/java/studio/craftory/core/listeners/CustomBlockListener.java @@ -2,21 +2,26 @@ import java.util.Optional; import javax.inject.Inject; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockFadeEvent; +import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; -import studio.craftory.core.items.CustomItemUtils; import studio.craftory.core.blocks.CustomBlockManager; import studio.craftory.core.blocks.CustomBlockRegistry; import studio.craftory.core.blocks.templates.BaseCustomBlock; import studio.craftory.core.data.CraftoryDirection; import studio.craftory.core.data.keys.CraftoryBlockKey; +import studio.craftory.core.items.CustomItemUtils; import studio.craftory.core.utils.Constants.Keys; import studio.craftory.core.utils.Log; @@ -34,11 +39,11 @@ public void onCustomBlockPlace(BlockPlaceEvent blockPlaceEvent) { ItemStack itemStack = blockPlaceEvent.getItemInHand(); CustomItemUtils.validateItemStackMeta(itemStack); PersistentDataContainer dataHolder = itemStack.getItemMeta().getPersistentDataContainer(); - if (!dataHolder.has(Keys.blockItemKey, PersistentDataType.STRING)) return; + if (!dataHolder.has(Keys.BLOCK_ITEM_KEY, PersistentDataType.STRING)) return; //Get Custom Block Data CraftoryDirection direction = getDirection(blockPlaceEvent.getPlayer()); - String blockKey = dataHolder.get(Keys.blockItemKey, PersistentDataType.STRING); + String blockKey = dataHolder.get(Keys.BLOCK_ITEM_KEY, PersistentDataType.STRING); Optional blockKeyOptional = blockRegistry.getBlockKey(blockKey); if (blockKeyOptional.isPresent()) { @@ -62,4 +67,33 @@ private CraftoryDirection getDirection(Player player) { if (degrees <= 225) return CraftoryDirection.SOUTH; return CraftoryDirection.WEST; } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onCustomBlockPhysics(BlockPhysicsEvent event) { + Material type = event.getChangedType(); + if ((type == Material.MUSHROOM_STEM || type == Material.BROWN_MUSHROOM_BLOCK || type == Material.RED_MUSHROOM_BLOCK + || type == Material.NOTE_BLOCK) && customBlockManager.containsCustomBlock(event.getBlock().getLocation())) { + event.setCancelled(true); + event.getBlock().getState().update(true, false); + } + } + + @EventHandler + public void onNoteBlockTwo(BlockFadeEvent e) { + if (e.getBlock().getType() != Material.GRASS_BLOCK) return; + for (BlockFace face : BlockFace.values()) { + if (e.getBlock().getRelative(face).getType() == Material.NOTE_BLOCK && customBlockManager.containsCustomBlock(e.getBlock().getRelative(face).getLocation())) { + e.setCancelled(true); + e.getBlock().setType(Material.DIRT, false); + return; + } + } + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onNoteBlockInteract(PlayerInteractEvent event) { + if (event.hasBlock() && event.getClickedBlock().getType() == Material.NOTE_BLOCK && customBlockManager.containsCustomBlock(event.getClickedBlock().getLocation())) { + event.setCancelled(true); + } + } } diff --git a/api/src/main/java/studio/craftory/core/processors/CustomBlockProcessor.java b/api/src/main/java/studio/craftory/core/processors/CustomBlockProcessor.java index c9fc048..85c7a51 100644 --- a/api/src/main/java/studio/craftory/core/processors/CustomBlockProcessor.java +++ b/api/src/main/java/studio/craftory/core/processors/CustomBlockProcessor.java @@ -1,111 +1,102 @@ -/**package studio.craftory.core.processors; - -import com.google.auto.service.AutoService; -import com.squareup.javapoet.JavaFile; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.TypeSpec; -import java.io.Writer; -import java.util.Set; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.Filer; -import javax.annotation.processing.Messager; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.Processor; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.annotation.processing.SupportedSourceVersion; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; -import javax.tools.Diagnostic.Kind; -import javax.tools.JavaFileObject; -import lombok.SneakyThrows; -import studio.craftory.core.annotations.CustomBlock; - -@SupportedAnnotationTypes("studio.craftory.core.annotations.CustomBlock") -@SupportedSourceVersion(SourceVersion.RELEASE_8) -@AutoService(Processor.class) -public class CustomBlockProcessor extends AbstractProcessor { - - private Types typeUtils; - private Elements elementUtils; - private Filer filer; - private Messager messager; - - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - super.init(processingEnv); - typeUtils = processingEnv.getTypeUtils(); - elementUtils = processingEnv.getElementUtils(); - filer = processingEnv.getFiler(); - messager = processingEnv.getMessager(); - } - - @SneakyThrows - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - messager.printMessage(Kind.MANDATORY_WARNING, "asd"); - for (TypeElement annotation : annotations) { - for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(annotation)) { - messager.printMessage(Kind.MANDATORY_WARNING, annotatedElement.getSimpleName()); - } - } - for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(CustomBlock.class)) { - messager.printMessage(Kind.MANDATORY_WARNING, "test"); - if (annotatedElement.getKind() == ElementKind.CLASS) { - TypeElement typeElement = (TypeElement) annotatedElement; - if (isValidClass(typeElement)) { - messager.printMessage(Kind.MANDATORY_WARNING, typeElement.getQualifiedName().toString()); - MethodSpec register = MethodSpec.methodBuilder("register") - .addModifiers(Modifier.PUBLIC) - .returns(void.class) - .addStatement("Craftory.registerCustomBlock(Class.forName(\""+typeElement.getQualifiedName().toString()+"\"))") - .build(); - - TypeSpec registerClass = TypeSpec - .classBuilder("RegisterUtils") - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addMethod(register) - .build(); - - JavaFile.builder("com.test", registerClass) - .build() - .writeTo(filer); - } - } - } - return true; - } - - private boolean isValidClass(TypeElement blockElement) { - - //Check class is public - if (!blockElement.getModifiers().contains(Modifier.PUBLIC)) { - return false; - } - - //Check class is not abstract - if (blockElement.getModifiers().contains(Modifier.ABSTRACT)) { - return false; - } - - for (Element enclosed : blockElement.getEnclosedElements()) { - if (enclosed.getKind() == ElementKind.CONSTRUCTOR) { - ExecutableElement consturctorElement = (ExecutableElement) enclosed; - if (consturctorElement.getParameters().size() == 2 && consturctorElement.getModifiers().contains(Modifier.PUBLIC)) { - messager.printMessage(Kind.NOTE, "Testasda"); - messager.printMessage(Kind.NOTE, consturctorElement.getParameters().get(0).asType().toString()); - return true; - } - } - } - - return false; - } -} -**/ \ No newline at end of file +//package studio.craftory.core.processors; +// +//import com.google.auto.service.AutoService; +//import com.squareup.javapoet.JavaFile; +//import com.squareup.javapoet.MethodSpec; +//import com.squareup.javapoet.TypeSpec; +//import com.squareup.javapoet.TypeSpec.Builder; +//import java.io.Writer; +//import java.util.Set; +//import javax.annotation.processing.AbstractProcessor; +//import javax.annotation.processing.Filer; +//import javax.annotation.processing.Messager; +//import javax.annotation.processing.ProcessingEnvironment; +//import javax.annotation.processing.Processor; +//import javax.annotation.processing.RoundEnvironment; +//import javax.annotation.processing.SupportedAnnotationTypes; +//import javax.annotation.processing.SupportedSourceVersion; +//import javax.lang.model.SourceVersion; +//import javax.lang.model.element.Element; +//import javax.lang.model.element.ElementKind; +//import javax.lang.model.element.ExecutableElement; +//import javax.lang.model.element.Modifier; +//import javax.lang.model.element.TypeElement; +//import javax.lang.model.util.Elements; +//import javax.lang.model.util.Types; +//import javax.tools.Diagnostic.Kind; +//import javax.tools.JavaFileObject; +//import lombok.SneakyThrows; +//import studio.craftory.core.Craftory; +//import studio.craftory.core.annotations.CustomBlock; +// +//@SupportedAnnotationTypes("studio.craftory.core.annotations.CustomBlock") +//@SupportedSourceVersion(SourceVersion.RELEASE_8) +//@AutoService(Processor.class) +//public class CustomBlockProcessor extends AbstractProcessor { +// +// private Types typeUtils; +// private Elements elementUtils; +// private Filer filer; +// private Messager messager; +// +// @Override +// public synchronized void init(ProcessingEnvironment processingEnv) { +// super.init(processingEnv); +// typeUtils = processingEnv.getTypeUtils(); +// elementUtils = processingEnv.getElementUtils(); +// filer = processingEnv.getFiler(); +// messager = processingEnv.getMessager(); +// } +// +// @SneakyThrows +// @Override +// public boolean process(Set annotations, RoundEnvironment roundEnv) { +// Builder registerClassBuilder = TypeSpec.classBuilder("RegisterUtils").addModifiers(Modifier.PUBLIC, Modifier.FINAL); +// MethodSpec.Builder registerMethodBuilder = MethodSpec.methodBuilder("register").addModifiers(Modifier.PUBLIC).returns(void.class); +// +// for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(CustomBlock.class)) { +// if (annotatedElement.getKind() == ElementKind.CLASS) { +// TypeElement typeElement = (TypeElement) annotatedElement; +// if (isValidClass(typeElement)) { +// messager.printMessage(Kind.MANDATORY_WARNING, typeElement.getQualifiedName().toString()); +// registerMethodBuilder.addStatement("$T.getCustomBlockAPI().registerCustomBlock($T.getInstance(), " +// +elementUtils.getBinaryName(typeElement)+".class)", Craftory.class); +// } +// } +// } +// +// registerClassBuilder.addMethod(registerMethodBuilder.build()); +// TypeSpec registerClass = registerClassBuilder.build(); +// +// JavaFile.builder("com.test", registerClass) +// .build() +// .writeTo(filer); +// return true; +// } +// +// private boolean isValidClass(TypeElement blockElement) { +// +// //Check class is public +// if (!blockElement.getModifiers().contains(Modifier.PUBLIC)) { +// return false; +// } +// +// //Check class is not abstract +// if (blockElement.getModifiers().contains(Modifier.ABSTRACT)) { +// return false; +// } +// +// for (Element enclosed : blockElement.getEnclosedElements()) { +// if (enclosed.getKind() == ElementKind.CONSTRUCTOR) { +// ExecutableElement consturctorElement = (ExecutableElement) enclosed; +// if (consturctorElement.getParameters().size() == 2 && consturctorElement.getModifiers().contains(Modifier.PUBLIC)) { +// messager.printMessage(Kind.NOTE, "Testasda"); +// messager.printMessage(Kind.NOTE, consturctorElement.getParameters().get(0).asType().toString()); +// return true; +// } +// } +// } +// +// return false; +// } +//} \ No newline at end of file diff --git a/api/src/main/java/studio/craftory/core/resourcepack/AssetLinker.java b/api/src/main/java/studio/craftory/core/resourcepack/AssetLinker.java new file mode 100644 index 0000000..4f03ca0 --- /dev/null +++ b/api/src/main/java/studio/craftory/core/resourcepack/AssetLinker.java @@ -0,0 +1,54 @@ +package studio.craftory.core.resourcepack; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import javax.inject.Inject; +import lombok.NonNull; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitRunnable; +import studio.craftory.core.Craftory; +import studio.craftory.core.blocks.BlockRenderManager; +import studio.craftory.core.blocks.rendering.CraftoryRenderer; +import studio.craftory.core.data.events.ResourcePackBuilt; +import studio.craftory.core.data.keys.CraftoryBlockKey; + +public class AssetLinker extends BukkitRunnable { + + private Map, Map> assetsToGenerate = new HashMap<>(); + private BlockAssetGenerator blockAssetGenerator = new BlockAssetGenerator(); + + @Inject + private BlockRenderManager blockRenderManager; + + @Override + public void run() { + //Need better system later + if (!Files.exists(Paths.get(Craftory.getInstance().getDataFolder() + "/resourcepacks"))) { + ResourcePackBuilder.run(); + linkCustomBlockAssets(); + } + ResourcePackBuilt builtEvent = new ResourcePackBuilt(); + Bukkit.getPluginManager().callEvent(builtEvent); + } + + public void registerBlockAssets(@NonNull CraftoryBlockKey blockKey, Class renderer, @NonNull String[] textures) { + assetsToGenerate.computeIfAbsent(renderer, k -> new HashMap<>()).put(blockKey.toString(), textures); + } + + + + private void linkCustomBlockAssets() { + for (Entry, Map> rendererAssets : assetsToGenerate.entrySet()) { + CraftoryRenderer renderer = blockRenderManager.getRenderers().get(rendererAssets.getKey().getSimpleName()); + + for (Entry blockAssets : rendererAssets.getValue().entrySet()) { + renderer.generateAssets(blockAssets.getKey(), blockAssets.getValue(), blockAssetGenerator); + } + } + blockAssetGenerator.writeRenderDataFile(); + } +} + diff --git a/api/src/main/java/studio/craftory/core/resourcepack/BlockAssetGenerator.java b/api/src/main/java/studio/craftory/core/resourcepack/BlockAssetGenerator.java new file mode 100644 index 0000000..99e6b84 --- /dev/null +++ b/api/src/main/java/studio/craftory/core/resourcepack/BlockAssetGenerator.java @@ -0,0 +1,288 @@ +package studio.craftory.core.resourcepack; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import lombok.NonNull; +import studio.craftory.core.Craftory; +import studio.craftory.core.data.CraftoryDirection; +import studio.craftory.core.utils.Log; + +public class BlockAssetGenerator { + + public static final String NOTE_BLOCK = "note_block"; + public static final String MUSHROOM_STEM = "mushroom_stem"; + public static final String BROWN_MUSHROOM_BLOCK = "brown_mushroom_block"; + public static final String RED_MUSHROOM_BLOCK = "red_mushroom_block"; + private ArrayList blocksToUse = new ArrayList<>(); + private final ArrayList resourcePacks = new ArrayList<>(Arrays.asList("low", "normal", "high")); + ObjectMapper mapper = new ObjectMapper(); + ObjectNode renderDataFile = mapper.createObjectNode(); + File file = new File(Craftory.getInstance().getDataFolder(), "renderData.json"); + + public BlockAssetGenerator() { + try { + renderDataFile = (ObjectNode) mapper.readTree(file); + } catch (IOException e) { + Log.debug("Couldn't read render data while generating assets"); + } + //Should be read from config file and generated + blocksToUse.add(new GenerationData(750, "a00T", NOTE_BLOCK)); + blocksToUse.add(new GenerationData(64, "0", MUSHROOM_STEM)); + blocksToUse.add(new GenerationData(64, "0", BROWN_MUSHROOM_BLOCK)); + blocksToUse.add(new GenerationData(64, "0", RED_MUSHROOM_BLOCK)); + } + + public void writeRenderDataFile() { + try { + mapper.writeValue(file, renderDataFile); + } catch (IOException e) { + Log.warn("Couldn't write render data"); + } + } + + public void addToRenderFile(String blockKey, ArrayNode renderFileData) { + renderDataFile.set(blockKey, renderFileData); + } + + public String generateBlockState() { + GenerationData generationData = blocksToUse.get(0); + switch (generationData.getBlockName()) { + case MUSHROOM_STEM: + return generateMushroomState(generationData, "s"); + case BROWN_MUSHROOM_BLOCK: + return generateMushroomState(generationData, "b"); + case RED_MUSHROOM_BLOCK: + return generateMushroomState(generationData, "r"); + case NOTE_BLOCK: + return generateNoteBlockState(generationData); + default: + return ""; + } + } + + public void addBlockStateToPack(String state, String asset, CraftoryDirection direction) { + String blockType = state.substring(0, 1); + String stateData = state.substring(1); + + switch (blockType) { + case "s": + addMushroomToPack(stateData, asset, getAllBlockStateFiles(MUSHROOM_STEM), direction); + break; + case "b": + addMushroomToPack(stateData, asset, getAllBlockStateFiles(BROWN_MUSHROOM_BLOCK), direction); + break; + case "n": + addNoteblockToPack(stateData, asset, getAllBlockStateFiles(NOTE_BLOCK), direction); + break; + case "r": + addMushroomToPack(stateData, asset, getAllBlockStateFiles(RED_MUSHROOM_BLOCK), direction); + break; + case "c": + + break; + default: + Log.warn("No render type found"); + break; + } + } + + private ArrayList getAllBlockStateFiles(String blockstateName) { + ArrayList paths = new ArrayList<>(); + for (String pack : resourcePacks) { + Path blockstatePath = Paths.get(Craftory.getInstance().getDataFolder() + + "/resourcepacks/" + pack + "/assets/minecraft/blockstates/" + blockstateName + ".json"); + if (!Files.exists(blockstatePath)) { + try { + Files.createDirectories(blockstatePath.getParent()); + Files.createFile(blockstatePath); + } catch (IOException e) { + Log.error(e.toString()); + } + } + paths.add(blockstatePath); + } + return paths; + } + + private void addNoteblockToPack(String state, String asset, ArrayList paths, CraftoryDirection direction) { + for (Path path : paths) { + if (Files.exists(path) && Files.isRegularFile(path)) { + try { + JsonNode node = mapper.readTree(path.toFile()); + if (!node.isObject()) { + node = mapper.createObjectNode(); + } + + ObjectNode noteblockState = mapper.createObjectNode(); + noteblockState.put("model", asset); + addDirectionData(noteblockState, direction); + + StringBuilder builder = new StringBuilder(); + builder.append("instrument="); + builder.append(getInstrument(state.substring(0,1))); + builder.append(",note="); + builder.append(Integer.parseInt(state.substring(1,3))); + builder.append(",powered="); + builder.append(mapBoolean(state.charAt(3))); + + ((ObjectNode) node.with("variants")).set(builder.toString(), noteblockState); + + mapper.writeValue(path.toFile(), node); + } catch (IOException e) { + Log.error(e.toString()); + } + } + } + } + + private String getInstrument(@NonNull String instrument) { + switch (instrument) { + case "a": + return "banjo"; + case "b": + return "basedrum"; + case "c": + return "bass"; + case "d" : + return "bell"; + case "e": + return "bit"; + case "f": + return "chime"; + case "g": + return "cow_bell"; + case "h": + return "didgeridoo"; + case "i": + return "flute"; + case "j": + return "guitar"; + case "k": + return "iron_xylophone"; + case "l": + return "pling"; + case "m": + return "snare"; + case "n": + return "hat"; + case "o": + return "xylophone"; + default: + return "error"; + } + } + + private void addDirectionData(ObjectNode node, CraftoryDirection direction) { + if (direction != CraftoryDirection.WEST) { + switch (direction) { + case NORTH: + node.put("y", 90); + break; + case SOUTH: + node.put("y", 270); + break; + case EAST: + node.put("y", 180); + break; + case UP: + node.put("x", 90); + break; + case DOWN: + node.put("x", 270); + break; + default: + break; + } + } + } + + private void addMushroomToPack(String state, String asset, ArrayList paths, CraftoryDirection direction) { + for (Path path : paths) { + if (Files.exists(path) && Files.isRegularFile(path)) { + try { + JsonNode node = mapper.readTree(path.toFile()); + + ObjectNode mushroomState = mapper.createObjectNode(); + mushroomState.with("when").put("east", mapBoolean(state.charAt(0))); + mushroomState.with("when").put("down", mapBoolean(state.charAt(1))); + mushroomState.with("when").put("north", mapBoolean(state.charAt(2))); + mushroomState.with("when").put("south", mapBoolean(state.charAt(3))); + mushroomState.with("when").put("up", mapBoolean(state.charAt(4))); + mushroomState.with("when").put("west", mapBoolean(state.charAt(5))); + mushroomState.with("apply").put("model", asset); + addDirectionData(mushroomState.with("apply"), direction); + + ArrayNode multipartNode = node.withArray("multipart"); + multipartNode.add(mushroomState); + + mapper.writeValue(path.toFile(), node); + } catch (IOException e) { + Log.error(e.toString()); + } + + + } + } + } + + private String mapBoolean(char booleanChar) { + if (booleanChar == 'T') { + return "true"; + } + return "false"; + } + + private String generateNoteBlockState(GenerationData generationData) { + String result = "n"+generationData.getData(); + char instrument = generationData.getData().charAt(0); + instrument += 1; + int note = Integer.parseInt(generationData.getData().substring(1,3)); + String powered = generationData.getData().substring(3,4); + + if (instrument == 'o' && note < 24) { + instrument = 'a'; + note += 1; + } else if (instrument == 'o' && note == 24) { + instrument = 'a'; + note = 0; + powered = "F"; + } + + String blockData = "" + instrument + ("00"+note).substring(String.valueOf(note).length()) + powered; + decreaseGenerationData(generationData, blockData); + + return result; + } + + private String generateMushroomState(GenerationData generationData, String block) { + StringBuilder result = new StringBuilder(); + result.append(block); + for (int i = 0; i < 6; i++) { + result.append((Integer.parseInt(generationData.getData()) & 0x1 << i) != 0 ? "T" : "F"); + } + + String blockData = String.valueOf(Integer.parseInt(generationData.getData()) - 1); + decreaseGenerationData(generationData, blockData); + + return result.toString(); + } + + private void decreaseGenerationData(GenerationData generationData, String blockData) { + if (generationData.getAmountLeft() != 0) { + generationData.setAmountLeft(generationData.getAmountLeft() - 1); + generationData.setData(blockData); + } else { + blocksToUse.remove(0); + } + } + +} diff --git a/api/src/main/java/studio/craftory/core/resourcepack/GenerationData.java b/api/src/main/java/studio/craftory/core/resourcepack/GenerationData.java new file mode 100644 index 0000000..7028945 --- /dev/null +++ b/api/src/main/java/studio/craftory/core/resourcepack/GenerationData.java @@ -0,0 +1,14 @@ +package studio.craftory.core.resourcepack; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class GenerationData { + private int amountLeft; + private String data; + private String blockName; +} diff --git a/api/src/main/java/studio/craftory/core/resourcepack/ResourcePackBuilder.java b/api/src/main/java/studio/craftory/core/resourcepack/ResourcePackBuilder.java new file mode 100644 index 0000000..7dc2bb8 --- /dev/null +++ b/api/src/main/java/studio/craftory/core/resourcepack/ResourcePackBuilder.java @@ -0,0 +1,112 @@ +package studio.craftory.core.resourcepack; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.File; +import java.io.IOException; +import java.util.Iterator; +import java.util.Optional; +import lombok.experimental.UtilityClass; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import studio.craftory.core.CraftoryAddon; +import studio.craftory.core.utils.Constants.ResourcePack; +import studio.craftory.core.utils.FileUtils; +import studio.craftory.core.utils.Log; + +@UtilityClass +public class ResourcePackBuilder { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public static void run() { + File tempDirectory = new File(ResourcePack.TEMP_PATH); + tempDirectory.mkdirs(); + + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + if (CraftoryAddon.class.isAssignableFrom(plugin.getClass())) { + + File assetDirectory = new File(ResourcePack.ASSETS_PATH, plugin.getName()); + assetDirectory.mkdirs(); + File zipFile = new File(tempDirectory, plugin.getName() + ".zip"); + + try { + if (!zipFile.createNewFile()) { + Log.debug("Couldn't create resource pack zip file, as already existed"); + } + } catch (IOException e) { + Log.error(e.toString()); + } + + FileUtils.downloadResource(((CraftoryAddon) plugin).getAddonResources(), zipFile); + FileUtils.unZip(zipFile, assetDirectory); + FileUtils.copyResources(assetDirectory.getAbsolutePath(), new File(ResourcePack.RESOURCE_PACK_PATH).getAbsolutePath(), + (source, dest) -> mergeResources(source, dest)); + + FileUtils.recursiveDirectoryDelete(ResourcePack.ASSETS_PATH); + } + } + FileUtils.recursiveDirectoryDelete(ResourcePack.TEMP_PATH); + } + + private static void mergeResources(File source, File dest) { + Optional fileExtensionOptional = getExtension(dest.getName()); + if (!fileExtensionOptional.isPresent()) { + Log.warn("Unknown file in resource pack", dest.getName()); + return; + } + + switch (fileExtensionOptional.get()) { + case "png": + case "ogg": + case "mcmeta": + Log.warn("Can't merge file " + dest.getName()); + break; + case "json": + mergeJSON(source, dest); + break; + default: + break; + } + } + + private static void mergeJSON(File source, File dest) { + try { + JsonNode sourceNode = objectMapper.readTree(source); + JsonNode destNode = objectMapper.readTree(dest); + objectMapper.writeValue(dest, merge(destNode, sourceNode)); + } catch (IOException e) { + Log.error(e.toString()); + } + } + + private static JsonNode merge(JsonNode mainNode, JsonNode updateNode) { + Iterator fieldNames = updateNode.fieldNames(); + while (fieldNames.hasNext()) { + + String fieldName = fieldNames.next(); + JsonNode jsonNode = mainNode.get(fieldName); + // if field exists and is an embedded object + if (jsonNode != null && jsonNode.isObject()) { + merge(jsonNode, updateNode.get(fieldName)); + } + else { + if (mainNode instanceof ObjectNode) { + // Overwrite field + JsonNode value = updateNode.get(fieldName); + ((ObjectNode) mainNode).set(fieldName, value); + } + } + + } + + return mainNode; + } + + private static Optional getExtension(String filename) { + return Optional.ofNullable(filename) + .filter(f -> f.contains(".")) + .map(f -> f.substring(filename.lastIndexOf(".") + 1)); + } +} diff --git a/api/src/main/java/studio/craftory/core/utils/Constants.java b/api/src/main/java/studio/craftory/core/utils/Constants.java index 7c1e769..87095e1 100644 --- a/api/src/main/java/studio/craftory/core/utils/Constants.java +++ b/api/src/main/java/studio/craftory/core/utils/Constants.java @@ -9,11 +9,11 @@ @UtilityClass public class Constants { - @UtilityClass public static class Keys { + private Keys(){} - public static final NamespacedKey blockItemKey = new NamespacedKey(Craftory.getInstance(), "blockItemKey"); - public static final ItemDataKey blockItemDataKey = new ItemDataKey(blockItemKey, PersistentDataType.STRING); + public static final NamespacedKey BLOCK_ITEM_KEY = new NamespacedKey(Craftory.getInstance(), "blockItemKey"); + public static final ItemDataKey BLOCK_ITEM_DATA_KEY = new ItemDataKey(BLOCK_ITEM_KEY, PersistentDataType.STRING); public static final NamespacedKey ITEM_NAME_NAMESPACED_KEY = new NamespacedKey(Craftory.getInstance(), "CUSTOM_ITEM_NAME"); public static final NamespacedKey CHARGE_NAMESPACED_KEY = new NamespacedKey(Craftory.getInstance(), "CHARGE"); @@ -21,4 +21,12 @@ public static class Keys { } + public static class ResourcePack { + private ResourcePack(){} + + public static final String RESOURCE_PACK_PATH = Craftory.getInstance().getDataFolder() +"/resourcepacks"; + public static final String ASSETS_PATH = Craftory.getInstance().getDataFolder() + "/assets"; + public static final String TEMP_PATH = Craftory.getInstance().getDataFolder() + "/temp"; + } + } diff --git a/api/src/main/java/studio/craftory/core/utils/FileUtils.java b/api/src/main/java/studio/craftory/core/utils/FileUtils.java new file mode 100644 index 0000000..96ba1d3 --- /dev/null +++ b/api/src/main/java/studio/craftory/core/utils/FileUtils.java @@ -0,0 +1,112 @@ +package studio.craftory.core.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Comparator; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import lombok.experimental.UtilityClass; + +@UtilityClass +public class FileUtils { + public void copyResources(String sourceDirectory, String destinationDirectory, MergeAction mergeAction) { + try (Stream stream = Files.walk(Paths.get(sourceDirectory))){ + stream.forEach(source -> { + Path destination = Paths.get(destinationDirectory, source.toString().substring(sourceDirectory.length())); + + if (Files.exists(destination) && !Files.isDirectory(destination)) { + mergeAction.merge(source.toFile(), destination.toFile()); + } else { + try { + Files.copy(source, destination); + } catch (IOException e) { + Log.warn("Unable to copy file ", source.toString(), " to location ", destination.toString()); + } + } + }); + } catch (IOException e) { + Log.error(e.toString()); + } + } + + public void downloadResource(URL url, File localFilename) { + try (ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream()); + FileOutputStream fileOutputStream = new FileOutputStream(localFilename); FileChannel fileChannel = fileOutputStream.getChannel()) { + + fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE); + } catch (IOException fileNotFoundException) { + Log.error(fileNotFoundException.toString()); + } + } + + public void unZip(File input, File outputDirectory) { + byte[] buffer = new byte[1024]; + try (ZipInputStream zis = new ZipInputStream(new FileInputStream(input))){ + ZipEntry zipEntry = zis.getNextEntry(); + + while (zipEntry != null) { + File newFile = newFile(outputDirectory, zipEntry); + if (zipEntry.isDirectory()) { + if (!newFile.isDirectory() && !newFile.mkdirs()) { + throw new IOException("Failed to create directory " + newFile); + } + } else { + // fix for Windows-created archives + File parent = newFile.getParentFile(); + if (!parent.isDirectory() && !parent.mkdirs()) { + throw new IOException("Failed to create directory " + parent); + } + + // write file content + try (FileOutputStream fos = new FileOutputStream(newFile)) { + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + } + } + zipEntry = zis.getNextEntry(); + } + + } catch (IOException e) { + Log.warn(e.toString()); + } + } + + private static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException { + File destFile = new File(destinationDir, zipEntry.getName()); + + String destDirPath = destinationDir.getCanonicalPath(); + String destFilePath = destFile.getCanonicalPath(); + + if (!destFilePath.startsWith(destDirPath + File.separator)) { + throw new IOException("Entry is outside of the target dir: " + zipEntry.getName()); + } + + return destFile; + } + + public void recursiveDirectoryDelete(String directory) { + try (Stream stream = Files.walk(Paths.get(directory))){ + stream.sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + } catch (IOException e) { + Log.warn("Couldn't delete directory: " + directory); + } + } + + public interface MergeAction { + void merge(File source, File dest); + } +} diff --git a/api/src/main/java/studio/craftory/core/utils/Log.java b/api/src/main/java/studio/craftory/core/utils/Log.java index a421cca..f0b8f3e 100644 --- a/api/src/main/java/studio/craftory/core/utils/Log.java +++ b/api/src/main/java/studio/craftory/core/utils/Log.java @@ -25,7 +25,7 @@ public final class Log { public static void info(@NonNull String... logMessages) { for (String logMessage : logMessages) { - logger.info(PREFIX + INFO_COLOR + logMessage); + logger.info(INFO_COLOR + logMessage); } } @@ -51,7 +51,7 @@ public static void warn(@NonNull String... logMessages) { public static void error(@NonNull String... logMessages) { for (String logMessage : logMessages) { - logger.severe(ERROR_COLOR + PREFIX +logMessage); + logger.severe(ERROR_COLOR +logMessage); } } diff --git a/api/src/main/resources/plugin.yml b/api/src/main/resources/plugin.yml index bb3edb7..2be0644 100644 --- a/api/src/main/resources/plugin.yml +++ b/api/src/main/resources/plugin.yml @@ -3,7 +3,6 @@ version: ${project.version} main: studio.craftory.core.Craftory api-version: 1.16 prefix: Craftory Core -load: STARTUP authors: [ BrettSaunders, MattyJones ] description: Plugin Extended Framework website: craftory.studio diff --git a/example/pom.xml b/example/pom.xml index 0842927..6c0300d 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -18,6 +18,7 @@ craftorystudios_Craftory_Example craftorystudios https://sonarcloud.io + true diff --git a/example/src/main/java/studio/craftory/craftoryexample/CraftoryExamplePlugin.java b/example/src/main/java/studio/craftory/craftoryexample/CraftoryExamplePlugin.java index 568ef33..e5f01ce 100644 --- a/example/src/main/java/studio/craftory/craftoryexample/CraftoryExamplePlugin.java +++ b/example/src/main/java/studio/craftory/craftoryexample/CraftoryExamplePlugin.java @@ -1,5 +1,7 @@ package studio.craftory.craftoryexample; +import java.net.MalformedURLException; +import java.net.URL; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -10,12 +12,14 @@ import org.bukkit.potion.PotionEffectType; import studio.craftory.core.Craftory; import studio.craftory.core.CraftoryAddon; +import studio.craftory.core.blocks.rendering.renderers.DefaultRotationalRenderer; import studio.craftory.core.data.keys.ItemDataKey; import studio.craftory.core.items.CustomItem; import studio.craftory.core.recipes.ShapedCraftingRecipe; import studio.craftory.core.recipes.ShapelessCraftingRecipe; +import studio.craftory.core.utils.Log; +import studio.craftory.craftoryexample.blocks.CopperOre; import studio.craftory.craftoryexample.blocks.SimpleGenerator; -import studio.craftory.craftoryexample.commands.SpawnGeneratorCommand; import studio.craftory.craftoryexample.items.Wrench; public final class CraftoryExamplePlugin extends JavaPlugin implements CraftoryAddon { @@ -26,9 +30,12 @@ public void onLoad() { /* Custom Item */ ItemDataKey magicalPower = new ItemDataKey(new NamespacedKey(this, "magical-power"), PersistentDataType.INTEGER); - CustomItem wrench = CustomItem.builder().name("wrench").unbreakable(true).attackDamage(1).handler(PlayerInteractEvent.class, - Wrench::onClick).displayName("Wrench").material(Material.STICK).displayNameColour(ChatColor.AQUA) - .holdEffect(PotionEffectType.SPEED.createEffect(Integer.MAX_VALUE,1)).attribute(magicalPower, 100).build(); + CustomItem wrench = CustomItem.builder() + .name("wrench").unbreakable(true) + .attackDamage(1).handler(PlayerInteractEvent.class, Wrench::onClick) + .displayName("Wrench").material(Material.STICK) + .displayNameColour(ChatColor.AQUA).holdEffect(PotionEffectType.SPEED.createEffect(Integer.MAX_VALUE,1)) + .attribute(magicalPower, 100).build(); wrench.register(this); ItemStack res = wrench.getItem(); res.setAmount(6); @@ -49,8 +56,20 @@ public void onLoad() { @Override public void onEnable() { - Craftory.getInstance().getCustomBlockAPI().registerCustomBlock(this, SimpleGenerator.class); - this.getCommand("simplegen").setExecutor(new SpawnGeneratorCommand()); + String[] test = {"custom/block/machine/generator_n"}; + Craftory.getCustomBlockAPI().registerCustomBlock(this, SimpleGenerator.class, test, DefaultRotationalRenderer.class); + + String[] test1 = {"custom/block/mineral/copper/copper_ore"}; + Craftory.getCustomBlockAPI().registerCustomBlock(this, CopperOre.class, test1); } + @Override + public URL getAddonResources() { + try { + return new URL("https://www.dropbox.com/s/l6q9uevu2cjpcju/CraftoryCore.zip?raw=1"); + } catch (MalformedURLException e) { + Log.error(e.toString()); + } + return null; + } } \ No newline at end of file diff --git a/example/src/main/java/studio/craftory/craftoryexample/blocks/CopperOre.java b/example/src/main/java/studio/craftory/craftoryexample/blocks/CopperOre.java new file mode 100644 index 0000000..4bf50d3 --- /dev/null +++ b/example/src/main/java/studio/craftory/craftoryexample/blocks/CopperOre.java @@ -0,0 +1,14 @@ +package studio.craftory.craftoryexample.blocks; + +import lombok.NonNull; +import org.bukkit.Location; +import studio.craftory.core.blocks.templates.ComplexCustomBlock; +import studio.craftory.core.data.CraftoryDirection; + + +public class CopperOre extends ComplexCustomBlock { + + public CopperOre(@NonNull Location location, @NonNull CraftoryDirection facingDirection) { + super(location, facingDirection); + } +} diff --git a/example/src/main/java/studio/craftory/craftoryexample/blocks/SimpleGenerator.java b/example/src/main/java/studio/craftory/craftoryexample/blocks/SimpleGenerator.java index b7fd13b..b7ff001 100644 --- a/example/src/main/java/studio/craftory/craftoryexample/blocks/SimpleGenerator.java +++ b/example/src/main/java/studio/craftory/craftoryexample/blocks/SimpleGenerator.java @@ -3,23 +3,13 @@ import lombok.NonNull; import org.bukkit.Location; import org.bukkit.event.player.PlayerInteractEvent; -import studio.craftory.core.annotations.CustomBlock; -import studio.craftory.core.annotations.RenderData; import studio.craftory.core.annotations.Tickable; -import studio.craftory.core.blocks.renders.Renderers; import studio.craftory.core.blocks.templates.ComplexCustomBlock; import studio.craftory.core.components.energy.EnergyOutput; import studio.craftory.core.components.energy.EnergyOutput.EnergyOutputData; import studio.craftory.core.components.energy.EnergyStorage.EnergyStorageData; import studio.craftory.core.data.CraftoryDirection; -@CustomBlock(renders = {Renderers.BLOCK_STATE_RENDER, Renderers.ENTITY_SPAWNER_RENDER, Renderers.HEAD_RENDER}) -@RenderData( - northFacingModel = "assets/blocks/northexample", southFacingModel = "assets/blocks/southexample", - eastFacingModel = "assets/blocks/eastexample", westFacingModel = "assets/blocks/westexample", - upFacingModel = "assets/blocks/upexample", downFacingModel = "assets/blocks/downexample", - headModel = "assets/blocks/headexample" -) @EnergyOutputData(maxExtract = 100) @EnergyStorageData(capacity = 1000000) public class SimpleGenerator extends ComplexCustomBlock implements EnergyOutput { diff --git a/example/src/main/java/studio/craftory/craftoryexample/commands/SpawnGeneratorCommand.java b/example/src/main/java/studio/craftory/craftoryexample/commands/SpawnGeneratorCommand.java deleted file mode 100644 index 4efc656..0000000 --- a/example/src/main/java/studio/craftory/craftoryexample/commands/SpawnGeneratorCommand.java +++ /dev/null @@ -1,23 +0,0 @@ -package studio.craftory.craftoryexample.commands; - -import java.util.Optional; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import studio.craftory.core.Craftory; -import studio.craftory.core.blocks.templates.BaseCustomBlock; -import studio.craftory.craftoryexample.blocks.SimpleGenerator; - -public class SpawnGeneratorCommand implements CommandExecutor { - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (sender instanceof Player) { - Player player = (Player)sender; - Optional generator = Craftory.getInstance().getCustomBlockAPI().placeCustomBlock(player.getLocation().add(0,3,0), SimpleGenerator.class); - return generator.isPresent(); - } - return false; - } -} diff --git a/pom.xml b/pom.xml index fc6158b..169eb02 100644 --- a/pom.xml +++ b/pom.xml @@ -31,13 +31,14 @@ 1.8 - 1.0-rc2 + 1.0 2.12.0 https://sonarcloud.io craftorystudios craftorystudios_Craftory_Parent + true diff --git a/testServers/.gitignore b/testServers/.gitignore index 6a9638a..3ac9903 100644 --- a/testServers/.gitignore +++ b/testServers/.gitignore @@ -1,13 +1,4 @@ # Created by .ignore support plugin (hsz.mobi) #Test Servers -*.txt -*.json -*.yml -*.properties -*.gz -*.log -*.dat -*.dat_old -*.lock -*.mca -*.mcmeta \ No newline at end of file +* +!*.bat \ No newline at end of file diff --git a/testServers/paper/1.16.5/plugins/.md b/testServers/paper/1.16.5/plugins/.md deleted file mode 100644 index e69de29..0000000