Compare commits

...

12 Commits

Author SHA1 Message Date
SemvdH
db760e5dda Add first steps for gui 2025-11-10 22:27:05 +01:00
SemvdH
1632d02e69 remove settings file 2025-11-10 19:43:49 +01:00
SemvdH
43c6d5265b add extra files to gitignore 2025-11-10 19:43:21 +01:00
SemvdH
c56fe10564 add equals and hashcode to coordinate class 2025-11-10 19:42:21 +01:00
SemvdH
1aa6a9f374 Move MinecraftColor to core plugin 2025-11-10 00:00:05 +01:00
SemvdH
cd23ab6192 Use database from core plugin in coordinates plugin 2025-11-09 23:56:33 +01:00
SemvdH
4168355ea7 Add proper dependency from coordinates to core plugin 2025-11-09 23:48:31 +01:00
SemvdH
1c073b1b14 add base project pom 2025-11-09 23:34:42 +01:00
SemvdH
6fa5dde5e2 Move config for database to core plugin 2025-11-09 22:57:01 +01:00
SemvdH
def99319f3 Fill pom.xml for core plugin 2025-11-09 22:55:45 +01:00
SemvdH
e3b91443ba Add base core plugin 2025-11-09 22:51:52 +01:00
SemvdH
f4ea8886b8 Add base project 2025-11-09 22:48:53 +01:00
23 changed files with 472 additions and 118 deletions

3
.gitignore vendored
View File

