Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
bc860d4
Addon build file will now delete if failed to load.
invalid-email-address Feb 20, 2025
c8add7b
Added a remove container function.
invalid-email-address Feb 22, 2025
a0d2460
Added more control to prompts.
invalid-email-address Feb 22, 2025
0570ba4
Made addon build file a temp file.
invalid-email-address Feb 23, 2025
de4ab28
Added more documentation and notes.
invalid-email-address Apr 19, 2025
5cb41c7
Fixed issues when skipping dialogue.
invalid-email-address Apr 19, 2025
3d5b69b
Added debug shortcut for reloading graphical components.
invalid-email-address Apr 19, 2025
ca0fd31
Added null checks when executing events.
invalid-email-address Apr 19, 2025
ec3a8fb
Added LayoutContainer.
invalid-email-address Apr 19, 2025
a603f16
Added catch statement to ignore window state issues.
invalid-email-address Apr 19, 2025
cfc1374
Added help functions for Window.
invalid-email-address Apr 19, 2025
c6c4074
Re-organized constructor parameters.
invalid-email-address Apr 19, 2025
5a314e7
Added a reload function for RenJava.
invalid-email-address Apr 19, 2025
204c1aa
Code cleanup.
invalid-email-address Apr 19, 2025
8665347
Removed DisplayOrder and implemented index base rendering. Added gene…
invalid-email-address Apr 21, 2025
e6f06d5
Added documentation.
invalid-email-address Apr 21, 2025
fe50349
Fixed wrong function call.
invalid-email-address Apr 21, 2025
615e0b0
Added getSection function.
invalid-email-address Apr 21, 2025
5813737
Fixed issue where wrong map size was being calculated.
invalid-email-address Apr 21, 2025
2863245
Fixed wrong directory for settings.properties
invalid-email-address Apr 21, 2025
86f481d
Added static shutdown function.
invalid-email-address Apr 22, 2025
4168b1f
Added helper functions for managing elements.
invalid-email-address Apr 22, 2025
04dca40
Removed index assignments for scenes. The elements will rely on autom…
invalid-email-address Apr 24, 2025
8c31c6e
Minor adjustments.
invalid-email-address Apr 27, 2025
fabee01
Added configuration for italic and bold fonts.
invalid-email-address Apr 27, 2025
cacaf33
Adjusted java doc.
invalid-email-address Apr 27, 2025
c83769c
Fixed issues when setting x and y positions.
invalid-email-address Apr 27, 2025
3f15f11
Fixed grammar issue.
invalid-email-address Apr 27, 2025
a8b9daf
Converted long if statement into a switch.
invalid-email-address Apr 27, 2025
8a7b17f
Added stylesheets to containers.
invalid-email-address Apr 27, 2025
958d3a1
Added java doc.
invalid-email-address Apr 27, 2025
2adfc8b
Added exception handling.
invalid-email-address Apr 27, 2025
400e883
Code cleanup.
invalid-email-address Apr 27, 2025
5cd7512
Update fading transition to reset opacity correctly and fix opacity i…
invalid-email-address Apr 30, 2025
ce5b9f6
Removed manual index set.
invalid-email-address May 3, 2025
03e9c7b
Removed page parameter.
invalid-email-address May 3, 2025
c896c55
Switched from Overlay to Element. Deprecated addOverlay function.
invalid-email-address May 3, 2025
a97bd4a
Removed page parameter.
invalid-email-address May 3, 2025
22f4eb7
Expanded Java doc.
invalid-email-address May 3, 2025
b8b6486
Added notes for addon loading.
invalid-email-address Sep 12, 2025
f91ea96
Added fading transitions will now stop at the end of the video.
invalid-email-address Sep 12, 2025
8723184
Fixed issues with InputScene text not aligning.
invalid-email-address Sep 12, 2025
bfd2b25
Added generic textbox function.
invalid-email-address Sep 12, 2025
2d39545
Cleaned up class.
invalid-email-address Sep 12, 2025
f96349b
Scenes will no longer progress when clicking insde the text area.
invalid-email-address Sep 14, 2025
8469bb6
Improved image loader caching.
invalid-email-address Oct 17, 2025
f8b2c0c
Added width and height controls.
invalid-email-address Oct 17, 2025
116a76b
Updated GUI engine to latest RenEngine version.
invalid-email-address Oct 17, 2025
3909bc8
Removed ImageNotFoundException throw.
invalid-email-address Oct 17, 2025
a45b9d3
Updated function call to use element mapping.
invalid-email-address Oct 17, 2025
e9e724b
Updated javadoc.
invalid-email-address Oct 17, 2025
69dca59
Removed deprecated Overlay call.
invalid-email-address Oct 17, 2025
c428dfb
Removed setIndex calls.
invalid-email-address Oct 17, 2025
b4acaba
Added abstract assemble function.
invalid-email-address Oct 17, 2025
ac79f33
Removed exception.
invalid-email-address Oct 17, 2025
a8862a9
Removed exception.
invalid-email-address Oct 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions src/main/java/me/piitex/renjava/Launch.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package me.piitex.renjava;

