Skip to content

Commit b336313

Browse files
committed
2 parents ed4678c + ef5ab61 commit b336313

File tree

13 files changed

+246
-17
lines changed

13 files changed

+246
-17
lines changed

Diff for: source/backend/ClientPrefs.hx

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package backend;
22

3+
import options.VisualsUISubState;
34
import options.NotesSubState;
45
import online.network.FunkinNetwork;
56
import online.GameClient;
@@ -383,4 +384,15 @@ class ClientPrefs {
383384
CoolUtil.asta(GameClient.room.state.player2.arrowColorP3),
384385
];
385386
}
387+
388+
public static function getNoteSkin(player:Int = 0):String
389+
{
390+
if(!GameClient.isConnected() || NotesSubState.isOpened || VisualsUISubState.isOpened)
391+
return data.noteSkin;
392+
393+
if(player == 0)
394+
return GameClient.room.state.player1.noteSkin;
395+
else
396+
return GameClient.room.state.player2.noteSkin;
397+
}
386398
}

Diff for: source/backend/NoteSkinData.hx

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package backend;
2+
3+
import openfl.utils.Assets;
4+
5+
#if sys
6+
import sys.io.File;
7+
import sys.FileSystem;
8+
#end
9+
10+
class NoteSkinData {
11+
public static var noteSkins:Array<NoteSkinStructure> = [];
12+
public static var noteSkinArray:Array<String> = [];
13+
14+
public static function reloadNoteSkins()
15+
{
16+
noteSkins = [];
17+
noteSkinArray = [];
18+
19+
var directories:Array<Array<String>> = [[Paths.getLibraryPathForce('', 'shared'), '']];
20+
#if MODS_ALLOWED
21+
directories.push([Paths.mods(), '']);
22+
23+
for (mod in Mods.parseList().enabled)
24+
{
25+
if(Mods.getGlobalMods().contains(mod))
26+
directories.push([Paths.mods(mod + '/'), mod]);
27+
}
28+
#end
29+
30+
var skinsFinished:Array<String> = [];
31+
32+
for (i in 0...directories.length) {
33+
var directory:String = directories[i][0] + 'images/noteSkins/list.txt';
34+
35+
for (skin in CoolUtil.coolTextFile(directory)) {
36+
if(!noteSkinArray.contains(skin)) {
37+
noteSkins.push({
38+
skin: skin,
39+
folder: directories[i][1],
40+
url: online.mods.OnlineMods.getModURL(directories[i][1])
41+
});
42+
43+
noteSkinArray.push(skin);
44+
}
45+
}
46+
}
47+
48+
noteSkins.insert(0, {skin: ClientPrefs.defaultData.noteSkin, folder: ''}); //Default skin always comes first
49+
noteSkinArray.insert(0, ClientPrefs.defaultData.noteSkin);
50+
}
51+
52+
public static function getCurrent(?player:Int = 0):NoteSkinStructure
53+
{
54+
var toReturn:NoteSkinStructure = null;
55+
56+
if(player == -1)
57+
toReturn = NoteSkinData.noteSkins[NoteSkinData.noteSkinArray.indexOf(ClientPrefs.data.noteSkin)];
58+
else
59+
toReturn = NoteSkinData.noteSkins[NoteSkinData.noteSkinArray.indexOf(ClientPrefs.getNoteSkin(player))];
60+
61+
if(toReturn == null)
62+
toReturn = NoteSkinData.noteSkins[0];
63+
64+
return toReturn;
65+
}
66+
}
67+
68+
typedef NoteSkinStructure = {
69+
var skin:String;
70+
var folder:String;
71+
@:optional var url:String;
72+
}

Diff for: source/objects/Note.hx

+42-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package objects;
33
// If you want to make a custom note type, you should search for:
44
// "function set_noteType"
55

6+
import backend.NoteSkinData;
67
import online.GameClient;
78
import backend.NoteTypesConfig;
89
import shaders.RGBPalette;
@@ -37,7 +38,7 @@ class Note extends FlxSprite
3738
public var extraData:Map<String, Dynamic> = new Map<String, Dynamic>();
3839