@@ -37,7 +37,8 @@ buildNumber.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
ic_plugin/settings.xml
ic_plugin/*
ic_plugin_core/settings.xml
# Eclipse m2e generated files
# Eclipse Core
.project

View File

@@ -6,9 +6,9 @@
<groupId>nl.interestingcorner.coordinates</groupId>
<artifactId>ic_plugin_coordinates</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ic_plugin_coordinates</name>
<!-- FIXME change it to the project's website -->
<url>https://interesting-corner.nl</url>
<properties>
@@ -34,6 +34,12 @@
</dependencyManagement>
<dependencies>
<dependency>
<groupId>nl.interestingcorner.core</groupId>
<artifactId>ic_plugin_core</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
@@ -97,12 +103,6 @@
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<systemPropertyVariables>
<db.username>${db.username}</db.username>
<db.password>${db.password}</db.password>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>

View File

@@ -1,14 +0,0 @@
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
<profiles>
<profile>
<id>default</id>
<properties>
<db.username>spigot</db.username>
<db.password>Z7nhqy+spigot-minecraft</db.password>
<db.name>ic_minecraft</db.name>
<db.host>localhost</db.host>
</properties>
</profile>
</profiles>
</settings>

View File

@@ -5,7 +5,7 @@ import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin;
import nl.interestingcorner.coordinates.commands.CoordinatesCommand;
import nl.interestingcorner.coordinates.db.DatabaseManager;
import nl.interestingcorner.coordinates.db.CoordinatesDatabaseManager;
import nl.interestingcorner.coordinates.gui.CoordinatesGUIListener;
public class App extends JavaPlugin {
@@ -13,12 +13,7 @@ public class App extends JavaPlugin {
@Override
public void onEnable() {
getLogger().info("Eyooo we boutta get lit!");
if (!DatabaseManager.INSTANCE.initialize(this)) {
getLogger().severe("Could not initialize database. Exiting!");
setEnabled(false);
return;
}
CoordinatesDatabaseManager.INSTANCE.initialize(this);
getLogger().info("Successfully initialized database");
getServer().getPluginManager().registerEvents(new CoordinatesGUIListener(), this);
@@ -29,10 +24,6 @@ public class App extends JavaPlugin {
@Override
public void onDisable() {
getLogger().info("Eyooo we outta here!");
if (!DatabaseManager.INSTANCE.close()) {
getLogger().severe("Error while trying to close db connection");
}
}
private void registerCommands() {

View File

@@ -1,23 +1,18 @@
package nl.interestingcorner.coordinates.commands;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ComponentStyle;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.TranslatableComponent;
import nl.interestingcorner.coordinates.db.Coordinate;
import nl.interestingcorner.coordinates.db.DatabaseManager;
import nl.interestingcorner.coordinates.db.MinecraftColor;
import nl.interestingcorner.coordinates.db.CoordinatesDatabaseManager;
import nl.interestingcorner.core.MinecraftColor;
public class AddCoordinateCommandHandler implements CoordinatesCommandHandler {
@@ -72,7 +67,7 @@ public class AddCoordinateCommandHandler implements CoordinatesCommandHandler {
}
//TODO check if item doesnt already exist, coordinate with same values, create isEquals method for coordinate
return DatabaseManager.INSTANCE
return CoordinatesDatabaseManager.INSTANCE
.addCoordinate(name, // name
description, // description
new Coordinate.Position(playerLocation.getBlockX(), playerLocation.getBlockY(),

View File

@@ -5,8 +5,8 @@ import java.util.List;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import nl.interestingcorner.coordinates.db.CoordinatesDatabaseManager;
import nl.interestingcorner.coordinates.db.Coordinate;
import nl.interestingcorner.coordinates.db.DatabaseManager;
import nl.interestingcorner.coordinates.gui.CoordinatesGUI;
public class GetCoordinatesCommandHandler implements CoordinatesCommandHandler {
@@ -16,10 +16,10 @@ public class GetCoordinatesCommandHandler implements CoordinatesCommandHandler {
if (sender instanceof Player player) {
List<Coordinate> coords;
if (args.length < 2) {
coords = DatabaseManager.INSTANCE.getAllCoordinates();
coords = CoordinatesDatabaseManager.INSTANCE.getAllCoordinates();
} else if (args[1].equalsIgnoreCase("world")) {
String world = player.getWorld().getName();
coords = DatabaseManager.INSTANCE.getAllCoordinates(world);
coords = CoordinatesDatabaseManager.INSTANCE.getAllCoordinates(world);
} else {
sender.sendMessage("Invalid argument: " + args[1]);
return false;

View File

@@ -1,5 +1,12 @@
package nl.interestingcorner.coordinates.db;
import java.util.List;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import nl.interestingcorner.core.MinecraftColor;
/**
* +-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+-----+---------+----------------+
* | Field | Type | Null | Key | Default | Extra |
@@ -22,6 +29,7 @@ package nl.interestingcorner.coordinates.db;
* Class to represent a coordinate to teleport to
*/
public class Coordinate {
private final int HASH_PRIME = 31;
/**
* auto-generated ID
*/
@@ -106,4 +114,58 @@ public class Coordinate {
.append(" }");
return sb.toString();
}
public ItemStack toItem()
{
ItemStack itemStack = new ItemStack(this.color.toMaterial());
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return itemStack;
}
meta.setDisplayName(this.color.toColorCode() + this.name);
meta.setLore(List.of(
MinecraftColor.WHITE.toColorCode() + this.description,
this.nether ? MinecraftColor.RED.toColorCode() + "Nether Coordinate" : "Overworld Coordinate",
"X: " + this.position.x(),
"Y: " + this.position.y(),
"Z: " + this.position.z(),
"World: " + this.world
));
itemStack.setItemMeta(meta);
return itemStack;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
{
return true;
}
if (obj == null || getClass() != obj.getClass())
{
return false;
}
Coordinate other = (Coordinate) obj;
return id == other.id &&
nether == other.nether &&
name.equals(other.name) &&
description.equals(other.description) &&
position.equals(other.position) &&
world.equals(other.world) &&
color == other.color;
}
@Override
public int hashCode() {
int result = Integer.hashCode(id);
result = HASH_PRIME * result + Boolean.hashCode(nether);
result = HASH_PRIME * result + (name != null ? name.hashCode() : 0);
result = HASH_PRIME * result + (description != null ? description.hashCode() : 0);
result = HASH_PRIME * result + (position != null ? position.hashCode() : 0);
result = HASH_PRIME * result + (world != null ? world.hashCode() : 0);
result = HASH_PRIME * result + (color != null ? color.hashCode() : 0);
return result;
}
}

View File

