mirror of
https://github.com/Terncode/pixel.horse.git
synced 2026-09-24 13:55:04 +02:00
Merge pull request #87 from Stubenhocker1399/discord-button
Add "Join Discord" button
This commit is contained in:
@@ -140,6 +140,7 @@ Add `config.json` file in root directory with following content. You can use `co
|
||||
```javascript
|
||||
{
|
||||
"title": "Pony Town",
|
||||
"discordLink": "https://discordapp.com/invite/<invite_code>", // optional
|
||||
"twitterLink": "https://twitter.com/<twitter_name>", // optional
|
||||
"contactEmail": "<your_contact_email>",
|
||||
"port": 8090,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"title": "Your Town",
|
||||
"discordLink": "<LINK_TO_DISCORD_INVITE>",
|
||||
"twitterLink": "<LINK_TO_TWITTER>",
|
||||
"contactEmail": "[email protected]",
|
||||
"port": 8090,
|
||||
|
||||
@@ -9,6 +9,7 @@ $warning: #df871c;
|
||||
$danger: #d9534f;
|
||||
$dark: #222;
|
||||
$patreon: #f96955;
|
||||
$discord: #7289DA;
|
||||
|
||||
$none: #777;
|
||||
$dev: #bd3e91;
|
||||
@@ -43,7 +44,8 @@ $theme-colors: (
|
||||
warning: $warning,
|
||||
danger: $danger,
|
||||
dark: $dark,
|
||||
patreon: $patreon
|
||||
patreon: $patreon,
|
||||
discord: $discord
|
||||
);
|
||||
|
||||
$gold: #ffcf00;
|
||||
|
||||
@@ -25,6 +25,7 @@ export const token = attr('data-token');
|
||||
export const version = attr('data-version');
|
||||
export const isPublic = attr('data-public') === 'true';
|
||||
export const supporterLink = attr('data-supporter-link');
|
||||
export const discordLink = attr('data-discord-link');
|
||||
export const twitterLink = attr('data-twitter-link');
|
||||
export const contactEmail = attr('data-email');
|
||||
export const copyrightName = attr('data-copyright');
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
clamp, lengthOfXY, setFlag, hasFlag, boundsIntersect, point, toInt, lerpColor, distanceXY
|
||||
} from '../common/utils';
|
||||
import {
|
||||
OFFLINE_PONY, MAX_SCALE, SUPPORTER_PONY, HOUR, MIN_SCALE, CAMERA_WIDTH_MIN, CAMERA_WIDTH_MAX,
|
||||
OFFLINE_PONY, MAX_SCALE, SUPPORTER_PONY, DISCORD_PONY, HOUR, MIN_SCALE, CAMERA_WIDTH_MIN, CAMERA_WIDTH_MAX,
|
||||
CAMERA_HEIGHT_MIN, CAMERA_HEIGHT_MAX, SECOND, TILE_CHANGE_RANGE, MINUTE, PONY_TYPE,
|
||||
REGION_SIZE, tileWidth, tileHeight
|
||||
} from '../common/constants';
|
||||
@@ -206,6 +206,7 @@ export class PonyTownGame implements Game {
|
||||
tileSets?: TileSets;
|
||||
offlinePony = createPony(0, 0, OFFLINE_PONY, mockPaletteManager.addArray(defaultPalette), mockPaletteManager);
|
||||
supporterPony = createPony(0, 0, SUPPORTER_PONY, mockPaletteManager.addArray(defaultPalette), mockPaletteManager);
|
||||
discordPony = createPony(0, 0, DISCORD_PONY, mockPaletteManager.addArray(defaultPalette), mockPaletteManager);
|
||||
scale: number;
|
||||
failedFBO = false;
|
||||
rightOverride?: boolean;
|
||||
@@ -718,6 +719,7 @@ export class PonyTownGame implements Game {
|
||||
|
||||
this.offlinePony = createPony(0, 0, OFFLINE_PONY, palettes.defaultPalette, this.paletteManager);
|
||||
this.supporterPony = createPony(0, 0, SUPPORTER_PONY, palettes.defaultPalette, this.paletteManager);
|
||||
this.discordPony = createPony(0, 0, DISCORD_PONY, palettes.defaultPalette, this.paletteManager);
|
||||
initializeToys(this.paletteManager);
|
||||
} catch (e) {
|
||||
this.errorReporter.captureEvent({ name: 'failed game.initWebGL', error: e.message, stack: e.stack });
|
||||
|
||||
@@ -136,6 +136,7 @@ export const MONTH_NAMES_EN = [
|
||||
|
||||
export const OFFLINE_PONY = 'DAKVlZUvLy82QIxomgCfgAYAGIAoQGEBwAEERFEUEA==';
|
||||
export const SUPPORTER_PONY = 'CAfz9PUFLUnapSD/1wD5aFT////+hHM2QIJkJ8AQLkkADAA6jXrsBT1Iw+wBMJOqoW1C2oW1AAI=';
|
||||
export const DISCORD_PONY = 'EAlyidplAf/U7f/r9//09vf///9//9QsLzOXp+E2QQJiBLQBPwAMADqNANFZmyFFGhKgorM8ICAEIBAgJGZyzAzMzMzAwMzMzAAAwA==';
|
||||
|
||||
// patreon reward tier IDs
|
||||
export const rewardLevel1 = '2255086';
|
||||
|
||||
@@ -4,7 +4,7 @@ import { getUrl } from '../../../client/rev';
|
||||
import { CREDITS, CONTRIBUTORS, Credit } from '../../../client/credits';
|
||||
import { CHANGELOG } from '../../../generated/changelog';
|
||||
import { SUPPORTER_REWARDS_LIST } from '../../../common/constants';
|
||||
import { supporterLink, contactEmail } from '../../../client/data';
|
||||
import { supporterLink, discordLink, contactEmail } from '../../../client/data';
|
||||
|
||||
function toCredit(credit: Credit) {
|
||||
return {
|
||||
@@ -27,5 +27,6 @@ export class About {
|
||||
readonly changelog = CHANGELOG;
|
||||
readonly rewards = SUPPORTER_REWARDS_LIST;
|
||||
readonly patreonLink = supporterLink;
|
||||
readonly discordLink = discordLink;
|
||||
readonly contactEmail = contactEmail;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { GameService } from '../services/gameService';
|
||||
import { Model, Friend } from '../services/model';
|
||||
import { version, host, contactEmail, supporterLink, twitterLink, copyrightName } from '../../client/data';
|
||||
import { version, host, contactEmail, supporterLink, twitterLink, discordLink, copyrightName } from '../../client/data';
|
||||
import { PonyTownGame } from '../../client/game';
|
||||
import { faTwitter, faPatreon, faEnvelope, faCog, faHome, faGamepad, faInfoCircle, faHorseHead } from '../../client/icons';
|
||||
import { faTwitter, faPatreon, faEnvelope, faCog, faHome, faGamepad, faInfoCircle, faHorseHead, faDiscord } from '../../client/icons';
|
||||
import { InstallService } from '../services/installService';
|
||||
import { OAuthProvider, Entity, FakeEntity, Pony } from '../../common/interfaces';
|
||||
import { registerServiceWorker, isBrowserOutdated, checkIframeKey } from '../../client/clientUtils';
|
||||
@@ -47,6 +47,7 @@ export class App implements OnInit, OnDestroy {
|
||||
readonly emailIcon = faEnvelope;
|
||||
readonly twitterIcon = faTwitter;
|
||||
readonly patreonIcon = faPatreon;
|
||||
readonly discordIcon = faDiscord;
|
||||
readonly cogIcon = faCog;
|
||||
readonly homeIcon = faHome;
|
||||
readonly helpIcon = faGamepad;
|
||||
@@ -54,6 +55,7 @@ export class App implements OnInit, OnDestroy {
|
||||
readonly charactersIcon = faHorseHead;
|
||||
readonly contactEmail = contactEmail;
|
||||
readonly patreonLink = supporterLink;
|
||||
readonly discordLink = discordLink;
|
||||
readonly twitterLink = twitterLink;
|
||||
readonly copyright = copyrightName;
|
||||
private url = location.pathname;
|
||||
|
||||
@@ -14,6 +14,7 @@ page-loader(*ngIf="!playing")
|
||||
h2.sr-only Character selection
|
||||
.mx-auto(style="max-width: 400px;")
|
||||
support-button.mb-3
|
||||
discord-button.mb-3
|
||||
install-button.mb-3
|
||||
character-select(
|
||||
[(error)]="error" [newButton]="true" [removeButton]="true" (change)="updateMuzzles()"
|
||||
|
||||
@@ -20,6 +20,8 @@ div(*ngIf="!playing")
|
||||
div(*ngIf="!!account")
|
||||
.form-group
|
||||
support-button
|
||||
.form-group
|
||||
discord-button
|
||||
.form-group(*ngIf="canInstall")
|
||||
install-button
|
||||
.form-group
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
a.btn.btn-lg.btn-outline-discord.btn-block.mb-2(
|
||||
*ngIf="discordLink" (mouseenter)="pony.excite()" (mouseout)="pony.reset()" [href]="discordLink" target="_blank"
|
||||
rel="noopener noreferrer")
|
||||
| Join us on Discord!
|
||||
svg.discord-logo(xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300")
|
||||
circle(fill="#2C2F33" cx="150" cy="150" r="150")
|
||||
//path(xmlns="http://www.w3.org/2000/svg" d="M40 12s-4.586-3.59-10-4l-.488.977C34.406 10.176 36.652 11.89 39 14c-4.047-2.066-8.04-4-15-4-6.96 0-10.953 1.934-15 4 2.348-2.11 5.02-4.016 9.488-5.023L18 8c-5.68.535-10 4-10 4s-5.121 7.426-6 22c5.16 5.953 13 6 13 6l1.64-2.184C13.856 36.848 10.716 35.121 8 32c3.238 2.45 8.125 5 16 5s12.762-2.55 16-5c-2.715 3.121-5.855 4.848-8.64 5.816L33 40s7.84-.047 13-6c-.879-14.574-6-22-6-22zM17.5 30c-1.934 0-3.5-1.79-3.5-4s1.566-4 3.5-4 3.5 1.79 3.5 4-1.566 4-3.5 4zm13 0c-1.934 0-3.5-1.79-3.5-4s1.566-4 3.5-4 3.5 1.79 3.5 4-1.566 4-3.5 4z" fill="#8C9EFF" scale="3")
|
||||
path(xmlns="http://www.w3.org/2000/svg" transform="translate(28,40)" fill="#7289DA" class="st0" d="M104.4 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1.1-6.1-4.5-11.1-10.2-11.1zM140.9 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1s-4.5-11.1-10.2-11.1z")
|
||||
path(xmlns="http://www.w3.org/2000/svg" transform="translate(28,40)" fill="#7289DA" class="st0" d="M189.5 20h-134C44.2 20 35 29.2 35 40.6v135.2c0 11.4 9.2 20.6 20.5 20.6h113.4l-5.3-18.5 12.8 11.9 12.1 11.2 21.5 19V40.6c0-11.4-9.2-20.6-20.5-20.6zm-38.6 130.6s-3.6-4.3-6.6-8.1c13.1-3.7 18.1-11.9 18.1-11.9-4.1 2.7-8 4.6-11.5 5.9-5 2.1-9.8 3.5-14.5 4.3-9.6 1.8-18.4 1.3-25.9-.1-5.7-1.1-10.6-2.7-14.7-4.3-2.3-.9-4.8-2-7.3-3.4-.3-.2-.6-.3-.9-.5-.2-.1-.3-.2-.4-.3-1.8-1-2.8-1.7-2.8-1.7s4.8 8 17.5 11.8c-3 3.8-6.7 8.3-6.7 8.3-22.1-.7-30.5-15.2-30.5-15.2 0-32.2 14.4-58.3 14.4-58.3 14.4-10.8 28.1-10.5 28.1-10.5l1 1.2c-18 5.2-26.3 13.1-26.3 13.1s2.2-1.2 5.9-2.9c10.7-4.7 19.2-6 22.7-6.3.6-.1 1.1-.2 1.7-.2 6.1-.8 13-1 20.2-.2 9.5 1.1 19.7 3.9 30.1 9.6 0 0-7.9-7.5-24.9-12.7l1.4-1.6s13.7-.3 28.1 10.5c0 0 14.4 26.1 14.4 58.3 0 0-8.5 14.5-30.6 15.2z")
|
||||
.discord-pony
|
||||
discord-pony(#pony [scale]="2")
|
||||
@@ -0,0 +1,45 @@
|
||||
@import '../../../../styles/partials/variables';
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: relative;
|
||||
|
||||
@media (max-width: 320px) {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.discord-logo {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 5px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
@media (max-width: 290px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.discord-pony {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 70px;
|
||||
width: 100px;
|
||||
overflow: hidden;
|
||||
border-radius: $border-radius-lg - 2px;
|
||||
|
||||
> discord-pony {
|
||||
position: absolute;
|
||||
bottom: -95px;
|
||||
left: -20px;
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { discordLink } from '../../../client/data';
|
||||
|
||||
@Component({
|
||||
selector: 'discord-button',
|
||||
templateUrl: 'discord-button.pug',
|
||||
styleUrls: ['discord-button.scss'],
|
||||
})
|
||||
export class DiscordButton {
|
||||
readonly discordLink = discordLink;
|
||||
constructor() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
character-preview(
|
||||
#characterPreview [pony]="pony" [state]="state" [noBackground]="true" [noShadow]="true"
|
||||
[noOutline]="true" [scale]="scale" style="width: 180px; height: 180px; position: relative; top: -20px;")
|
||||
@@ -0,0 +1,88 @@
|
||||
import { Component, OnInit, OnDestroy, Input, ViewChild } from '@angular/core';
|
||||
import { defaultExpression } from '../../../client/ponyUtils';
|
||||
import { defaultPonyState } from '../../../client/ponyHelpers';
|
||||
import { DISCORD_PONY } from '../../../common/constants';
|
||||
import { Expression, Muzzle, HeadAnimation, Iris } from '../../../common/interfaces';
|
||||
import { excite } from '../../../client/ponyAnimations';
|
||||
import { FrameService, FrameLoop } from '../../services/frameService';
|
||||
import { CharacterPreview } from '../character-preview/character-preview';
|
||||
import { decompressPonyString } from '../../../common/compressPony';
|
||||
|
||||
const BLEP: Expression = {
|
||||
...defaultExpression,
|
||||
muzzle: Muzzle.Blep,
|
||||
};
|
||||
|
||||
const EXCITED: Expression = {
|
||||
...defaultExpression,
|
||||
muzzle: Muzzle.SmileOpen,
|
||||
};
|
||||
|
||||
const DERP: Expression = {
|
||||
...defaultExpression,
|
||||
muzzle: Muzzle.SmileOpen,
|
||||
leftIris: Iris.Up,
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'discord-pony',
|
||||
templateUrl: 'discord-pony.pug',
|
||||
})
|
||||
export class DiscordPony implements OnInit, OnDestroy {
|
||||
@ViewChild('characterPreview', { static: true }) characterPreview!: CharacterPreview;
|
||||
@Input() scale = 3;
|
||||
pony = decompressPonyString(DISCORD_PONY);
|
||||
state = defaultPonyState();
|
||||
private expression?: Expression;
|
||||
private headAnimation?: HeadAnimation;
|
||||
private headTime = 0;
|
||||
private loop: FrameLoop;
|
||||
constructor(frameService: FrameService) {
|
||||
this.loop = frameService.create(delta => this.tick(delta));
|
||||
}
|
||||
ngOnInit() {
|
||||
this.loop.init();
|
||||
}
|
||||
ngOnDestroy() {
|
||||
this.loop.destroy();
|
||||
}
|
||||
excite() {
|
||||
this.headTime = 0;
|
||||
this.headAnimation = excite;
|
||||
this.expression = Math.random() < 0.2 ? DERP : EXCITED;
|
||||
}
|
||||
reset() {
|
||||
this.expression = undefined;
|
||||
}
|
||||
private tick(delta: number) {
|
||||
this.headTime += delta;
|
||||
|
||||
if (this.headAnimation) {
|
||||
const frame = Math.floor(this.headTime * this.headAnimation.fps);
|
||||
|
||||
if (frame >= this.headAnimation.frames.length && !this.headAnimation.loop) {
|
||||
this.headAnimation = undefined;
|
||||
this.state.headAnimation = undefined;
|
||||
this.state.headAnimationFrame = 0;
|
||||
this.characterPreview.blink();
|
||||
} else {
|
||||
this.state.headAnimation = this.headAnimation;
|
||||
this.state.headAnimationFrame = frame % this.headAnimation.frames.length;
|
||||
}
|
||||
} else {
|
||||
this.state.headAnimation = undefined;
|
||||
|
||||
if (this.expression) {
|
||||
if (Math.random() < 0.01) {
|
||||
this.expression = undefined;
|
||||
}
|
||||
} else {
|
||||
if (Math.random() < 0.005) {
|
||||
this.expression = BLEP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.state.expression = this.expression;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { supporterLink } from '../../../client/data';
|
||||
import { supporterLink, discordLink } from '../../../client/data';
|
||||
import { GENERAL_RULES } from '../../../common/constants';
|
||||
|
||||
@Component({
|
||||
@@ -8,5 +8,6 @@ import { GENERAL_RULES } from '../../../common/constants';
|
||||
})
|
||||
export class PlayNotice {
|
||||
readonly patreonLink = supporterLink;
|
||||
readonly discordLink = discordLink;
|
||||
readonly rules = GENERAL_RULES;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ import { SpriteBox } from './sprite-box/sprite-box';
|
||||
import { SpriteSelection } from './sprite-selection/sprite-selection';
|
||||
import { SupportButton } from './support-button/support-button';
|
||||
import { SupporterPony } from './supporter-pony/supporter-pony';
|
||||
import { DiscordButton } from './discord-button/discord-button';
|
||||
import { DiscordPony } from './discord-pony/discord-pony';
|
||||
import { SetSelection, SetOutlineHidden } from './set-selection/set-selection';
|
||||
import { CheckBox } from './check-box/check-box';
|
||||
import { PortraitBox } from './portrait-box/portrait-box';
|
||||
@@ -91,6 +93,8 @@ const declarations = [
|
||||
SpriteSelection,
|
||||
SupportButton,
|
||||
SupporterPony,
|
||||
DiscordButton,
|
||||
DiscordPony,
|
||||
SetSelection,
|
||||
SetOutlineHidden,
|
||||
CheckBox,
|
||||
|
||||
@@ -5,6 +5,7 @@ export interface AppConfig {
|
||||
title: string;
|
||||
twitterLink?: string;
|
||||
supporterLink?: string;
|
||||
discordLink?: string;
|
||||
contactEmail?: string;
|
||||
port: number;
|
||||
adminPort?: number;
|
||||
|
||||
@@ -100,6 +100,7 @@ export function createIndex(assetsPath: string, adminAssetsPath: string) {
|
||||
title: config.title,
|
||||
twitterLink: config.twitterLink,
|
||||
supporterLink: config.supporterLink,
|
||||
discordLink: config.discordLink,
|
||||
email: config.contactEmail,
|
||||
logo: `${config.host}${getRevImageURL('logo-120.png')}`,
|
||||
loadingImage: `data:image/png;base64,${loadingImage.toString('base64')}`,
|
||||
|
||||
@@ -50,6 +50,7 @@ html(lang="en")
|
||||
data-key="kmncxb908z"
|
||||
data-version=version
|
||||
data-supporter-link=supporterLink
|
||||
data-discord-link=discordLink
|
||||
data-twitter-link=twitterLink
|
||||
data-email=email
|
||||
data-copyright=title
|
||||
|
||||
Reference in New Issue
Block a user