3940
public var strumTime:Float = 0;
40-
public var mustPress:Bool = false;
41+
public var mustPress(default, set):Bool = false;
4142
public var noteData:Int = 0;
4243
public var canBeHit:Bool = false;
4344
public var tooLate:Bool = false;
@@ -317,8 +318,18 @@ class Note extends FlxSprite
317318
var skin:String = texture + postfix;
318319
if(texture.length < 1) {
319320
skin = PlayState.SONG != null ? PlayState.SONG.arrowSkin : null;
320-
if(skin == null || skin.length < 1)
321+
if(skin == null || skin.length < 1) {
321322
skin = defaultNoteSkin + postfix;
323+
324+
lastTexture = defaultNoteSkin;
325+
lastPostfix = postfix;
326+
} else {
327+
lastTexture = '';
328+
lastPostfix = '';
329+
}
330+
} else {
331+
lastTexture = texture;
332+
lastPostfix = postfix;
322333
}
323334

324335
var animName:String = null;
@@ -328,7 +339,7 @@ class Note extends FlxSprite
328339

329340
var skinPixel:String = skin;
330341
var lastScaleY:Float = scale.y;
331-
var skinPostfix:String = getNoteSkinPostfix();
342+
var skinPostfix:String = getNoteSkinPostfix(mustPress);
332343
var customSkin:String = skin + skinPostfix;
333344
var path:String = PlayState.isPixelStage ? 'pixelUI/' : '';
334345
if(customSkin == _lastValidChecked || Paths.fileExists('images/' + path + customSkin + '.png', IMAGE))
@@ -375,11 +386,12 @@ class Note extends FlxSprite
375386
animation.play(animName, true);
376387
}
377388

378-
public static function getNoteSkinPostfix()
389+
public static function getNoteSkinPostfix(?mustPress:Bool = true)
379390
{
380391
var skin:String = '';
381-
if(ClientPrefs.data.noteSkin != ClientPrefs.defaultData.noteSkin)
382-
skin = '-' + ClientPrefs.data.noteSkin.trim().toLowerCase().replace(' ', '_');
392+
var noteSkin:String = NoteSkinData.getCurrent(!GameClient.room?.state?.swagSides ?? false ? (mustPress ? 1 : 0) : (mustPress ? 0 : 1)).skin;
393+
if(noteSkin != ClientPrefs.defaultData.noteSkin)
394+
skin = '-' + noteSkin.trim().toLowerCase().replace(' ', '_');
383395
return skin;
384396
}
385397

@@ -553,4 +565,28 @@ class Note extends FlxSprite
553565
@:unreflective public var noteAlpha(get, set):Float;
554566
@:unreflective function get_noteAlpha():Float { return alpha; }
555567
@:unreflective function set_noteAlpha(value:Float):Float { return super.set_alpha(value); }
568+
569+
var lastTexture:String = '';
570+
var lastPostfix:String = '';
571+
function set_mustPress(value:Bool):Bool
572+
{
573+
mustPress = value;
574+
reloadNote(lastTexture, lastPostfix); // workaround for player related things
575+
576+
if (isSustainNote) {
577+
var animBefore:String = animation.curAnim.name;
578+
579+
animation.play(colArray[noteData % colArray.length] + 'Scroll');
580+
offsetX = width / 2;
581+
582+
animation.play(animBefore);
583+
updateHitbox();
584+
offsetX -= width / 2;
585+
586+
if (PlayState.isPixelStage)
587+
offsetX += 30;
588+
}
589+
590+
return value;
591+
}
556592
}

Diff for: source/objects/NoteSplash.hx

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package objects;
22

3+
import online.GameClient;
34
import shaders.RGBPalette;
45
import flixel.system.FlxAssets.FlxShader;
56
import flixel.graphics.frames.FlxFrame;

Diff for: source/objects/StrumNote.hx

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package objects;
33
import online.GameClient;
44
import shaders.RGBPalette;
55
import shaders.RGBPalette.RGBShaderReference;
6+
import backend.NoteSkinData;
67

