Commit 7d71f787 authored by Friends233's avatar Friends233

外部通信

parent 6ce3a256
...@@ -581,7 +581,7 @@ ...@@ -581,7 +581,7 @@
"_is3DNode": false, "_is3DNode": false,
"_groupIndex": 0, "_groupIndex": 0,
"groupIndex": 0, "groupIndex": 0,
"_id": "07ZQOj+O5DupSUzq6wJ1x1" "_id": "15/k8hSCpMn5yTkRNsd7E6"
}, },
{ {
"__type__": "cc.Sprite", "__type__": "cc.Sprite",
...@@ -611,7 +611,7 @@ ...@@ -611,7 +611,7 @@
"_fillRange": 0, "_fillRange": 0,
"_isTrimmedMode": true, "_isTrimmedMode": true,
"_atlas": null, "_atlas": null,
"_id": "0djeEpGbJNXrPz0cbF9Itp" "_id": "85fZTJn5FPIodAbSeEnovO"
}, },
{ {
"__type__": "7c5ffhlHDpBpoDQ8wfKN7pu", "__type__": "7c5ffhlHDpBpoDQ8wfKN7pu",
...@@ -764,7 +764,7 @@ ...@@ -764,7 +764,7 @@
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
-152, -167,
392.553, 392.553,
0, 0,
0, 0,
...@@ -2349,7 +2349,7 @@ ...@@ -2349,7 +2349,7 @@
"_is3DNode": false, "_is3DNode": false,
"_groupIndex": 0, "_groupIndex": 0,
"groupIndex": 0, "groupIndex": 0,
"_id": "14FuV4E4pKcJXoee/woO9W" "_id": "beEXxWtEdHO733goHkm2rf"
}, },
{ {
"__type__": "cc.Sprite", "__type__": "cc.Sprite",
...@@ -2379,7 +2379,7 @@ ...@@ -2379,7 +2379,7 @@
"_fillRange": 0, "_fillRange": 0,
"_isTrimmedMode": true, "_isTrimmedMode": true,
"_atlas": null, "_atlas": null,
"_id": "1dmEUoDDFGSr1H3zBl57qz" "_id": "dazdKb2qVJKo9zqBV0DE+R"
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
...@@ -2441,7 +2441,7 @@ ...@@ -2441,7 +2441,7 @@
"_is3DNode": false, "_is3DNode": false,
"_groupIndex": 0, "_groupIndex": 0,
"groupIndex": 0, "groupIndex": 0,
"_id": "4cuxTEbehCsJYSCSHpIpH/" "_id": "94CD8dim1Js7UBKY999Q4K"
}, },
{ {
"__type__": "cc.Sprite", "__type__": "cc.Sprite",
...@@ -2471,7 +2471,7 @@ ...@@ -2471,7 +2471,7 @@
"_fillRange": 0, "_fillRange": 0,
"_isTrimmedMode": true, "_isTrimmedMode": true,
"_atlas": null, "_atlas": null,
"_id": "cdmDsSacRKg6pcDEshTXfh" "_id": "27JbCZHIFL+p6Vx9wQ+Bi2"
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
...@@ -2533,7 +2533,7 @@ ...@@ -2533,7 +2533,7 @@
"_is3DNode": false, "_is3DNode": false,
"_groupIndex": 0, "_groupIndex": 0,
"groupIndex": 0, "groupIndex": 0,
"_id": "3aOKea3k9BY4pPb9dmlQDV" "_id": "aeiL0lx2FCb4TTXLUMToJp"
}, },
{ {
"__type__": "cc.Sprite", "__type__": "cc.Sprite",
...@@ -2563,7 +2563,7 @@ ...@@ -2563,7 +2563,7 @@
"_fillRange": 0, "_fillRange": 0,
"_isTrimmedMode": true, "_isTrimmedMode": true,
"_atlas": null, "_atlas": null,
"_id": "23LPXn1BRFiItlEoT0OOmm" "_id": "acy/c1iY5ABqNDyUzVA1Ap"
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
...@@ -2625,7 +2625,7 @@ ...@@ -2625,7 +2625,7 @@
"_is3DNode": false, "_is3DNode": false,
"_groupIndex": 0, "_groupIndex": 0,
"groupIndex": 0, "groupIndex": 0,
"_id": "5biWgPGa9LWIggHPTmoumk" "_id": "4fWrjhYktAbJDUsbUd/8Zf"
}, },
{ {
"__type__": "cc.Sprite", "__type__": "cc.Sprite",
...@@ -2655,7 +2655,7 @@ ...@@ -2655,7 +2655,7 @@
"_fillRange": 0, "_fillRange": 0,
"_isTrimmedMode": true, "_isTrimmedMode": true,
"_atlas": null, "_atlas": null,
"_id": "6aX2V3JMlN26khZTAyTodl" "_id": "04cmGQjnJPVICj9Vbp0rHJ"
}, },
{ {
"__type__": "7c5ffhlHDpBpoDQ8wfKN7pu", "__type__": "7c5ffhlHDpBpoDQ8wfKN7pu",
...@@ -3009,13 +3009,13 @@ ...@@ -3009,13 +3009,13 @@
"tag": 0, "tag": 0,
"_offset": { "_offset": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
"x": -1, "x": 0.9,
"y": -116.2 "y": -122.9
}, },
"_size": { "_size": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 28.4, "width": 41.4,
"height": 54 "height": 29.7
}, },
"_id": "00DUR/4UFGJZyF3VRt2QCn" "_id": "00DUR/4UFGJZyF3VRt2QCn"
}, },
...@@ -3229,8 +3229,8 @@ ...@@ -3229,8 +3229,8 @@
], ],
"_srcBlendFactor": 770, "_srcBlendFactor": 770,
"_dstBlendFactor": 771, "_dstBlendFactor": 771,
"_string": "第关", "_string": "第关",
"_N$string": "第关", "_N$string": "第关",
"_fontSize": 22, "_fontSize": 22,
"_lineHeight": 22, "_lineHeight": 22,
"_enableWrapText": true, "_enableWrapText": true,
...@@ -3583,8 +3583,8 @@ ...@@ -3583,8 +3583,8 @@
], ],
"_srcBlendFactor": 770, "_srcBlendFactor": 770,
"_dstBlendFactor": 771, "_dstBlendFactor": 771,
"_string": "3/5", "_string": "0/3",
"_N$string": "3/5", "_N$string": "0/3",
"_fontSize": 24, "_fontSize": 24,
"_lineHeight": 24, "_lineHeight": 24,
"_enableWrapText": true, "_enableWrapText": true,
......
/** 关卡信息 */ /** 关卡信息 */
export const LevelInfo = [ export const LevelInfo = [
{ level: 1, countDown: 30, colors: ['#EC5F33', '#E52800', '#CA1D00'] } { level: 1, colors: ['#EC5F33', '#E52800', '#CA1D00'] }
{ level: 2, countDown: 30, colors: ['#FF9400', '#FF6C00', '#EC5F33', '#E52800', '#CA1D00'] } { level: 2, colors: ['#FF9400', '#FF6C00', '#EC5F33', '#E52800', '#CA1D00'] }
{ level: 3, countDown: 30, colors: ['#FFD34A', '#FFC300', '#FFB637', '#FF9400', '#FF6C00', '#EC5F33', '#E52800', '#CA1D00'] } { level: 3, colors: ['#FFD34A', '#FFC300', '#FFB637', '#FF9400', '#FF6C00', '#EC5F33', '#E52800', '#CA1D00'] }
] ]
export const CUSTOM_EVENT = { export const CUSTOM_EVENT = {
/** 爪子动画结束的回调 */ /** 爪子动画结束的回调 */
CLIP_ANI_END: 'CLIP_ANI_END', CLIP_ANI_END: 'CLIP_ANI_END',
/** 爪子碰撞 */ /** 爪子碰撞 */
CLIP_COLLISION: 'CLIP_COLLISION' CLIP_COLLISION: 'CLIP_COLLISION',
/** 游戏结束 */
GAME_OVER: 'GAME_OVER',
/** 下一关 */
NEXT_LEVEL: 'NEXT_LEVEL',
/** 过关 */
PASS_LEVEL: 'PASS_LEVEL',
/** 开始游戏 */
GAME_START: 'GAME_START'
} }
export const Config = { export const Config = {
...@@ -34,6 +42,9 @@ export const Config = { ...@@ -34,6 +42,9 @@ export const Config = {
/** 普通道具每种最多生成数量 */ /** 普通道具每种最多生成数量 */
propsNum: 2, propsNum: 2,
/** 每关的游戏时间 */
countDowns: [30, 30, 30]
/** 道具分布图 4*3 */ /** 道具分布图 4*3 */
propsMap: [ propsMap: [
[ [
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
// - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html // - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html
import { CUSTOM_EVENT, Config, LevelInfo } from "./Config/GameConfig"; import { CUSTOM_EVENT, Config, LevelInfo } from "./Config/GameConfig";
import exportEvent from "./exportEvent";
import { getProbability, getRandomArrayElements, loadGameResources, numToChinese, randomNum, set16ToRgb } from "./utils"; import { getProbability, getRandomArrayElements, loadGameResources, numToChinese, randomNum, set16ToRgb } from "./utils";
const { ccclass, property } = cc._decorator; const { ccclass, property } = cc._decorator;
...@@ -70,8 +71,11 @@ export default class GameScene extends cc.Component { ...@@ -70,8 +71,11 @@ export default class GameScene extends cc.Component {
/** 场面上剩余加分道具数量 */ /** 场面上剩余加分道具数量 */
surplusStar = Config.bestPropsNum surplusStar = Config.bestPropsNum
/** 游戏配置 */
gameConfig = {...Config}
protected onLoad(): void { protected onLoad(): void {
// loadGameResources() loadGameResources()
/** 开启碰撞检测 */ /** 开启碰撞检测 */
const cm = cc.director.getCollisionManager() const cm = cc.director.getCollisionManager()
cm.enabled = true cm.enabled = true
...@@ -81,21 +85,25 @@ export default class GameScene extends cc.Component { ...@@ -81,21 +85,25 @@ export default class GameScene extends cc.Component {
start() { start() {
this.clip = cc.find('clipMask/clipWrp/clip', this.node) this.clip = cc.find('clipMask/clipWrp/clip', this.node)
this.resetConfig()
this.refreshLevelInfo()
this.refreshStageProps()
this.addNodeEvent() this.addNodeEvent()
} }
/** 重置游戏设置 */ /**
resetConfig() { * 重置游戏配置
this.clipSpeed = Config.normalPropSpeed * @param con 游戏配置
this.surplusStar = Config.bestPropsNum */
this.clip.getChildByName('line').height = Config.maxLong resetConfig(con={}) {
this.gameConfig = {
...Config,
...con
}
this.clipSpeed = this.gameConfig.normalPropSpeed
this.surplusStar = this.gameConfig.bestPropsNum
this.clip.getChildByName('line').height = this.gameConfig.maxLong
const rotationAni = cc.find('clipMask/clipWrp', this.node) const rotationAni = cc.find('clipMask/clipWrp', this.node)
.getComponent(cc.Animation) .getComponent(cc.Animation)
.getAnimationState('clipRation') .getAnimationState('clipRation')
rotationAni.speed = Config.rotationSpeed rotationAni.speed = this.gameConfig.rotationSpeed
} }
/** 爪子碰撞事件 */ /** 爪子碰撞事件 */
...@@ -103,7 +111,7 @@ export default class GameScene extends cc.Component { ...@@ -103,7 +111,7 @@ export default class GameScene extends cc.Component {
const other: cc.Collider = detail.other const other: cc.Collider = detail.other
this.clipTarget = other.node this.clipTarget = other.node
this.clipSpeed = other.tag == 1 ? Config.bestPropSpeed : Config.normalPropSpeed this.clipSpeed = other.tag == 1 ? this.gameConfig.bestPropSpeed : this.gameConfig.normalPropSpeed
this.setClipState(CLIP_STATE.STOP) this.setClipState(CLIP_STATE.STOP)
} }
...@@ -113,6 +121,13 @@ export default class GameScene extends cc.Component { ...@@ -113,6 +121,13 @@ export default class GameScene extends cc.Component {
gameBtn.on(cc.Node.EventType.TOUCH_END, this.playGame, this) gameBtn.on(cc.Node.EventType.TOUCH_END, this.playGame, this)
this.node.on(CUSTOM_EVENT.CLIP_ANI_END, this.onAnimCompleted, this) this.node.on(CUSTOM_EVENT.CLIP_ANI_END, this.onAnimCompleted, this)
this.node.on(CUSTOM_EVENT.CLIP_COLLISION, this.onCollEnter, this) this.node.on(CUSTOM_EVENT.CLIP_COLLISION, this.onCollEnter, this)
exportEvent.on(CUSTOM_EVENT.NEXT_LEVEL,this.nextLevel,this)
exportEvent.on(CUSTOM_EVENT.GAME_START,(config) => {
this.resetConfig(config)
this.refreshLevelInfo()
this.refreshStageProps()
},this)
// TODO 测试用 // TODO 测试用
const href = window?.location?.href const href = window?.location?.href
const isTest = href?.includes('duibadev') || href?.includes('duibatest') || href?.includes('localhost') const isTest = href?.includes('duibadev') || href?.includes('duibatest') || href?.includes('localhost')
...@@ -122,7 +137,6 @@ export default class GameScene extends cc.Component { ...@@ -122,7 +137,6 @@ export default class GameScene extends cc.Component {
const testEventMap = { const testEventMap = {
next: 'nextLevel', next: 'nextLevel',
refreshProp: 'refreshStageProps', refreshProp: 'refreshStageProps',
addTime: 'addTime'
} }
testNode.children.forEach((n) => { testNode.children.forEach((n) => {
const event = this?.[testEventMap[n.name]] const event = this?.[testEventMap[n.name]]
...@@ -192,6 +206,10 @@ export default class GameScene extends cc.Component { ...@@ -192,6 +206,10 @@ export default class GameScene extends cc.Component {
this.isGameOver = true this.isGameOver = true
this.setClipState(CLIP_STATE.GAME_OVER) this.setClipState(CLIP_STATE.GAME_OVER)
this.unschedule(this.startCd) this.unschedule(this.startCd)
exportEvent.fire(CUSTOM_EVENT.GAME_OVER,{
score:this.starNum,
level:this.actLevel
})
} }
/** /**
...@@ -207,7 +225,6 @@ export default class GameScene extends cc.Component { ...@@ -207,7 +225,6 @@ export default class GameScene extends cc.Component {
const cd = this.countDown - 1 || 0 const cd = this.countDown - 1 || 0
if (!cd || cd <= 0) { if (!cd || cd <= 0) {
this.setLable('cdIcon/cd', `0s`) this.setLable('cdIcon/cd', `0s`)
console.log('倒计时结束')
this.gameOver() this.gameOver()
this.unschedule(this.startCd) this.unschedule(this.startCd)
return return
...@@ -227,7 +244,7 @@ export default class GameScene extends cc.Component { ...@@ -227,7 +244,7 @@ export default class GameScene extends cc.Component {
this.starNum = 0 this.starNum = 0
this.levelObjectives = LevelInfo[level].colors.length this.levelObjectives = LevelInfo[level].colors.length
this.actLevelInfo = LevelInfo[level] this.actLevelInfo = LevelInfo[level]
this.countDown = this.actLevelInfo.countDown this.countDown = this.gameConfig.countDowns[level] || 0
this.setLable('levelName', `第${numToChinese(level + 1)}关`) this.setLable('levelName', `第${numToChinese(level + 1)}关`)
this.setLable('starIcon/starProc', `${this.starNum}/${this.levelObjectives}`) this.setLable('starIcon/starProc', `${this.starNum}/${this.levelObjectives}`)
...@@ -255,7 +272,11 @@ export default class GameScene extends cc.Component { ...@@ -255,7 +272,11 @@ export default class GameScene extends cc.Component {
this.setLable('starIcon/starProc', `${this.starNum}/${this.levelObjectives}`) this.setLable('starIcon/starProc', `${this.starNum}/${this.levelObjectives}`)
// 达到目标 // 达到目标
if (this.starNum >= this.levelObjectives) { if (this.starNum >= this.levelObjectives) {
this.nextLevel() exportEvent.fire(CUSTOM_EVENT.PASS_LEVEL,{
score:this.starNum,
level:this.actLevel
})
// this.nextLevel()
} }
} }
...@@ -282,14 +303,14 @@ export default class GameScene extends cc.Component { ...@@ -282,14 +303,14 @@ export default class GameScene extends cc.Component {
/** 刷新舞台道具 */ /** 刷新舞台道具 */
refreshStageProps() { refreshStageProps() {
this.surplusStar = Config.bestPropsNum this.surplusStar = this.gameConfig.bestPropsNum
const gameStage = cc.find('gameStage', this.node) const gameStage = cc.find('gameStage', this.node)
const stageProps: cc.Node[] = gameStage.children const stageProps: cc.Node[] = gameStage.children
const mapIdx = Math.floor(randomNum(0, Config.propsMap.length)) const mapIdx = Math.floor(randomNum(0, this.gameConfig.propsMap.length))
const stageMap: number[] = [...Config.propsMap[mapIdx]] const stageMap: number[] = [...this.gameConfig.propsMap[mapIdx]]
// 生成加分道具 // 生成加分道具
for (let i = 0; i < Config.bestPropsNum; i++) { for (let i = 0; i < this.gameConfig.bestPropsNum; i++) {
// 随机取 // 随机取
let idx = Math.floor(randomNum(0, stageMap.length)) let idx = Math.floor(randomNum(0, stageMap.length))
...@@ -300,7 +321,7 @@ export default class GameScene extends cc.Component { ...@@ -300,7 +321,7 @@ export default class GameScene extends cc.Component {
} }
// 随机道具池 // 随机道具池
let propsRandom = [] let propsRandom = []
for (let i = 0; i < Config.propsNum; i++) { for (let i = 0; i < this.gameConfig.propsNum; i++) {
propsRandom.push(...this.propItem) propsRandom.push(...this.propItem)
} }
// 剩余格子数量 // 剩余格子数量
...@@ -341,7 +362,7 @@ export default class GameScene extends cc.Component { ...@@ -341,7 +362,7 @@ export default class GameScene extends cc.Component {
// 锚点跟爪子之间的大致距离 // 锚点跟爪子之间的大致距离
const offset = 41 const offset = 41
const maxLong = Config.maxLong - offset const maxLong = this.gameConfig.maxLong - offset
// 爪子出手 // 爪子出手
if (this.clipState == CLIP_STATE.PLAY) { if (this.clipState == CLIP_STATE.PLAY) {
...@@ -349,14 +370,14 @@ export default class GameScene extends cc.Component { ...@@ -349,14 +370,14 @@ export default class GameScene extends cc.Component {
this.setClipState(CLIP_STATE.STOP) this.setClipState(CLIP_STATE.STOP)
return return
} }
this.clip.y -= dt * Config.playSpeed this.clip.y -= dt * this.gameConfig.playSpeed
} }
// 爪子回收 // 爪子回收
if (this.clipState == CLIP_STATE.STOP) { if (this.clipState == CLIP_STATE.STOP) {
if (this.clip.y >= -offset) { if (this.clip.y >= -offset) {
// 恢复初始速度 // 恢复初始速度
this.clipSpeed = Config.normalPropSpeed this.clipSpeed = this.gameConfig.normalPropSpeed
this.setClipState(CLIP_STATE.DEFAULT) this.setClipState(CLIP_STATE.DEFAULT)
return return
} }
......
class EventObject {
public type: string;
public target: EventCenterClass;
public detail: Object;
public timeStamp: Number;
constructor(type: string, target: EventCenterClass, detail: Object) {
this.type = type;
this.target = target;
this.detail = detail;
this.timeStamp = +new Date();
}
}
interface EventNameObj {
type: string;
};
type EventName = string | EventNameObj;
export class EventCenterClass {
private _listeners: Object
constructor() {
this._listeners = {}
}
/**
* 增加一个事件监听。
* @param type - 要监听的事件类型。
* @param listener - 事件监听回调函数。
* @param context - 上下文
* @param once - 是否是一次性监听,即回调函数响应一次后即删除,不再响应。
* @returns - 对象本身。链式调用支持。
*/
on<T>(type: string, listener: Function, context: T, once: boolean) {
let listeners: any;
listeners = (this._listeners = this._listeners || {});
const eventListeners = (listeners[type] = listeners[type] || []);
for (let i = 0, len = eventListeners.length; i < len; i++) {
const el = eventListeners[i];
if (el.listener === listener) return;
}
eventListeners.push({ listener, context, once });
return this;
}
/**
* 删除一个事件监听。如果不传入任何参数,则删除所有的事件监听;如果不传入第二个参数,则删除指定类型的所有事件监听。
* @param type - 要删除监听的事件类型。
* @param listener - 要删除监听的回调函数。
* @returns - 对象本身。链式调用支持。
*/
off(type: string, listener: Function) {
let listeners: any;
listeners = (this._listeners = this._listeners || {});
// remove all event listeners
if (arguments.length == 0) {
listeners = null;
return this;
}
const eventListeners = listeners && listeners[type];
if (eventListeners) {
// remove event listeners by specified type
if (arguments.length == 1) {
delete listeners[type];
return this;
}
for (let i = 0, len = eventListeners.length; i < len; i++) {
const el = eventListeners[i];
if (el.listener === listener) {
eventListeners.splice(i, 1);
if (eventListeners.length === 0) delete listeners[type];
break;
}
}
}
return this;
}
/**
* 发送事件。当第一个参数类型为Object时,则把它作为一个整体事件对象。
* @param type - 要发送的事件类型。
* @param detail - 要发送的事件的具体信息,即事件随带参数。
* @returns - 是否成功调度事件。
*/
fire(type: EventName, detail?: Object) {
let event;
let eventType;
if (typeof type === 'string') {
eventType = type;
} else {
event = type;
eventType = type.type;
}
const listeners: any = this._listeners;
if (!listeners) return false;
const eventListeners: any = listeners[eventType];
if (eventListeners) {
const eventListenersCopy = eventListeners.slice(0);
event = event || new EventObject(eventType, this, detail);
for (let i = 0; i < eventListenersCopy.length; i++) {
const el = eventListenersCopy[i];
el.listener.call(el.context, event);
if (el.once) {
const index = eventListeners.indexOf(el);
if (index > -1) {
eventListeners.splice(index, 1);
}
}
}
if (eventListeners.length == 0) delete listeners[eventType];
return true;
}
return false;
}
}
let exportEvent = new EventCenterClass()
export default exportEvent;
\ No newline at end of file
{
"ver": "1.1.0",
"uuid": "d252bfc3-9abd-472c-b0b7-93ce4bbdd2f9",
"importer": "typescript",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
"author": "爱德 <caoxingru@duiba.com.cn>", "author": "爱德 <caoxingru@duiba.com.cn>",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@duiba/event-bus": "^1.0.0",
"ali-oss": "^6.17.1", "ali-oss": "^6.17.1",
"chokidar": "^3.5.3", "chokidar": "^3.5.3",
"co": "^4.6.0", "co": "^4.6.0",
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
# yarn lockfile v1 # yarn lockfile v1
"@duiba/event-bus@^1.0.0":
version "1.0.0"
resolved "http://npm.dui88.com:80/@duiba%2fevent-bus/-/event-bus-1.0.0.tgz#dad13916893742ed6082ec3f6d17852e25ad7007"
integrity sha512-AHWKWw9gnXQUj/ar/MHeAhiSUCYZa8ii0FWmqOyAIengeTg6ILNtKjyanB6uH1BHKX7UMOYZETc1BiLbjq1jkw==
"@tootallnate/once@1": "@tootallnate/once@1":
version "1.1.2" version "1.1.2"
resolved "http://npm.dui88.com:80/@tootallnate%2fonce/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" resolved "http://npm.dui88.com:80/@tootallnate%2fonce/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment