Merge remote-tracking branch 'upstream/archive' into archive-update-v0.55.0

This commit is contained in:
Eliot Partridge
2019-10-01 18:04:54 -05:00
39 changed files with 2998 additions and 2486 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ h1(focusTitle) Account settings
| Changes saved
.form-group.text-right
button.btn.btn-default(type="submit" [disabled]="!canSubmit" style="min-width: 100px;")
| Save
| {{saveButtonText}}
div(style="margin-bottom: 100px;")
.form-group
+10 -1
View File
@@ -8,6 +8,7 @@ import { oauthProviders } from '../../../client/data';
import { Model } from '../../services/model';
import { getProviderIcon } from '../../shared/sign-in-box/sign-in-box';
import { faStar, faExclamationCircle, faSync } from '../../../client/icons';
import { Router } from '@angular/router';
@Component({
selector: 'account',
@@ -33,9 +34,10 @@ export class Account implements OnInit, OnDestroy {
removedAccount?: boolean;
accountError?: string;
accountSaved = false;
isNewAccount = false;
hides: HiddenPlayer[] | undefined = undefined;
page = 0;
constructor(private model: Model) {
constructor(private model: Model, private router: Router) {
}
ngOnInit() {
const account = this.account!;
@@ -44,6 +46,7 @@ export class Account implements OnInit, OnDestroy {
name: account.name,
birthdate: account.birthdate,
};
this.isNewAccount = account.birthdate === '';
this.pageChanged();
}
@@ -88,6 +91,9 @@ export class Account implements OnInit, OnDestroy {
get showAccountAlert() {
return this.model.missingBirthdate;
}
get saveButtonText() {
return this.isNewAccount ? 'Save and continue' : 'Save';
}
icon(id: string) {
return getProviderIcon(id);
}
@@ -98,6 +104,9 @@ export class Account implements OnInit, OnDestroy {
this.model.updateAccount(this.data)
.catch((e: Error) => this.accountError = e.message)
.then(() => this.accountSaved = true);
if (this.isNewAccount) {
this.router.navigate(['home']);
}
}
}
removeSite(site: SocialSiteInfo) {
+4 -2
View File
@@ -205,13 +205,15 @@ h1(focusTitle) Help
p.text-fading.
This is usually caused by outdated graphics drivers or browser.
Check if your browser is #[a(href="https://updatemybrowser.org/") up to date] and check
if there are new updates for your graphics card or device.
if there are new updates for your graphics driver or your device.
p.text-fading.
If your browser is already up to date, try installing different browser.
We recommend using #[a(href="https://www.google.com/chrome/") Chrome]
or #[a(href="https://www.mozilla.org/en-US/firefox/new/") Firefox].
p.text-fading.
Some older devices don't support necessary functions and will never work with the game.
If other workarounds didn't help, switching Graphics Quality to Low usually works.
You'll find that option in the game settings. After switching to Low, it
might take a minute for the screen to stop glitching.
section
h4 Graphical glitches, disappearing objects
@@ -83,6 +83,13 @@ export class ActionBar {
this.closeActions();
}
else {
// if the action menu was opened from the settings dropdown, just do nothing
// it means you can't close that menu by clicking on this button, but it's
// a minor issue
if (document.body.classList.contains('actions-modal-opened')) {
return;
}
this.isWaitingForActionsModal = true;
this.modalRef = this.modalService.show(this.actionsModal, { ignoreBackdropClick: true });
}
@@ -94,6 +94,7 @@ export class ActionsModal implements OnInit, OnDestroy {
this.game.editingActions = false;
clearInterval(this.interval);
this.subscription && this.subscription.unsubscribe();
this.close.emit(); // need to emit in case the menu wasn't closed with the Close button
this.notify.emit();
}
ok() {
@@ -102,8 +102,8 @@
.form-group
custom-checkbox(
[(checked)]="account.filterCyrillic"
help="Hide all messages containing russian alphabet")
| Filter russian chat
help="Hide all messages containing Russian alphabet")
| Filter Russian chat
.form-group
custom-checkbox(
[(checked)]="account.filterSwearWords"
@@ -112,6 +112,12 @@ ng-template(#shareLinkPopover)
.form-group
button.btn.btn-sm.ml-1([(ngModel)]="animation.loop" btnCheckbox [btnHighlight]="animation.loop")
| loop
.form-group(*ngIf="mode !== 'body'")
button.btn.btn-sm.ml-1([(ngModel)]="animation.dontOpenEyes" btnCheckbox [btnHighlight]="animation.dontOpenEyes")
| dontOpenEyes
.form-group(*ngIf="mode !== 'body'")
button.btn.btn-sm.ml-1([(ngModel)]="animation.dontCloseMouth" btnCheckbox [btnHighlight]="animation.dontCloseMouth")
| dontCloseMouth
.btn-group.ml-1(dropdown)
button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle title="Before animation")
| before: {{beforeAnimation?.name || 'none'}}
@@ -7,9 +7,9 @@ import {
BodyAnimationFrame as IBodyAnimationFrame,
HeadAnimation as IHeadAnimation,
HeadAnimationFrame as IHeadAnimationFrame,
ColorExtraSet, PonyInfo, PonyObject, BodyShadow, PonyEye
ColorExtraSet, PonyInfo, PonyObject, BodyShadow, PonyEye, HeadAnimationProperties
} from '../../../common/interfaces';
import { removeItem, repeat, isKeyEventInvalid, cloneDeep, array } from '../../../common/utils';
import { removeItem, repeat, isKeyEventInvalid, cloneDeep, array, hasFlag } from '../../../common/utils';
import { toPalette, createDefaultPony, syncLockedPonyInfo } from '../../../common/ponyInfo';
import { Key } from '../../../client/input/input';
import { defaultPonyState, defaultDrawPonyOptions } from '../../../client/ponyHelpers';
@@ -63,6 +63,8 @@ interface BodyAnimation extends BaseAnimation {
interface HeadAnimation extends BaseAnimation {
lockEyes?: boolean;
frames: HeadAnimationFrame[];
dontOpenEyes?: boolean;
dontCloseMouth?: boolean;
}
interface AnimationsData {
@@ -201,6 +203,13 @@ export class ToolsAnimation implements OnInit, OnDestroy {
if (!this.playing) {
if (this.mode === 'body') {
this.state.animationFrame = this.frame;
if (this.state.headAnimation) {
const headFrames = this.state.headAnimation.frames.length;
let headFrame = Math.floor(this.frame / this.state.animation.frames.length * headFrames);
headFrame = Math.min(headFrame, headFrames - 1);
this.state.headAnimationFrame = headFrame;
}
} else {
this.state.headAnimationFrame = this.frame;
}
@@ -459,9 +468,10 @@ export class ToolsAnimation implements OnInit, OnDestroy {
console.log(`shadow: [${shadow.map(x => `[${x.join(', ')}]`).join(', ')}]`);
}
} else {
const animation = toHeadAnimation(this.headAnimation, true);
const compressed = animation.frames.map(compressHeadFrame);
console.log(JSON.stringify(compressed));
const frames = this.headAnimation.frames
.map(f => [f.duration, '[' + compressHeadFrame(f).join(', ') + ']'])
.map(([repeat, frame]) => repeat > 1 ? `...repeat(${repeat}, ${frame})` : frame);
console.log(`frames: [\n${frames.map(x => `\t${x}`).join(',\n')}\n]`);
}
}
png(scale = 1) {
@@ -531,9 +541,11 @@ export class ToolsAnimation implements OnInit, OnDestroy {
if (this.playing) {
this.time += delta;
if (this.mode === 'body') {
const isBodyMode = this.mode === 'body';
if (isBodyMode) {
if (this.state.animation) {
const frame = this.time * this.state.animation.fps;
const frame = Math.floor(this.time * this.state.animation.fps);
if (frame > this.state.animation.frames.length && !this.state.animation.loop) {
this.bodyAnimationPlaying = (this.bodyAnimationPlaying + 1) % this.bodyAnimationsToPlay.length;
@@ -541,14 +553,15 @@ export class ToolsAnimation implements OnInit, OnDestroy {
this.state.animationFrame = 0;
this.time = 0;
} else {
this.state.animationFrame = Math.floor(frame) % this.state.animation.frames.length;
this.state.animationFrame = frame % this.state.animation.frames.length;
}
}
} else {
if (this.state.headAnimation) {
const frame = Math.floor(this.time * this.state.headAnimation.fps);
this.state.headAnimationFrame = frame % this.state.headAnimation.frames.length;
}
}
if (this.state.headAnimation) {
const fps = this.state.headAnimation.fps;
const frame = Math.floor(this.time * fps) + (isBodyMode && !this.state.headAnimation.loop ? fps : 0);
this.state.headAnimationFrame = frame % this.state.headAnimation.frames.length;
}
}
}
@@ -564,9 +577,10 @@ export class ToolsAnimation implements OnInit, OnDestroy {
return this.storage.getJSON<AnimationsData>('tools-animations', {});
}
private createAnimationSprites(scale: number) {
const isBodyMode = this.mode === 'body';
const animation = toBodyAnimation(this.bodyAnimation, true, this.switch);
const headAnimation = toHeadAnimation(this.headAnimation, true);
const frames = this.mode === 'body' ? animation.frames.length : headAnimation.frames.length;
const frames = isBodyMode ? animation.frames.length : headAnimation.frames.length;
const buffer = createCanvas(ponyWidth, ponyHeight);
const batch = new ContextSpriteBatch(buffer);
const info = toPalette(this.pony.info);
@@ -582,14 +596,23 @@ export class ToolsAnimation implements OnInit, OnDestroy {
const x = i % cols;
const y = Math.floor(i / cols);
let headFrame = 0;
if (isBodyMode) {
let animTime = i / animation.fps;
if (!headAnimation.loop) {
animTime += 1;
}
headFrame = Math.floor(animTime * headAnimation.fps);
}
batch.start(sprites.paletteSpriteSheet, 0);
drawPony(batch, info, {
...defaultPonyState(),
animation,
animationFrame: this.mode === 'body' ? i : 0,
headAnimation: this.mode === 'head' ? headAnimation : undefined,
headAnimationFrame: this.mode === 'head' ? i : 0,
animationFrame: isBodyMode ? i : 0,
headAnimation: headAnimation,
headAnimationFrame: isBodyMode ? headFrame : i,
blinkFrame: 1,
}, ponyWidth / 2, ponyHeight - 10, options);
@@ -696,7 +719,7 @@ function compressBodyFrame(f: BodyAnimationFrame): number[] {
], x => !x);
}
function fromHeadAnimation({ name, fps, loop, frames }: IHeadAnimation, index: number): HeadAnimation {
function fromHeadAnimation({ name, fps, loop, properties, frames }: IHeadAnimation, index: number): HeadAnimation {
const fs: HeadAnimationFrame[] = [];
frames.forEach(f => {
@@ -713,18 +736,30 @@ function fromHeadAnimation({ name, fps, loop, frames }: IHeadAnimation, index: n
builtin: true,
fps,
loop,
dontOpenEyes: hasFlag(properties, HeadAnimationProperties.DontIncreaseEyeOpenness),
dontCloseMouth: hasFlag(properties, HeadAnimationProperties.DontDecreaseMouthOpenness),
name: `# builtin ${index.toString().padStart(2, '0')} # ${name}`,
frames: fs,
};
}
function toHeadAnimation({ name, frames, fps, loop }: HeadAnimation, full: boolean): IHeadAnimation {
function toHeadAnimation({ name, frames, fps, loop, dontOpenEyes, dontCloseMouth }: HeadAnimation, full: boolean):
IHeadAnimation {
const fs = (full && !loop) ? repeat(fps, createDefaultHeadFrame()).concat(frames) : frames;
let properties = HeadAnimationProperties.None;
if (dontOpenEyes) {
properties |= HeadAnimationProperties.DontIncreaseEyeOpenness;
}
if (dontCloseMouth) {
properties |= HeadAnimationProperties.DontDecreaseMouthOpenness;
}
return {
name,
fps,
loop,
properties,
frames: flatMap(fs, f => repeat(full ? f.duration : 1, f)),
};
}
@@ -788,6 +823,7 @@ function fixHeadAnimation(a: HeadAnimation): HeadAnimation {
fps: a.fps || 24,
loop: a.loop || false,
lockEyes: a.lockEyes || false,
dontOpenEyes: a.dontOpenEyes || false,
frames: (a.frames || []).map(fixHeadFrame),
};
}
@@ -17,7 +17,7 @@ import { createCamera } from '../../../common/camera';
import { mockPaletteManager } from '../../../common/ponyInfo';
import { isCritter } from '../../../common/entityUtils';
import {
createAnEntity, cloud, pony, apple, apple2, orange, orange2, candy, gift1, gift2, appleGreen, appleGreen2
createAnEntity, cloud, pony, apple, apple2, orange, orange2, candy, gift1, gift2, appleGreen, appleGreen2, bunny
} from '../../../common/entities';
import { drawMap } from '../../../client/draw';
import { includes, observableToPromise, hasFlag } from '../../../common/utils';
@@ -142,7 +142,7 @@ function drawTheMap(canvas: HTMLCanvasElement, map: WorldMap, info: ToolsMapOthe
};
const ignoreTypes = [
cloud, pony, apple, apple2, appleGreen, appleGreen2, orange, orange2, candy, gift1, gift2
cloud, pony, apple, apple2, appleGreen, appleGreen2, orange, orange2, candy, gift1, gift2, bunny
].map(e => e.type);
const shouldDraw = (e: Entity) => {