78
class StrumNote extends FlxSprite
89
{
@@ -52,7 +53,7 @@ class StrumNote extends FlxSprite
5253
if(PlayState.SONG != null && PlayState.SONG.arrowSkin != null && PlayState.SONG.arrowSkin.length > 1) skin = PlayState.SONG.arrowSkin;
5354
else skin = Note.defaultNoteSkin;
5455

55-
var customSkin:String = skin + Note.getNoteSkinPostfix();
56+
var customSkin:String = skin + Note.getNoteSkinPostfix(player == 1);
5657
if(Paths.fileExists('images/$customSkin.png', IMAGE)) skin = customSkin;
5758

5859
texture = skin; //Load texture and anims

Diff for: source/online/GameClient.hx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package online;
22

3+
import backend.NoteSkinData;
34
import flixel.FlxState;
45
import online.network.Auth;
56
import online.network.FunkinNetwork;
@@ -51,7 +52,7 @@ class GameClient {
5152
}, (exc) -> {
5253
onJoin(exc);
5354
LoadingScreen.toggle(false);
54-
Alert.alert("Failed to connect!", exc.toString());
55+
Alert.alert("Failed to connect!", exc.details());
5556
});
5657
}
5758

@@ -200,6 +201,11 @@ class GameClient {
200201
options.set("skinURL", OnlineMods.getModURL(ClientPrefs.data.modSkin[0]));
201202
}
202203

204+
var data:NoteSkinStructure = NoteSkinData.getCurrent(-1);
205+
options.set('noteSkin', data.skin);
206+
options.set('noteSkinMod', data.folder);
207+
options.set('noteSkinURL', data.url);
208+
203209
// if (asHost) {
204210
// options.set("gameplaySettings", ClientPrefs.data.gameplaySettings);
205211
// }

Diff for: source/online/backend/schema/Player.hx

