Better responsive UI, added author field and improved project loading.

This commit is contained in:
天クマ 2025-03-28 20:17:21 -03:00
commit ea805dbb28
15 changed files with 176 additions and 198 deletions

BIN
1.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

View file

@ -1,130 +0,0 @@
var obfuscators = [];
var styleMap = {
'§4': 'font-weight:normal;text-decoration:none;color:#be0000',
'§c': 'font-weight:normal;text-decoration:none;color:#fe3f3f',
'§6': 'font-weight:normal;text-decoration:none;color:#d9a334',
'§e': 'font-weight:normal;text-decoration:none;color:#fefe3f',
'§2': 'font-weight:normal;text-decoration:none;color:#00be00',
'§a': 'font-weight:normal;text-decoration:none;color:#3ffe3f',
'§b': 'font-weight:normal;text-decoration:none;color:#3ffefe',
'§3': 'font-weight:normal;text-decoration:none;color:#00bebe',
'§1': 'font-weight:normal;text-decoration:none;color:#0000be',
'§9': 'font-weight:normal;text-decoration:none;color:#3f3ffe',
'§d': 'font-weight:normal;text-decoration:none;color:#fe3ffe',
'§5': 'font-weight:normal;text-decoration:none;color:#be00be',
'§f': 'font-weight:normal;text-decoration:none;color:#ffffff',
'§7': 'font-weight:normal;text-decoration:none;color:#bebebe',
'§8': 'font-weight:normal;text-decoration:none;color:#3f3f3f',
'§0': 'font-weight:normal;text-decoration:none;color:#000000',
'§l': 'font-weight:bold',
'§n': 'text-decoration:underline;text-decoration-skip:spaces',
'§o': 'font-style:italic',
'§m': 'text-decoration:line-through;text-decoration-skip:spaces',
};
function obfuscate(string, elem) {
var magicSpan,
currNode,
len = elem.childNodes.length;
if(string.indexOf('<br>') > -1) {
elem.innerHTML = string;
for(var j = 0; j < len; j++) {
currNode = elem.childNodes[j];
if(currNode.nodeType === 3) {
magicSpan = document.createElement('span');
magicSpan.innerHTML = currNode.nodeValue;
elem.replaceChild(magicSpan, currNode);
init(magicSpan);
}
}
} else {
init(elem, string);
}
function init(el, str) {
var i = 0,
obsStr = str || el.innerHTML,
len = obsStr.length;
obfuscators.push( window.setInterval(function () {
if(i >= len) i = 0;
obsStr = replaceRand(obsStr, i);
el.innerHTML = obsStr;
i++;
}, 0) );
}
function randInt(min, max) {
return Math.floor( Math.random() * (max - min + 1) ) + min;
}
function replaceRand(string, i) {
var randChar = String.fromCharCode( randInt(64,90) ); /*Numbers: 48-57 Al:64-90*/
return string.substr(0, i) + randChar + string.substr(i + 1, string.length);
}
}
function applyCode(string, codes) {
var len = codes.length;
var elem = document.createElement('span'),
obfuscated = false;
for(var i = 0; i < len; i++) {
elem.style.cssText += styleMap[codes[i]] + ';';
if(codes[i] === '§k') {
obfuscate(string, elem);
obfuscated = true;
}
}
if(!obfuscated) elem.innerHTML = string;
return elem;
}
function parseStyle(string) {
var codes = string.match(/§.{1}/g) || [],
indexes = [],
apply = [],
tmpStr,
indexDelta,
noCode,
final = document.createDocumentFragment(),
len = codes.length,
string = string.replace(/\n|\\n/g, '<br>');
for(var i = 0; i < len; i++) {
indexes.push( string.indexOf(codes[i]) );
string = string.replace(codes[i], '\x00\x00');
}
if(indexes[0] !== 0) {
final.appendChild( applyCode( string.substring(0, indexes[0]), [] ) );
}
for(var i = 0; i < len; i++) {
indexDelta = indexes[i + 1] - indexes[i];
if(indexDelta === 2) {
while(indexDelta === 2) {
apply.push ( codes[i] );
i++;
indexDelta = indexes[i + 1] - indexes[i];
}
apply.push ( codes[i] );
} else {
apply.push( codes[i] );
}
if( apply.lastIndexOf('§r') > -1) {
apply = apply.slice( apply.lastIndexOf('§r') + 1 );
}
tmpStr = string.substring( indexes[i], indexes[i + 1] );
final.appendChild( applyCode(tmpStr, apply) );
}
return final;
}
function clearObfuscators() {
var i = obfuscators.length;
for(;i--;) {
clearInterval(obfuscators[i]);
}
obfuscators = [];
}
String.prototype.replaceColorCodes = function() {
clearObfuscators();
var outputString = parseStyle(String(this));
return outputString;
};
/////////////////////////////////////////////////
function cutString(str, cutStart, cutEnd){
return str.substr(0,cutStart) + str.substr(cutEnd+1);
}