import javafx.application.Application;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.io.*;
Expand All @@ -19,6 +20,8 @@
import me.piitex.renjava.configuration.RenJavaConfiguration;
import me.piitex.renjava.gui.GuiLoader;
import me.piitex.renjava.gui.Window;
import me.piitex.renjava.gui.overlays.ButtonOverlay;
import me.piitex.renjava.gui.prompts.Prompt;
import me.piitex.renjava.loggers.ApplicationLogger;
import me.piitex.renjava.loggers.RenLogger;
import org.reflections.Reflections;
Expand Down Expand Up @@ -93,7 +96,6 @@ private static void loadClass(Class<?> clazz, String[] args, InfoFile infoFile)

// Try to create info file if it didn't exist.
if (!infoFile.exists()) {

// Try to re-create
infoFile = new InfoFile(new File(renJava.getBaseDirectory(), "/renjava/build.info"), true);
if (!infoFile.exists()) {
Expand All @@ -117,7 +119,6 @@ private static void loadClass(Class<?> clazz, String[] args, InfoFile infoFile)

infoFile.write("main", clazz.getName());
infoFile.write("file", fileName);

} catch (URISyntaxException e) {
RenLogger.LOGGER.error("Could retrieve runtime information.", e);
}
Expand Down Expand Up @@ -179,6 +180,10 @@ public void start(Stage stage) {

/**
* This is just a default execute for testing purposes only.
* To make this execute work in your own environment, create a 'test' folder.
* The folder should be in the root directory of this project.
* Place gui default assets inside /~test/game/
* Run {@link Main#main(String[])}
*/
@Game(name = "Default Execute", author = "piitex", version = "0.0.0")
@Configuration(title = "{name}", width = 1920, height = 1080)
Expand Down Expand Up @@ -214,7 +219,29 @@ public void createStory() {

@Override
public void start() {
Prompt prompt = new Prompt("Are you sure you want to start a new game?");
prompt.setBlockMainWindow(false);

ButtonOverlay yes = new ButtonOverlay("yes", "Yes", Color.WHITE);
yes.setY(325);
prompt.addElement(yes);

yes.onClick(event -> {
// TODO: Play the first story of the game. (New game)
System.out.println("Starting new game...");
});

ButtonOverlay no = new ButtonOverlay("no", "No", Color.WHITE);
no.setY(325);
no.setX(840);

no.onClick(event -> {
prompt.closeWindow();
});

prompt.addElement(no);

prompt.render();
}
}
}
1 change: 1 addition & 0 deletions src/main/java/me/piitex/renjava/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public class Main {

/**
* Initializes the javafx application.
* This is needed because the main execute cannot be executed while extending Application.
*
* @param args Application parameters.
*/
Expand Down
73 changes: 63 additions & 10 deletions src/main/java/me/piitex/renjava/RenJava.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package me.piitex.renjava;

import javafx.application.HostServices;
import javafx.application.Platform;
import javafx.scene.paint.Color;
import javafx.stage.StageStyle;
import me.piitex.renjava.addons.AddonLoader;
Expand All @@ -16,7 +17,9 @@
import me.piitex.renjava.configuration.SettingsProperties;
import me.piitex.renjava.events.EventHandler;
import me.piitex.renjava.events.defaults.*;
import me.piitex.renjava.gui.GuiLoader;
import me.piitex.renjava.gui.Window;
import me.piitex.renjava.gui.WindowBuilder;
import me.piitex.renjava.gui.containers.ScrollContainer;
import me.piitex.renjava.gui.layouts.VerticalLayout;
import me.piitex.renjava.gui.menus.MainMenu;
Expand Down Expand Up @@ -80,7 +83,6 @@ public abstract class RenJava {

protected String buildVersion;


// Error tracking
private static long lastErrorTimeStamp;
private static int spamTrack = 0;
Expand All @@ -99,6 +101,7 @@ protected void init() {
// Run after super
PLAYER = new Player();
TRACKS = new Tracks();
ADDONLOADER = new AddonLoader();
EVENTHANDLER = new EventHandler();

EVENTHANDLER.registerListener(new MenuClickEventListener());
Expand All @@ -109,25 +112,71 @@ protected void init() {
this.registerData(PLAYER);
this.registerData(TRACKS);
new RenLoader(this);
ADDONLOADER = new AddonLoader();
}

public void reload(boolean resetGraphics) {
// Reloads the game. Do not call unless you know what you are doing.
PLAYER = null;
TRACKS = null;
EVENTHANDLER.getRegisteredListeners().clear();
registeredCharacters.clear();
registeredData.clear();
ADDONLOADER.disable();
ADDONLOADER = null;

gameWindow.clear();
gameWindow.render();

// Re-initialize.
init();

if (resetGraphics) {
gameWindow.getStage().setOnHiding(null);
gameWindow.getStage().hide();
new GuiLoader(gameWindow.getStage(), this, hostServices);
}
}

/**
* Used when displaying game information.
*
* @return The name of the project.
*/
public String getName() {
return name;
}

/**
* Used when displaying game information.
*
* @return The author of the project.
*/
public String getAuthor() {
return author;
}

/**
* Used when displaying game information.
*
* @return The version of the project.
*/
public String getVersion() {
return version;
}

/**
* The engine will automatically create a unique id for every project. See {@link me.piitex.renjava.utils.MDUtils#getGameID(String)}
* <p>
* The id is used as a unique game folder stored on the local system. Used for storing global data that can transfer between different save versions.
* @return The generated game id.
*/
public Integer getID() {
return id;
}

/**
* @return The applications logger.
*/
public Logger getLogger() {
return logger;
}
Expand Down Expand Up @@ -214,8 +263,6 @@ public void setBaseDir(File baseDir) {

/**
* Registers a character in the RenJava framework.
* <p>
* The registerCharacter() method is used to register a character in the RenJava framework.
* Registered characters can be accessed and managed by other parts of the framework using their unique ID.
*
* @param character The character object to be registered.
Expand All @@ -233,8 +280,6 @@ public Collection<Character> getCharacters() {

/**
* Retrieves a character by its ID.
* <p>
* The getCharacter() method is used to retrieve a character object based on its ID.
* Characters are registered using the registerCharacter() method and can be accessed using their unique ID.
*
* @param id The ID of the character to retrieve.
Expand Down Expand Up @@ -431,6 +476,14 @@ public static void openLink(String url) {
getInstance().getHost().showDocument(url);
}

/**
* Forcefully closes the application.
*/
public static void shutdown() {
Platform.exit();
System.exit(0);
}

public static void writeStackTrace(Exception e) {
if (lastErrorTimeStamp > 0) {
spamTrack++;
Expand Down Expand Up @@ -467,7 +520,7 @@ public static void writeStackTrace(Exception e) {
}

if (errorWindow == null) {
errorWindow = new Window("Error", StageStyle.DECORATED, CONFIGURATION.getGameIcon(), 920, 650, false);
errorWindow = new WindowBuilder("Error").setStageStyle(StageStyle.DECORATED).setIcon(CONFIGURATION.getGameIcon()).setDimensions(920, 650).setScale(false).build();
} else {
errorWindow.clearContainers();
}
Expand All @@ -493,11 +546,11 @@ public static void writeStackTrace(Exception e) {
texts.add(stackTrace);

TextFlowOverlay textFlowOverlay = new TextFlowOverlay(texts, 900, 600);
rootLayout.addOverlay(textFlowOverlay);
rootLayout.addElement(textFlowOverlay);

container.addLayout(rootLayout);
container.addElement(rootLayout);

errorWindow.addContainers(container);
errorWindow.addContainer(container);

errorWindow.render();
}
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/me/piitex/renjava/RenLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ public RenLoader(RenJava renJava) {
setupGame();
if (shutdown) {
// Shutdown application if startup fails.
Platform.exit();
System.exit(0);
RenJava.shutdown();
return;
}

Expand Down Expand Up @@ -244,8 +243,11 @@ public synchronized String getVersion() {
}

if (version == null) {
// we could not compute the version so use a blank
version = "";
// Please read and understand the RenJava license.
// Any modifications to RenJava that are sold for commercial use must be available.
// Any person can request source and all authors/developers must abide by that request.
// Sources must be disclosed this ensures safety and security of the application.
version = "Unknown (Request author for source)";
}

return version;
Expand Down
41 changes: 31 additions & 10 deletions src/main/java/me/piitex/renjava/addons/AddonLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import me.piitex.renjava.RenJava;
import me.piitex.renjava.configuration.InfoFile;
import me.piitex.renjava.loggers.RenLogger;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.jetbrains.annotations.Nullable;

Expand All @@ -11,7 +12,6 @@
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
Expand All @@ -24,6 +24,7 @@ public class AddonLoader {
private final List<Addon> addons = new ArrayList<>();

private final Logger logger;

public AddonLoader() {
logger = RenLogger.LOGGER;
}
Expand All @@ -39,7 +40,7 @@ public void load() {
logger.info("No addons to load.");
return; // No need to load if there are no addons.
} else {
logger.info("Loading " + size + " addon(s)...");
logger.info("Loading {} addon(s)...", size);
}

Map<File, String> lateLoaders = new HashMap<>();
Expand All @@ -65,10 +66,18 @@ public void load() {

// Convert entry to file then load info file
try {
File buildFile = new File(RenJava.getInstance().getBaseDirectory(), "addons/build.info");
Files.copy(zipFile.getInputStream(entry), Path.of(buildFile.getPath()), StandardCopyOption.REPLACE_EXISTING);
File buildFile = File.createTempFile("build", ".info");
buildFile.deleteOnExit();

InfoFile build = new InfoFile(buildFile, false);
InfoFile build;
try (FileOutputStream outputStream = new FileOutputStream(buildFile)) {
IOUtils.copy(zipFile.getInputStream(entry), outputStream);
build = new InfoFile(buildFile, false);
} catch (IOException e) {
RenLogger.LOGGER.error("Could not create temp-file for '{}'.", file.getName());
RenJava.writeStackTrace(e);
continue;
}

boolean invalidVersion = false;

Expand Down Expand Up @@ -107,9 +116,6 @@ public void load() {
nonDependants.add(file);

}
// Delete after
buildFile.delete();

extractResources(zipFile);

} catch (IOException e) {
Expand All @@ -130,12 +136,19 @@ public void load() {
}
});

// Java will scan the files randomly with no certain order.
// This will loop through the addons and attempt to load them.
// If the addon succeeds it will be added to passed and removed from validations.
// The loop will continue until validations is empty or the same addon fails twice.
Map<File, String> validations = new HashMap<>(lateLoaders);
Collection<String> passed = new HashSet<>();
AtomicReference<String> lastValidated = new AtomicReference<>("");

while (!validations.isEmpty()) {
lateLoaders.forEach((file, string) -> {

// The same addon can only be looped twice in a row if it's the only addon left.
// If the addon failed twice it means there was a problem with that addon.
if (lastValidated.get().equalsIgnoreCase(file.getName())) {
logger.error("Could not initialize " + file.getName() + ": May be the result of a missing dependency.");
validations.remove(file);
Expand All @@ -145,9 +158,13 @@ public void load() {
return;
}
String dependency = string.trim();

// Dependencies are configured; dependencies=test1,test2
// If it contains a ',' it is likely to have multiple dependencies.
if (dependency.contains(",")) {
boolean canExecute = true;
Collection<Addon> dep = new HashSet<>();
// Loop the dependencies by its comma. test1,test2
for (String depend : dependency.split(",")) {
Addon addon = addons.stream().filter(addon1 -> addon1.getName().equalsIgnoreCase(depend)).findAny().orElse(null);
if (addon == null) {
Expand Down Expand Up @@ -197,6 +214,11 @@ public void load() {
private void initAddon(File file, @Nullable Collection<Addon> dependencies) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
try (JarFile jarFile = new JarFile(file)) {
Enumeration<JarEntry> entries = jarFile.entries();

// Deprecation notice!
// new URL is deprecated and moved to new URI(str).toUrl();
// This method does not work with the string.
// So I'm keeping it in for now.
URL[] urls = {new URL("jar:file:" + file.getPath() + "!/")};
URLClassLoader cl = URLClassLoader.newInstance(urls);
while (entries.hasMoreElements()) {
Expand All @@ -207,7 +229,7 @@ private void initAddon(File file, @Nullable Collection<Addon> dependencies) thro

// Authors should warn users about using pirated versions or getting addons from unknown sources.
// This can easily allow malicious code to be executed. I will not be adding any form on 'anti malware' checks. Don't download something you don't trust.
// Also be aware of the licence renjava uses. Authors are required to provide source to code per the GPL 3.0 license.
// Also be aware of the licence renjava uses. Authors are required to provide source code per the GPL 3.0 license.
Class<?> clazz = cl.loadClass(clazzName);
if (Addon.class.isAssignableFrom(clazz)) {
Object object = clazz.getDeclaredConstructor().newInstance();
Expand All @@ -216,7 +238,6 @@ private void initAddon(File file, @Nullable Collection<Addon> dependencies) thro
addon.getDependencies().addAll(dependencies);
}
addons.add(addon);
//clazz.getMethod("onLoad").invoke(object, null);
boolean failed = false;
try {
addon.onLoad(); // Loads addon
Expand Down
Loading