@@ -1,65 +1,28 @@
package nl.interestingcorner.coordinates.db;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.plugin.java.JavaPlugin;
public enum DatabaseManager {
import nl.interestingcorner.core.MinecraftColor;
import nl.interestingcorner.core.db.DatabaseManager;
public enum CoordinatesDatabaseManager implements nl.interestingcorner.core.db.DatabaseInitializeListener{
INSTANCE;
private Connection connection;
private JavaPlugin app;
/**
* Initializes the database. Creates the file and sets up the db structure.
*
* @param app the app to use for logging
* @return true if the database was initialized successfully. False if not.
*/
public boolean initialize(JavaPlugin app) {
public void initialize(JavaPlugin app) {
this.app = app;
if (!setupDatabase()) {
return false;
}
if (!initializeTables()) {
return false;
}
return true;
}
/**
* Closes the connectino to the database
*
* @return true if the connection closed succesfully, false if not.
*/
public boolean close() {
try {
if (this.connection != null && !this.connection.isClosed()) {
this.connection.close();
}
} catch (SQLException ex) {
this.app.getLogger().log(Level.SEVERE, "Error while closing the databse connection: {0}", ex.getMessage());
return false;
}
return true;
DatabaseManager.INSTANCE.registerDatabaseInitializeListener(this);
}
/**
@@ -159,33 +122,9 @@ public enum DatabaseManager {
return true;
}
/**
* Sets up the connectino to the database. Creates a new .db file if it
* doesn't exist yet.
*
* @return true if the connection was set up successfully. False if not.
*/
private boolean setupDatabase() {
if (!this.app.getDataFolder().exists()) {
if (!this.app.getDataFolder().mkdirs()) {
app.getLogger().severe("Could not create data folder");
return false;
}
}
File dbFile = new File(app.getDataFolder(), "database.db");
String url = "jdbc:sqlite:" + dbFile.getAbsolutePath();
try {
this.connection = DriverManager.getConnection(url);
} catch (SQLException e) {
this.app.getLogger().log(Level.SEVERE, "Could not connect to database file {0}: {1}",
new Object[] { dbFile, e.getMessage() });
}
this.app.getLogger().log(Level.INFO, "Connected to SQLite database: {0}", dbFile.getName());
return true;
public boolean addCoordinate(Coordinate coordinate) {
return addCoordinate(coordinate.name, coordinate.description, coordinate.position, coordinate.nether,
coordinate.world, coordinate.color);
}
/**
@@ -213,4 +152,13 @@ public enum DatabaseManager {
return true;
}
@Override
public void initializeDatabaseTables(Connection connection) {
this.connection = connection;
if (!initializeTables()) {
this.app.getLogger().severe("Could not initialize coordinates database tables");
}
this.app.getLogger().info("Coordinates database tables initialized");
}
}

View File

@@ -10,7 +10,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import nl.interestingcorner.coordinates.db.Coordinate;
import nl.interestingcorner.coordinates.db.MinecraftColor;
import nl.interestingcorner.core.MinecraftColor;
public class CoordinatesGUI {
public static void open(Player player, List<Coordinate> coordinates) {

View File

@@ -2,6 +2,7 @@ main: nl.interestingcorner.coordinates.App
name: IC-coords
version: 0.1
api-version: 1.21
depend: [IC-core]
commands:
ic-coords:

View File

View File

127
ic_plugin_core/pom.xml Normal file
View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>nl.interestingcorner.core</groupId>
<artifactId>ic_plugin_core</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ic_plugin_core</name>
<url>https://interesting-corner.nl</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>17</maven.compiler.release>
</properties>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.11.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<!-- Optionally: parameterized tests support -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
<version>2.28.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.21.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.50.3.0</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<includes>
<include>plugin.yml</include>
</includes>
</resource>
</resources>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.4.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<systemPropertyVariables>
<db.username>${db.username}</db.username>
<db.password>${db.password}</db.password>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.12.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.6.1</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,22 @@
package nl.interestingcorner.core;
import org.bukkit.plugin.java.JavaPlugin;
import nl.interestingcorner.core.db.DatabaseManager;
/**
* Core plugin class for the Interesting Corner plugin
*/
public class App extends JavaPlugin {
@Override
public void onEnable() {
DatabaseManager.INSTANCE.initialize(this);
getLogger().info("Core plugin loaded!");
}
@Override
public void onDisable() {
DatabaseManager.INSTANCE.close();
getLogger().info("Core plugin exited!");
}
}

View File

@@ -1,4 +1,4 @@
package nl.interestingcorner.coordinates.db;
package nl.interestingcorner.core;
import java.util.HashMap;

View File

@@ -0,0 +1,11 @@
package nl.interestingcorner.core.db;
import java.sql.Connection;
public interface DatabaseInitializeListener {
/**
* Gets called when the databse has been setup and tables can be initialized.
* @param connection the connection to the database
*/
void initializeDatabaseTables(Connection connection);
}

View File

@@ -0,0 +1,118 @@
package nl.interestingcorner.core.db;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.bukkit.plugin.java.JavaPlugin;
public enum DatabaseManager {
INSTANCE;
private Connection connection;
private JavaPlugin app;
private boolean initialized = false;
private final List<DatabaseInitializeListener> databaseInitializeListeners = new ArrayList<>();
/**
* Initializes the database. Creates the file and sets up the db structure.
*
* @param app the app to use for logging
* @return true if the database was initialized successfully. False if not.
*/
public boolean initialize(JavaPlugin app) {
if (this.initialized) {
return true;
}
this.app = app;
if (!setupDatabase()) {
return false;
}
initializeTables();
return true;
}
/**
* Closes the connection to the database
*
* @return true if the connection closed succesfully, false if not.
*/
public boolean close() {
try {
if (this.connection != null && !this.connection.isClosed()) {
this.connection.close();
this.initialized = false;
}
} catch (SQLException ex) {
this.app.getLogger().log(Level.SEVERE, "Error while closing the databse connection: {0}", ex.getMessage());
return false;
}
return true;
}
public void registerDatabaseInitializeListener(DatabaseInitializeListener listener) {
this.databaseInitializeListeners.add(listener);
this.app.getLogger().log(Level.INFO, "Registered database initialize listener: {0}", listener.getClass().getName());
// immediately initialize if the database is already initialized
if (this.initialized) {
try {
listener.initializeDatabaseTables(this.connection);
} catch (Exception e) {
this.app.getLogger().log(Level.SEVERE, "Could not initialize database tables: {0}", e.getMessage());
}
}
}
/**
* Sets up the connectino to the database. Creates a new .db file if it
* doesn't exist yet.
*
* @return true if the connection was set up successfully. False if not.
*/
private boolean setupDatabase() {
if (!this.app.getDataFolder().exists()) {
if (!this.app.getDataFolder().mkdirs()) {
app.getLogger().severe("Could not create data folder");
return false;
}
}
File dbFile = new File(app.getDataFolder(), "database.db");
String url = "jdbc:sqlite:" + dbFile.getAbsolutePath();
try {
this.connection = DriverManager.getConnection(url);
} catch (SQLException e) {
this.app.getLogger().log(Level.SEVERE, "Could not connect to database file {0}: {1}",
new Object[] { dbFile, e.getMessage() });
}
this.app.getLogger().log(Level.INFO, "Connected to SQLite database: {0}", dbFile.getName());
this.initialized = true;
return true;
}
/**
* initializes the tables for the database.
*/
private void initializeTables() {
for (DatabaseInitializeListener listener : this.databaseInitializeListeners) {
try {
listener.initializeDatabaseTables(this.connection);
} catch (Exception e) {
this.app.getLogger().log(Level.SEVERE, "Could not initialize database tables: {0}", e.getMessage());
}
}
}
}

View File

@@ -0,0 +1,14 @@
package nl.interestingcorner.core.gui;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
public class GUI implements InventoryHolder {
@Override
public Inventory getInventory() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'getInventory'");
}
}

View File

@@ -0,0 +1,42 @@
package nl.interestingcorner.core.gui;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
public class GUIBuilder {
public static final int MAX_INVENTORY_SIZE = 54; // max size of inventory before pages are needed
public static final int MAX_PAGE_INVENTORY_SIZE = 45; // max amount of items on a page
public Inventory buildInventory(List<ItemStack> items) {
/**
* if more than 45, add pages. Split by 45 items per page.
* use bottom row leftmost and rightmost item for navigation.
* use paper item for page number display in middle.
* use lore of navigation items clicked to handle showing next/previous page.
* use player.getOpeninventory() to get current inventory and update or close
* it.
*/
int itemsAmount = items.size();
int pagesAmount = getPagesAmount(itemsAmount);
Inventory gui = Bukkit.createInventory(null, MAX_INVENTORY_SIZE, "Coordinates Menu");
for (ItemStack item : items) {
gui.addItem(item);
}
return gui;
}
private static int getPagesAmount(int itemsAmount) {
if (itemsAmount > MAX_INVENTORY_SIZE) {
return ((itemsAmount / MAX_PAGE_INVENTORY_SIZE) + 1);
}
return 1;
}
}

View File

@@ -0,0 +1,4 @@
main: nl.interestingcorner.core.App
name: IC-core
version: 0.1
api-version: 1.21

View File

@@ -0,0 +1,19 @@
package nl.interestingcorner;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
/**
* Unit test for simple App.
*/
public class AppTest {
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue() {
assertTrue(true);
}
}

View File

@@ -1,4 +1,5 @@
#!/bin/bash
mvn install -f "/home/sem/Development/Minecraft/mc-ic-server/ic_plugin/pom.xml"
mvn jar:jar -f "/home/sem/Development/Minecraft/mc-ic-server/ic_plugin/pom.xml"
mvn install -f "/home/sem/Development/Minecraft/mc-ic-server/pom.xml"
scp ic_plugin_core/target/ic_plugin_core-1.0-SNAPSHOT.jar sem@10.10.100.50:/home/sem/minecraft/plugins
scp ic_plugin_coordinates/target/ic_plugin_coordinates-1.0-SNAPSHOT.jar sem@10.10.100.50:/home/sem/minecraft/plugins

12
pom.xml Normal file
View File

@@ -0,0 +1,12 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>nl.interestingcorner</groupId>
<artifactId>ic_plugins</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>ic_plugin_core</module>
<module>ic_plugin_coordinates</module>
</modules>
</project>