30
featured.js Normal file
View file

@ -0,0 +1,30 @@
const featuredHelper = document.querySelector("#featuredHelper");
async function getFeaturedJSON() {
const response = await fetch(`featured.json`);
if (!response.ok) {
featuredHelper.innerHTML = `
<p>;( Oopsie! Could not load featured projects...</p>
`
throw new Error("Failed to fetch featured projects JSON");
}
const data = await response.json();
data.forEach(project => {
const featuredDiv = document.createElement("div");
featuredDiv.classList.add("featuredProject");
featuredDiv.id = `featured-${project}`;
featuredDiv.innerHTML = `
<a href="project.html?id=${project}">
<img src="projects/${project}/logo.png">
<p>:${project}</p>
</a>
`;
featuredHelper.appendChild(featuredDiv);
loadProject(project, document.querySelector(`featured-${project} p`), undefined, undefined, undefined, document.querySelector(`featured-${project} img`))
});
}
getFeaturedJSON();

View file

@ -1 +1 @@
["aboukkit"] ["aboukkit", "ghostsandstuff"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View file

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="project.js"></script> <script src="project.js"></script>
<script src="featured.js" defer></script> <script src="featured.js" defer></script>
<title>NBeta</title> <title>neoBeta</title>
</head> </head>
<body> <body>
<div id="everythingHelper"> <div id="everythingHelper">
@ -18,6 +18,7 @@
<a href="index.html">mods</a> - <a href="index.html">mods</a> -
<a href="index.html">plugins</a> <a href="index.html">plugins</a>
</ul> </ul>
<p id="credits">Adrian Victor, 2025 (<a href="https://git.disroot.org/adrianvictor/neoBeta">Unlicense</a>)</p>
</div> </div>
</header> </header>
<main> <main>

View file

@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="styles.css" media="screen"> <link rel="stylesheet" href="styles.css" media="screen">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NBeta</title> <title>neoBeta</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<!-- <script src="MinecraftColorCodes.3.7.js"></script> --> <!-- <script src="MinecraftColorCodes.3.7.js"></script> -->
<script src="project.js"></script> <script src="project.js"></script>
@ -19,27 +19,33 @@
<a href="index.html">mods</a> - <a href="index.html">mods</a> -
<a href="index.html">plugins</a> <a href="index.html">plugins</a>
</ul> </ul>
<p id="credits">Adrian Victor, 2025 (<a href="https://git.disroot.org/adrianvictor/neoBeta">Unlicense</a>)</p>
</div> </div>
</header> </header>
<div id="projectHeader"> <div id="projectHeader">
<img> <img>
<div id="projectTitleSubtitle"> <div id="projectTitleSubtitle">
<h1>Loading project...</h1> <div id="projectTitleAuthor">
<p>...</p> <h1 id="projectTitle">Loading project...</h1>
<p id="projectAuthor">by tenkuma</p>
</div>
<p id="projectSubtitle">...</p>
</div> </div>
<button>Download</button> <a id="downloadLink"><button id="downloadButton">Download</button></a>
</div> </div>
<main id="projectDescription"> <main id="projectDescription">
</main> </main>
</div> </div>
<script> <script>
const downloadButton = document.querySelector("#projectHeader button"); const downloadButton = document.querySelector("#downloadLink");
const header = document.querySelector("#projectHeader"); const header = document.querySelector("#projectHeader");
const headerTitle = document.querySelector("#projectHeader h1"); const headerTitle = document.querySelector("#projectTitle");
const subtitle = document.querySelector("#projectHeader p"); const subtitle = document.querySelector("#projectSubtitle");
const main = document.querySelector("main"); const author = document.querySelector("#projectAuthor");
const logo = document.querySelector("#projectHeader img"); const logo = document.querySelector("#projectHeader img");
loadProject(projectID, headerTitle, subtitle, main, logo); const main = document.querySelector("main");
const body = document.querySelector("body");
loadProject(projectID, headerTitle, subtitle, author, main, logo, downloadButton, body, body);
</script> </script>
</body> </body>
</html> </html>

View file

@ -16,16 +16,36 @@ async function getProjectDescription(obj, id = projectID) {
} }
} }
async function loadProject(id = projectID, objTitle, objSubtitle, objDescription, objLogo) { async function loadProject(id = projectID, objTitle, objSubtitle, objAuthor, objDescription, objLogo, objDownloadLink, changeColor, changeBackground) {
try { try {
const jsonData = await getProjectJSON(id); const jsonData = await getProjectJSON(id);
if (objTitle) objTitle.innerText = jsonData.project.title; if (objTitle) objTitle.innerText = jsonData.project.title;
if (objSubtitle) objSubtitle.innerText = jsonData.project.subtitle; if (objSubtitle) objSubtitle.innerText = jsonData.project.subtitle;
if (objAuthor) objAuthor.innerText = `by ${jsonData.project.author}`;
if (objDescription) await getProjectDescription(objDescription, id); if (objDescription) await getProjectDescription(objDescription, id);
if (objLogo) objLogo.src = `projects/${id}/logo.png`;
if (jsonData.project.downloadLink) {
if (objDownloadLink) objDownloadLink.href = jsonData.project.downloadLink;
} else {
if (objDownloadLink) objDownloadLink.innerText = "Download unavailable";
}
if (jsonData.project.displayLogo == true) {
if (objLogo) objLogo.src = `projects/${id}/logo.png`;
} else {
objLogo.remove();
}
if (jsonData.project.backgroundColor) {
changeColor.style.backgroundColor = jsonData.project.backgroundColor;
}
if (jsonData.project.backgroundImage) {
changeBackground.style.backgroundImage = `url(${jsonData.project.backgroundImage})`;
}
if (jsonData.project.backgroundImageSize) {
changeBackground.style.backgroundSize = jsonData.project.backgroundImageSize;
}
} catch (error) { } catch (error) {
console.error("Error loading project:", error); console.error("Error loading project:", error);
} }

View file

@ -1,19 +1,20 @@
## Custom commands with predefined responses! ![Aboukkit logo, abboukit written in a Minecraft's logo like font painted in red.](https://cdn.modrinth.com/data/cached_images/94b1f813f8e15f82dddcffa5284c92e59cb93b27.png)
This plugin adds a simple way to add custom commands that will respond users with predefined messages from config.yml. It supports Minecraft's color coding (use & instead of §) and placeholders for player/server info (TODO).
### Default Commands This plugin adds a simple way to add custom commands that will respond users with predefined messages from ```config.yml```. It supports Minecraft's color coding (use & instead of §) ~~and placeholders for player/server info~~ (TODO).
- About
- Aboukkit
These default commands §aneed§r to be configured.
### Adding new commands ## Default Commands
First of all: run the server with the plugin for the first time, so config.yml is generated. - About
- Aboukkit
Follow the structure that the template shows in your config.yml. Then use a file explorer to open the plugin's JAR file and edit plugin.yml, you can copy a command entry and fill all the fields (be careful with indentation, YML does not support TAB). These default commands need to be configured.
### Why? ## Adding new commands
First of all: run the server with the plugin for the first time, so ```config.yml``` is generated.
Follow the structure that the template shows in your ```config.yml```. Then use a file explorer to open the plugin's JAR file and edit plugin.yml, you can copy a command entry and fill all the fields (be careful with indentation, YML does not support TAB).
## Why?
I made this plugin because I have a server for version b1.7.3 and I wanted to add a /about command to give credit to the server founders and link to our website. So I made this that I will use every time I need a simple 'wall of text' command. I made this plugin because I have a server for version b1.7.3 and I wanted to add a /about command to give credit to the server founders and link to our website. So I made this that I will use every time I need a simple 'wall of text' command.
Newer versions ## Newer versions
I don't see why I would build this for latest versions, I guess there are already better solutions. I made this just because of the lack of plugins for Minecraft beta. I don't see why I would build this for latest versions, I guess there are already better solutions. I made this just because of the lack of plugins for Minecraft beta.

View file

@ -1,23 +1,11 @@
{ {
"project": { "project": {
"author": "tenkuma",
"title": "Aboukkit", "title": "Aboukkit",
"subtitle": "A Brief Subtitle for the Project", "subtitle": "Adds a simple way to add custom commands with custom responses to your server.",
"description": "This is a placeholder description for the project. You can add details about the project's objectives, features, and goals here.", "downloadLink": "https://modrinth.com/plugin/aboukkit/versions",
"logo": "", "backgroundColor": "darkred",
"images": [ "displayLogo": true
{
"src": "images/image1.jpg",
"alt": "Image 1 description"
},
{
"src": "images/image2.jpg",
"alt": "Image 2 description"
},
{
"src": "images/image3.jpg",
"alt": "Image 3 description"
}
]
} }
} }

View file

@ -0,0 +1,6 @@
This plugins aims to use stuff from my library that would not fit into any plugin (or not in the way presented here) that has ~~a lot~~ (WIP) of random stuff. Everything should be togglable in the config.
## Features
- **RainbowChat:** Rainbow color code.
- **SkibidiBlocker:** Strike a lightning on players that say a word.
- **AntiSpam:** Blocks repeated words in the chat. Optionally can strike a lightning to the player who is spamming.

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 KiB

View file

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Before After
Before After

View file

@ -0,0 +1,11 @@
{
"project": {
"author": "tenkuma",
"title": "Ghosts 'n Stuff",
"subtitle": "Adds a simple way to add custom commands with custom responses to your server.",
"backgroundImage": "projects/ghostsandstuff/ghosts.jpg",
"backgroundImageSize": "cover",
"displayLogo": true
}
}

View file

@ -27,7 +27,8 @@ a {
main { main {
outline: 2px solid gray; outline: 2px solid gray;
margin-top: 20px; margin-top: 20px;
padding: 10px; padding: 20px;
background-color: black;
} }
button { button {
@ -35,7 +36,7 @@ button {
background-color: black; background-color: black;
color: white; color: white;
padding: 10px; padding: 10px;
border: 1px solid white; outline: 1px white;
} }
button:hover { button:hover {
@ -43,22 +44,15 @@ button:hover {
border: 1px solid gray; border: 1px solid gray;
} }
/* #titleBox { code {
background-color: brown; font-family: Minecraft, 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
width: 100px; background-color: rgb(75, 75, 75);
height: 100px; border: 1px solid white;
color: white; padding-left: 4px;
text-align: center; padding-right: 4px;
background: url("1.gif"); /* margin-left: 2px;
background-size: contain; margin-right: 2px; */
outline: 2px solid white; }
margin-right: 12px;
} */
/* #titleBox:hover ~ #linksBox {
outline: 2px solid white;
height: auto;
} */
#linksBox { #linksBox {
padding: 10px; padding: 10px;
@ -149,24 +143,31 @@ button:hover {
padding-top: 20px; padding-top: 20px;
gap: 20px; gap: 20px;
display: flex; display: flex;
text-shadow: 2px 2px gray;
} }
#projectHeader button { #downloadButton {
border: 2px solid gray;
}
#downloadLink {
color: gray;
height: fit-content; height: fit-content;
margin-top: auto; margin-top: auto;
margin-bottom: auto; margin-bottom: auto;
margin-left: auto; margin-left: auto;
margin-right: 20px; text-align: right;
text-shadow: 2px 2px black;
} }
#projectHeader button:hover { #downloadButton:hover {
cursor: pointer; cursor: pointer;
border-color: white;
} }
#projectHeader img { #projectHeader img {
outline: 2px solid gray; outline: 2px solid gray;
width: 5vw; height: 100%;
height: 5vw;
} }
#projectDescription li { #projectDescription li {
@ -175,7 +176,21 @@ button:hover {
} }
#projectDescription h1, h2 { #projectDescription h1, h2 {
margin-bottom: 8px; margin-top: 8px;
}
#projectTitleAuthor {
display: flex;
}
#projectAuthor {
margin-left: 10px;
margin-top: auto;
margin-bottom: 6px;
}
#credits {
margin-left: auto;
} }
@media only screen and (max-width: 1280px) { @media only screen and (max-width: 1280px) {
@ -193,6 +208,29 @@ button:hover {
margin-right: auto; margin-right: auto;
} }
#projectHeader {
flex-direction: column;
text-align: center;
}
#projectHeader * {
margin-left: auto;
margin-right: auto;
}
#projectAuthor {
margin-left: 10px;
}
#projectTitle {
margin-right: 0;
}
#projectHeader img {
width: 10vh;
height: 10vh;
}
} }
@media only screen and (max-width: 300px) { @media only screen and (max-width: 300px) {
@ -201,5 +239,12 @@ button:hover {
max-width: 90%; max-width: 90%;
} }
#projectTitleAuthor {
flex-direction: column;
}
#projectAuthor {
margin: 0;
}
} }