This commit is contained in:
NewHappyRabbit
2025-02-11 02:06:44 +02:00
7 changed files with 46 additions and 32 deletions
+6 -5
View File
@@ -5,11 +5,12 @@ const emojiTable: string[][] = [
["😀", "😱", "🤡", "😡", "🥺"],
["😈", "👏", "🥉", "🥈", "🥇"],
["🤙", "🥰", "😇", "😊", "🔥"],
["💪", "🏳️", "💀", "😭", "🤦‍♂️"],
["😎", "👎", "👍", "🥱", "💔"],
["❤️", "💰", "🤝", "🖕", "💥"],
["🆘", "🕊️", "➡️", "⬅️", "↙️"],
["↖️", "↗️", "⬆️", "↘️", "⬇️"],
["💪", "🏳️", "💀", "😭", "🫡"],
["🤦‍♂️", "👎", "👍", "🥱", "💔"],
["😎", "❤️", "💰", "🤝", "🖕"],
["💥", "🆘", "🕊️", "➡️", "⬅️"],
["↙️", "↖️", "↗️", "⬆️", "↘️"],
["⬇️", "❓", "⏳", "☢️", "⚠️"]
];
@customElement("emoji-table")
+1 -1
View File
@@ -183,7 +183,7 @@ export class PlayerPanel extends LitElement implements Layer {
<div class="flex flex-col gap-1">
<div class="text-white text-opacity-80 text-sm px-2">Traitor</div>
<div class="bg-opacity-50 bg-gray-700 rounded p-2 text-white">
${other.isTraitor()}
${other.isTraitor() ? "yes" : "no"}
</div>
</div>
+2 -1
View File
@@ -123,7 +123,8 @@ export class TerritoryLayer implements Layer {
this.alternativeView = e.alternateView;
});
this.eventBus.on(DragEvent, (e) => {
this.lastDragTime = Date.now();
// TODO: consider re-enabling this on mobile or low end devices for smoother dragging.
// this.lastDragTime = Date.now();
});
this.redraw();
}
+22 -16
View File
@@ -69,12 +69,12 @@
</head>
<body
class="h-full overflow-hidden select-none font-sans min-h-screen bg-opacity-0 bg-cover bg-center bg-fixed transition-opacity duration-300 ease-in-out">
class="h-full select-none font-sans min-h-screen bg-opacity-0 bg-cover bg-center bg-fixed transition-opacity duration-300 ease-in-out flex flex-col">
<!-- Main container with responsive padding -->
<!-- Logo section remains the same -->
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-4 sm:py-6 lg:py-8">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-4 sm:py-6 lg:py-8 flex-grow">
<div class="flex justify-center">
<img src="../../resources/images/OpenFrontLogo.svg" alt="OpenFront.io" />
<img src="../../resources/images/OpenFrontLogo.png" alt="OpenFront.io" />
</div>
<div class="flex justify-center text-sm font-bold mt-[-10px] pb-6 md:pb-12">
v0.15.0
@@ -105,18 +105,6 @@
Single Player
</button>
</div>
<!-- Links section -->
<div class="flex justify-center mt-4">
<a href="https://discord.gg/k22YrnAzGp" id="discord-link" target="_blank" rel="noopener noreferrer"
class="flex items-center justify-center px-6 py-2 bg-blue-200 hover:bg-blue-200 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition duration-300 ease-in-out mx-2">
<img src="../../resources/images/DiscordIcon.svg" alt="Discord" class="w-12 h-12" />
</a>
<a href="https://youtu.be/jvHEvbko3uw?si=znspkP84P76B1w5I" id="yt-link" target="_blank" rel="noopener noreferrer"
class="flex items-center justify-center px-2 py-0 bg-blue-200 hover:bg-blue-200 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition duration-300 ease-in-out mx-2">
<img src="../../resources/images/QuestionMarkIcon.svg" alt="Question Mark" class="mt-4 w-20 h-20" />
</a>
</div>
</div>
<!-- Game components -->
@@ -146,11 +134,29 @@
<div class="w-full sm:w-2/3 sm:fixed sm:right-0 sm:bottom-0 sm:flex justify-end" style="pointer-events: auto">
<events-display></events-display>
</div>
<div class="w-full md:w-fit" style="pointer-events: auto">
<div class="w-full sm:w-1/3" style="pointer-events: auto">
<control-panel></control-panel>
</div>
</div>
<!-- Footer section -->
<div class="w-full bg-gray-900/80 backdrop-blur-md py-4">
<div
class="max-w-7xl mx-auto px-4 flex justify-between items-center text-white sm:flex-row flex-col sm:gap-0 gap-4">
<div class="flex sm:flex-row flex-col sm:gap-8 gap-2">
<a href="https://youtu.be/jvHEvbko3uw?si=znspkP84P76B1w5I"
class="text-white/70 hover:text-white transition-colors duration-300" target="_blank">How to Play</a>
<a href="https://discord.gg/k22YrnAzGp" class="text-white/70 hover:text-white transition-colors duration-300"
target="_blank">Discord</a>
</div>
<div class="text-white/70">
© 2025
<a href="https://github.com/openfrontio/OpenFrontIO" class="hover:text-white transition-colors duration-300"
target="_blank">OpenFront.io</a>.
</div>
</div>
</div>
<!-- Scripts -->
<script>
// Remove preload class after everything is loaded
+5 -5
View File
@@ -19,7 +19,7 @@ export const pastelTheme = new (class implements Theme {
colord({ r: 125, g: 255, b: 75 }), // Warmer tint
colord({ r: 115, g: 250, b: 68 }), // Cooler tint
];
private water = colord({ r: 75, g: 142, b: 190 });
private water = colord({ r: 70, g: 132, b: 180 });
private shorelineWater = colord({ r: 100, g: 143, b: 255 });
private territoryColors: Colord[] = [
@@ -167,11 +167,11 @@ export const pastelTheme = new (class implements Theme {
if (gm.isShoreline(tile) && gm.isWater(tile)) {
return this.shorelineWater;
}
if (gm.magnitude(tile) < 7) {
if (gm.magnitude(tile) < 10) {
return colord({
r: Math.max(w.r - 7 + mag, 0),
g: Math.max(w.g - 7 + mag, 0),
b: Math.max(w.b - 7 + mag, 0),
r: Math.max(w.r - 10 + mag, 0),
g: Math.max(w.g - 10 + mag, 0),
b: Math.max(w.b - 10 + mag, 0),
});
}
return this.water;
@@ -26,6 +26,8 @@ export class ConstructionExecution implements Execution {
private ticksUntilComplete: Tick;
private cost: number;
constructor(
private ownerId: PlayerID,
private tile: TileRef,
@@ -56,6 +58,8 @@ export class ConstructionExecution implements Execution {
0,
spawnTile
);
this.cost = this.mg.unitInfo(this.constructionType).cost(this.player);
this.player.removeGold(this.cost);
this.construction.setConstructionType(this.constructionType);
this.ticksUntilComplete = info.constructionDuration;
return;
@@ -69,6 +73,8 @@ export class ConstructionExecution implements Execution {
if (this.ticksUntilComplete == 0) {
this.player = this.construction.owner();
this.construction.delete(false);
// refund the cost so player has the gold to build the unit
this.player.addGold(this.cost);
this.completeConstruction();
this.active = false;
return;
+4 -4
View File
@@ -11,9 +11,9 @@ const matcher = new RegExpMatcher({
});
export const MIN_USERNAME_LENGTH = 3;
export const MAX_USERNAME_LENGTH = 20;
export const MAX_USERNAME_LENGTH = 27;
const validPattern = /^[a-zA-Z0-9_\[\] ]+$/;
const validPattern = /^[a-zA-Z0-9_\[\] 🐈🍀]+$/;
const shadowNames = [
"NicePeopleOnly",
@@ -61,7 +61,7 @@ export function validateUsername(username: string): {
if (!validPattern.test(username)) {
return {
isValid: false,
error: "Username can only contain letters, numbers, and underscores.",
error: "Username can only contain letters, numbers, spaces, underscores, and [square brackets].",
};
}
@@ -71,7 +71,7 @@ export function validateUsername(username: string): {
export function sanitizeUsername(str: string): string {
const sanitized = str
.replace(/[^a-zA-Z0-9]/g, "")
.replace(/[^a-zA-Z0-9_\[\] 🐈🍀]/g, "")
.slice(0, MAX_USERNAME_LENGTH);
return sanitized.padEnd(MIN_USERNAME_LENGTH, "x");
}