1
+ // ==UserScript==
2
+ // @name gamemodels3d bypass
3
+ // @namespace k3rielit.freerobux
4
+ // @version 0.2
5
+ // @description try to take over the world!
6
+ // @author k3rielit
7
+ // @match *://*.gamemodels3d.com/*
8
+ // @icon https://www.google.com/s2/favicons?sz=64&domain=gamemodels3d.com
9
+ // @grant none
10
+ // @run -at document-start
11
+ // @updateURL https://github.com/k3rielit/scripts/raw/main/gamemodels3d/gm3dbypass.user.js
12
+ // @downloadURL https://github.com/k3rielit/scripts/raw/main/gamemodels3d/gm3dbypass.user.js
13
+ // ==/UserScript==
14
+
15
+ ( function ( ) {
16
+ 'use strict' ;
17
+
18
+ function loadScript ( type , src , stringContent ) {
19
+ return new Promise ( function ( resolve , reject ) {
20
+ var script = document . createElement ( 'script' ) ;
21
+ script . onload = function ( ) {
22
+ console . log ( `[loadScript] Success: ${ this . type } @ ${ this . src } ` ) ;
23
+ resolve ( ) ;
24
+ } ;
25
+ script . onerror = function ( ) {
26
+ console . error ( `[loadScript] Error: ${ this . type } @ ${ this . src } ` ) ;
27
+ reject ( ) ;
28
+ } ;
29
+ if ( type ) script . type = type ;
30
+ if ( src ) script . src = src ;
31
+ if ( stringContent ) script . text = stringContent ;
32
+ document . body . appendChild ( script ) ;
33
+ console . log ( script ) ;
34
+ } ) ;
35
+ }
36
+
37
+ function injectExporter ( ) {
38
+ window . VIEWER3D . Exporter = class Exporter {
39
+ constructor ( ) { }
40
+ parse ( model , format , name ) {
41
+ console . log ( `[VIEWER3D.Exporter] ${ name } .${ format } ` ) ;
42
+ console . log ( model ) ;
43
+ let exporter ;
44
+ const stlOptions = { binary : true } ;
45
+ switch ( format ) {
46
+
47
+ case 'drc' :
48
+ exporter = new window . DRACOExporter ( ) ; // never used, here for future updates
49
+ saveFile ( `${ name } .${ format } ` , exporter . parse ( model ) , 'application/octet-stream' ) ;
50
+ break ;
51
+
52
+ case 'gltf' :
53
+ exporter = new window . GLTFExporter ( ) ;
54
+ exporter . parse (
55
+ model ,
56
+ ( parsedModel ) => { console . log ( parsedModel ) ; saveFile ( `${ name } .${ format } ` , JSON . stringify ( parsedModel ) , 'application/json' ) } ,
57
+ exportErrorHandler
58
+ ) ;
59
+ break ;
60
+
61
+ case 'obj' :
62
+ exporter = new window . OBJExporter ( ) ;
63
+ saveFile ( `${ name } .${ format } ` , exporter . parse ( model ) , 'application/octet-stream' ) ;
64
+ break ;
65
+
66
+ case 'ply' :
67
+ exporter = new window . PLYExporter ( ) ; // never used, here for future updates
68
+ saveFile ( `${ name } .${ format } ` , exporter . parse ( model ) , 'application/octet-stream' ) ;
69
+ break ;
70
+
71
+ case 'stl' :
72
+ exporter = new window . STLExporter ( ) ;
73
+ saveFile ( `${ name } .${ format } ` , exporter . parse ( model , stlOptions ) , 'application/octet-stream' ) ;
74
+ break ;
75
+
76
+ default :
77
+ console . warn ( `[Exporter] Unknown format: ${ format } ` ) ;
78
+ break ;
79
+ }
80
+
81
+ }
82
+ }
83
+ }
84
+
85
+ function exportErrorHandler ( error ) {
86
+ console . error ( `[Exporter] Error: ${ error } ` ) ;
87
+ }
88
+
89
+ function saveFile ( filename , content , mimeType ) {
90
+ console . log ( 'saving xd' ) ;
91
+ const blob = new Blob ( [ content ] , { type : mimeType } ) ;
92
+ if ( window . navigator . msSaveOrOpenBlob ) {
93
+ window . navigator . msSaveBlob ( blob , filename ) ;
94
+ }
95
+ else {
96
+ const elem = window . document . createElement ( 'a' ) ;
97
+ elem . style . display = "none" ;
98
+ elem . href = window . URL . createObjectURL ( blob , { oneTimeOnly : true } ) ;
99
+ elem . download = filename ;
100
+ document . body . appendChild ( elem ) ;
101
+ elem . click ( ) ;
102
+ document . body . removeChild ( elem ) ;
103
+ }
104
+ }
105
+
106
+ function downloadGltf ( modelObject , fileName ) {
107
+ var dataString = 'data:text/json;charset=utf-8,' + encodeURIComponent ( JSON . stringify ( modelObject ) ) ;
108
+ var downloadNode = document . createElement ( 'a' ) ;
109
+ downloadNode . setAttribute ( 'href' , dataString ) ;
110
+ downloadNode . setAttribute ( 'download' , fileName ) ;
111
+ document . body . appendChild ( downloadNode ) ;
112
+ downloadNode . click ( ) ;
113
+ downloadNode . remove ( ) ;
114
+ }
115
+
116
+ // Inject three.js importmap and exporter addons
117
+ loadScript ( 'importmap' , null , `
118
+ {
119
+ "imports": {
120
+ "three": "https://unpkg.com/[email protected] /build/three.module.js",
121
+ "three/addons/": "https://unpkg.com/[email protected] /examples/jsm/"
122
+ }
123
+ }
124
+ ` ) ;
125
+
126
+ loadScript ( 'module' , null , `
127
+ import { DRACOExporter } from 'three/addons/exporters/DRACOExporter.js';
128
+ import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';
129
+ import { OBJExporter } from 'three/addons/exporters/OBJExporter.js';
130
+ import { PLYExporter } from 'three/addons/exporters/PLYExporter.js';
131
+ import { STLExporter } from 'three/addons/exporters/STLExporter.js';
132
+ window.DRACOExporter = DRACOExporter;
133
+ window.GLTFExporter = GLTFExporter;
134
+ window.OBJExporter = OBJExporter;
135
+ window.PLYExporter = PLYExporter;
136
+ window.STLExporter = STLExporter;
137
+ ` ) ;
138
+
139
+ // The 3d viewer only appears after navigating to its tab, wait for that, and inject the exporter
140
+ const downloadSelector = '#viewer3dContainer > div.viewer3d_controlPanel > div.right > img:nth-child(2)' ;
141
+ if ( document . querySelector ( downloadSelector ) ) {
142
+ console . log ( document . querySelector ( downloadSelector ) ) ;
143
+ injectExporter ( ) ;
144
+ }
145
+ const observer = new MutationObserver ( ( mutationList , observer ) => {
146
+ if ( document . querySelector ( downloadSelector ) ) {
147
+ console . log ( document . querySelector ( downloadSelector ) ) ;
148
+ observer . disconnect ( ) ;
149
+ injectExporter ( ) ;
150
+ }
151
+ } ) ;
152
+ observer . observe ( document . body , {
153
+ attributes : true , childList : true , subtree : true
154
+ } ) ;
155
+
156
+ } ) ( ) ;
0 commit comments