+9
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ class Player extends Schema {
7474
@:type("boolean")
7575
public var verified:Bool = false;
7676

77+
@:type("string")
78+
public var noteSkin:String = null;
79+
80+
@:type("string")
81+
public var noteSkinMod:String = null;
82+
83+
@:type("string")
84+
public var noteSkinURL:String = null;
85+
7786
@:type("array", "number")
7887
public var arrowColor0:ArraySchema<Dynamic> = new ArraySchema<Dynamic>();
7988

Diff for: source/online/objects/ChatBox.hx

+38-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class ChatBox extends FlxTypedSpriteGroup<FlxSprite> {
4040
var onCommand:(String, Array<String>) -> Bool;
4141

4242
static var lastMessages:Array<Dynamic> = [];
43+
var dwnMsgToClick:Map<NoteSkinDownloadMessage, ()->Void> = new Map<NoteSkinDownloadMessage, ()->Void>();
4344

4445
var initMessage:String = "See /help for the list of commands!";
4546

@@ -59,6 +60,19 @@ class ChatBox extends FlxTypedSpriteGroup<FlxSprite> {
5960
}
6061
}
6162

63+
public function addNoteSkinDownloadMessage(onClick:()->Void) {
64+
instance.targetAlpha = 5;
65+
66+
var chat = new NoteSkinDownloadMessage(instance.bg.width);
67+
instance.chatGroup.insert(0, chat);
68+
69+
dwnMsgToClick.set(chat, onClick);
70+
71+
if (instance.chatGroup.length >= 22) {
72+
instance.chatGroup.remove(instance.chatGroup.members[instance.chatGroup.length - 1], true);
73+
}
74+
}
75+
6276
public static function clearLogs() {
6377
if (instance?.chatGroup != null)
6478
instance.chatGroup.clear();
@@ -188,9 +202,17 @@ class ChatBox extends FlxTypedSpriteGroup<FlxSprite> {
188202
msg.alpha = 0.8;
189203
if (msg != null && FlxG.mouse.visible && FlxG.mouse.overlaps(msg, camera)) {
190204
msg.alpha = 1;
191-
if (FlxG.mouse.justPressed && msg.link != null) {
192-
focused = false;
193-
RequestSubstate.requestURL(msg.link);
205+
if (FlxG.mouse.justPressed) {
206+
if(msg.link != null) {
207+
focused = false;
208+
RequestSubstate.requestURL(msg.link);
209+
}
210+
else if(Std.isOfType(msg, NoteSkinDownloadMessage)) {
211+
var func = dwnMsgToClick.get(cast msg);
212+
213+
if(func != null)
214+
func();
215+
}
194216
}
195217
}
196218
if (!focused) {
@@ -292,4 +314,17 @@ class ChatMessage extends FlxText {
292314
if (link != null)
293315
addFormat(new FlxTextFormat(FlxColor.CYAN), formatBeg, formatEnd);
294316
}
317+
}
318+
319+
class NoteSkinDownloadMessage extends ChatMessage {
320+
static final MESSAGE:String = "There's an opponent note skin available! Click here to download it.";
321+
static final DOWNLOAD_MSG_PART:String = 'Click here to download it.';
322+
323+
public function new(fieldWidth:Float = 0) {
324+
super(fieldWidth, {content: MESSAGE, hue: null});
325+
326+
var startIndex:Int = MESSAGE.indexOf(DOWNLOAD_MSG_PART);
327+
var endIndex:Int = startIndex + DOWNLOAD_MSG_PART.length;
328+
addFormat(new FlxTextFormat(FlxColor.CYAN), startIndex, endIndex);
329+
}
295330
}

Diff for: source/online/states/RoomState.hx

+39
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import backend.WeekData;
1919
import backend.Song;
2020
import haxe.crypto.Md5;
2121
import states.FreeplayState;
22+
import states.ModsMenuState;
2223
import openfl.utils.Assets as OpenFlAssets;
2324

2425
@:build(lumod.LuaScriptClass.build())
@@ -196,9 +197,26 @@ class RoomState extends MusicBeatState {
196197
});
197198
});
198199

200+
GameClient.room.state.player1.listen("noteSkin", (value, prev) -> {
201+
if (value == prev)
202+
return;
203+
Waiter.put(() -> {
204+
checkNoteSkin(true);
205+
});
206+
});
207+
208+
GameClient.room.state.player2.listen("noteSkin", (value, prev) -> {
209+
if (value == prev)
210+
return;
211+
Waiter.put(() -> {
212+
checkNoteSkin(false);
213+
});
214+
});
215+
199216
GameClient.room.state.gameplaySettings.onChange((o, n) -> {
200217
FreeplayState.updateFreeplayMusicPitch();
201218
});
219+
202220
}
203221

204222
override function destroy() {
@@ -474,6 +492,9 @@ class RoomState extends MusicBeatState {
474492
verifyDownloadMod(false, true);
475493
checkStage();
476494

495+
checkNoteSkin(true);
496+
checkNoteSkin(false);
497+
477498
if (stage != null)
478499
stage.createPost();
479500

@@ -607,6 +628,24 @@ class RoomState extends MusicBeatState {
607628
}
608629
}
609630

631+
function checkNoteSkin(isP1:Bool, ?manualDownload:Bool = false) {
632+
var player = isP1 ? GameClient.room.state.player1 : GameClient.room.state.player2;
633+
634+
if (!FileSystem.exists(Paths.mods(player.noteSkinMod)) && player.noteSkinURL != null) {
635+
OnlineMods.downloadMod(player.noteSkinURL, manualDownload, function(_) {
636+
Mods.updatedOnState = false;
637+
Mods.parseList();
638+
Mods.pushGlobalMods();
639+
});
640+
641+
if(!manualDownload && ClientPrefs.data.disableAutoDownloads) {
642+
chatBox.addNoteSkinDownloadMessage(function() {
643+
checkNoteSkin(isP1, true);
644+
});
645+
}
646+
}
647+
}
648+
610649
override function openSubState(obj:FlxSubState) {
611650
obj.cameras = [camHUD];
612651
super.openSubState(obj);

0 commit comments

Comments
 (0)